x
Solved

# Accessing char[][]?

Posted on 2004-09-12
Medium Priority
291 Views
Hello,

I have a char array declared array[15][20];

And choose a random postion in the array, using int index = rand() % 300; Meaning 15*20.

Is the any appraoch to convert the index value in a two int variables to access the array[row][column];

Thanks
0
Question by:EmailSurfer
• 7
• 7
• 2
• +2

LVL 11

Expert Comment

ID: 12039140
Well, the positiion 99 would be 4 * 20 + 19 = array[4][19]

Looks like array[index / 20][index % 20] should work.

-bcl
0

Author Comment

ID: 12039203
Thanks I'll try this.

I just wondered if I should be using index = rand() % 298, rather than 300.

The array is declared as char array[15][20];

0

Author Comment

ID: 12039213

I meant should the end postiions be taken into account?

Thanks
0

LVL 39

Expert Comment

ID: 12039531
>>>> looks like array[index / 20][index % 20] should work.

yes, but

((char*)array)[index]

would do the same.

>>>> I just wondered if I should be using index = rand() % 298

No, rand()%300 gives numbers in the range of 0 to 299. That's exactly char array[15][20] or char array[300];

Regards, Alex

0

Author Comment

ID: 12039786

I wondered if I could also ask?

My program uses the rand() function to choose a postion in the array. Though I found the positions choosen seem close to the previous, and almost follow a pattern.

I tried the max_rand, approach describe on the web. But wondered if there was any better approaches?

And could I finally ask, if I had two arrays equals to char[15][20],

Is there anyway, in a method to choose which array we use. Other than declaring the arrays as char[2][15][20], and choosing the first array or second?

Thanks
0

LVL 39

Expert Comment

ID: 12039848
You can seed the rand() function using srand(any_odd_integer) before. However, seeding always with tthe sanme number gives same rand() sequence. To get arbitrary values seed with time() value in seconds (since 1.1.1970).

#include <time.h>

void main()
{
srand(time());

unsigned char array[300];

for (int i = 0; i < 300; i++)
array[i] = rand() % 256;
}

Regards, Alex
0

Author Comment

ID: 12042627
Thanks,

At the moment I am using: srand((unsigned)time(NULL));

Should this be, srand((unsigned)time());

Could I ask finally, if I had two arrays equals to char[15][20],

Is there anyway, in a print method to choose which array we loop through. Other than declaring the arrays as char[2][15][20], and choosing the first array or second? I hope this makes sense.

Thanks
0

LVL 39

Expert Comment

ID: 12042691
>> Should this be, srand((unsigned)time());

No, it was my fault, time(...)  needs a NULL argument to get the current system time.

>> Is there anyway, in a print method to choose which array we loop through

If you have to differ in a print method whether you have to print the first or second array you should pass that information as an argument, e. g.

void MyClass::print(int arr[10][20], bool isFirst)
{
....
}

However, normally functions shouldn't be made too specific as you are decreasing their reusability then.

Regards, Alex

0

Author Comment

ID: 12042946
Thanks

I sometimes found the numbers generated by srand((unsigned)time()), did not always seem to be random.

#include <iostream>
#include <cstdlib>
#include <ctime>

int nrand ( int n )
{
int r;
int bucket_size = RAND_MAX / n;

if ( n <= 0 || n > RAND_MAX )
return 0;
do {
r = std::rand() / bucket_size;
} while ( r >= n );

return r;
}

int main()
{
std::srand ( (unsigned int)std::time ( 0 ) );
for ( int i = 0; i < 10; ++i )
std::cout<< nrand ( 10 ) <<std::endl;

return 0;
}

With regards the two array char[15][20], here is a basic model of my class. I have left out the constuctors, deconstructor. Could you advise of any approach I could choose which array I loop through?

Many thanks

class myClass{

char array1[15][20];
char array2[15][20];
}

myclass:print(){
for(int i = 0; i < 15; i++)}
for(int j = 0; j < 20; j++){
//cout << array[i][j];
}
}
}
0

LVL 39

Expert Comment

ID: 12043451
>>>> Could you advise of any approach I could choose which array I loop through?

Pass the array as an argument to print

myclass:print(char array[15][20])
{
for(int i = 0; i < 15; i++)}
for(int j = 0; j < 20; j++){
cout << array[i][j];
}
}

>>>> I sometimes found the numbers generated by srand((unsigned)time()), did not always seem to be random

You should consider 2 issues:

1. time(NULL) returns the number of seconds since 1.1.1970. A second actually isn't a very fine resolution. So if you are calling srand(time(NULL)) two times to get different sequences, you should make sure that there is at least 1 second difference between two calls.

2. If you need the rand() numbers for crypting reasons, you should know, that it isn't very difficult to find out a possible time range when you have created a rand() sequence. So, generally rand() numbers based on a time() srand() are not good enough for crypting purposes, also because MAX_RAND on most systems is 65536 (16 bit).

For all other purposes IMHO it's good enough.

>>>> int nrand ( int n )

I don't know exactly what's the purpose of nrand() is. But in fact you'll get only numbers that are less than the argument you are passing. So, you haven't to do any modulo stuff like with rand() %n. The difference is that nrand skips some very large rand() numbers (look at the while condition) and that it makes an additional division. So the numbers you'll get are different from that of rand() and couldn't be calculated by someone who didn't know of the algorithm used.

Regards, Alex

0

LVL 30

Expert Comment

ID: 12043481

