Link to home
Start Free TrialLog in
Avatar of EmailSurfer
EmailSurfer

asked on

Accessing char[][]?

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
Avatar of bcladd
bcladd

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

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

-bcl
Avatar of EmailSurfer

ASKER

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];


I meant should the end postiions be taken into account?

Thanks
>>>> 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

Thank you for replying.

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
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
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
>> 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

Thanks

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

There are many articles on the web about this issue. One site gave this example, I would be interested in your thoughts?

#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];
      }
}
}
>>>> 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



Avatar of Axter
>>There are many articles on the web about this issue. One site gave this example, I would be interested in your thoughts?

Many times when newbies complain about srand not being random it's becauser they're trying to seed it multiple times.
BAD Example:
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.
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;
}
>>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.
>>>> 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

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;
}
You need:

class myClass{
public:                       // to have access to array1 and array2 in main
   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(array1);   // member functions have access to private member data
    printArray(array2);
}

int main(){
   myclass object;
   
   object.print();    //print array1 and  array2

   return 0;
}


Regards, Alex
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;
}
ASKER CERTIFIED SOLUTION
Avatar of itsmeandnobodyelse
itsmeandnobodyelse
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial