Solved

Accessing char[][]?

Posted on 2004-09-12
18
268 Views
Last Modified: 2010-04-01
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
Comment
Question by:EmailSurfer
  • 7
  • 7
  • 2
  • +2
18 Comments
 
LVL 11

Expert Comment

by:bcladd
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

by:EmailSurfer
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

by:EmailSurfer
ID: 12039213

I meant should the end postiions be taken into account?

Thanks
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
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

by:EmailSurfer
ID: 12039786
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
0
 
LVL 39

Expert Comment

by:itsmeandnobodyelse
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

by:EmailSurfer
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

by:itsmeandnobodyelse
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

by:EmailSurfer
ID: 12042946
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];
      }
}
}
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 39

Expert Comment

by:itsmeandnobodyelse
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

by:Axter
ID: 12043481
>>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.
0
 

Author Comment

by:EmailSurfer
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

by:Axter
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

by:itsmeandnobodyelse
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

by:EmailSurfer
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

by:itsmeandnobodyelse
ID: 12049697
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
0
 

Expert Comment

by:AntoniRyszard
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

by:
itsmeandnobodyelse earned 65 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

Why You Should Analyze Threat Actor TTPs

After years of analyzing threat actor behavior, it’s become clear that at any given time there are specific tactics, techniques, and procedures (TTPs) that are particularly prevalent. By analyzing and understanding these TTPs, you can dramatically enhance your security program.

Join & Write a Comment

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn additional member functions of the vector class. Specifically, the capacity and swap member functions will be introduced.

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now