Many times when newbies complain about srand not being random it's becauser they're trying to seed it multiple times.
int main()
{
for ( int i = 0; i < 10; ++i )
{
std::srand ( (unsigned int)std::time ( 0 ) );
std::cout<< nrand ( 10 ) <<std::endl;
}

The above code seeds before each call to rand(), which will cause non-random sequence.

However, in your original code, you're only seeding once in your program, and that's the way it should be.
Seed once through out the entire program, and never seed again, and you should get a good random sequence.
0

Author Comment

ID: 12043660
Thanks again,

Could I ask what the difference between these are:

srand((unsigned)time(NULL));
srand((unsigned)time(0));

I was still a little unsure about the printing the char array.

If I had a basic class structure as below, I have not included the constructor. Could I decide in the main method, which char array we print?

I understand I could declare the arrays as char array[2][15][20], and then just pass an int to the print method to indicate which array to use.

I just wondered if was anyother method, perhaps using pointers?

class myClass{

char array1[15][20];
char array2[15][20];
}

myclass::print(){
for(int i = 0; i < 15; i++)}
for(int j = 0; j < 20; j++){
//cout << array[i][j];
}
}
}

int main(){
myclass object;

object.print();    //print array1
object.print();    //print array2

return 0;
}
0

LVL 30

Expert Comment

ID: 12043678
>>Could I ask what the difference between these are:
>>srand((unsigned)time(NULL));
>>srand((unsigned)time(0));

There's no practical difference.  In the eyes of the compiler, it's the same.
0

LVL 39

Expert Comment

ID: 12043888
>>>> srand((unsigned)time(NULL));
>>>> srand((unsigned)time(0));

There is no difference. In all common environments there is a basic definition

#define NULL 0

Some people say NULL is the C way to initialize or pass pointers and 0 the C++ way. I don't agree to that as i have no C history of my own.

>>>> I just wondered if was anyother method, perhaps using pointers?

Actually, the method i recommeded above is the pointer method you are asking for.

void print(char array[15][20]);

is equivalent to

void print(char* array);

The only difference is how to use the indices/index.

void print(char array[15][20])
{
for (int i = 0; i < 15; ++i)
for (int n= 0; n < 20; ++n)
cout << array[i][n] << ',';
}

void print(char* array)
{
for (int i = 0; i < 15; ++i)
for (int n= 0; n < 20; ++n)
cout << array[i*20+n] << ',';
}

Regards, Alex

0

Author Comment

ID: 12044051
Thanks again

From the main method, I am correct in saying the class arrays could referenced using somelike:

class myClass{

char array1[15][20];
char array2[15][20];

public:
void print(char * array)
}

myclass::print(char * array){
for(int i = 0; i < 15; i++)}
for(int j = 0; j < 20; j++){
//cout << array[i][j];
}
}
}

int main(){
myclass object;

object.print(char * array1);    //print array1
object.print(char * array 2);    //print array2

return 0;
}
0

LVL 39

Expert Comment

ID: 12049697
You need:

class myClass{
char array1[15][20];
char array2[15][20];

public:
void print(char * array);
}

void myclass::print(char * array){
for(int i = 0; i < 15; i++){
for(int j = 0; j < 20; j++){
cout << array[i*20+j];
}
}
}

int main(){
myclass object;

object.print((char *) object.array1);    //print array1
object.print((char *) object.array 2);    //print array2

return 0;
}

You see, it isn't elegant that way.

class myClass{

char array1[15][20];
char array2[15][20];

public:
void print();
void printArray(char array[15][20]);
}

void myclass::printArray(char array[15][20]){
for(int i = 0; i < 15; i++){
for(int j = 0; j < 20; j++){
cout << array[i][j];
}
}
}

void myclass::print()
{
printArray(array2);
}

int main(){
myclass object;

object.print();    //print array1 and  array2

return 0;
}

Regards, Alex
0

Expert Comment

ID: 12052620
And to print either array1 or array2, would you recommend passing the print function a signal. Is this the best approach?

class myClass{

char array1[15][20];
char array2[15][20];

public:
void print();
void printArray(char array[15][20]);
}

void myclass::printArray(char array[15][20]){
for(int i = 0; i < 15; i++){
for(int j = 0; j < 20; j++){
cout << array[i][j];
}
}
}

void myclass::print(int signal)
{
if(signal == 1){
printArray(array1);
}
else if( signal == 2){
printArray(array2);
}
}

int main(){
myclass object;

object.print(1);
object.print(2);

return 0;
}
0

LVL 39

Accepted Solution

itsmeandnobodyelse earned 260 total points
ID: 12052769
Yes, looks not bad, though for real data one should consider an enum instead of numbers.

enum ICD { FIRST_IMPORTANT_CHAR_DATA , SECOND_IMPORTANT_CHAR_DATA };
class myClass{

char array1[15][20];
char array2[15][20];

public:
void print(ICD signal);
void printArray(char array[15][20]);
};

void myClass::printArray(char array[15][20]){
for(int i = 0; i < 15; i++){
for(int j = 0; j < 20; j++){
cout << array[i][j];
}
}
}

void myClass::print(ICD signal)
{
typedef char  Array15_20[15][20];
Array15_20*  both[] = { &array1, &array2 };

printArray(*both[signal]);
}

int main(){
myClass object;

object.print(FIRST_IMPORTANT_CHAR_DATA);
object.print(SECOND_IMPORTANT_CHAR_DATA);

return 0;
}

BTW, a typedef isn't a bad idea when handling with multidimensional arrays.

Regards, Alex

0

## Featured Post

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.