Hi guys,

I have an array which reads in a file and displays it to the screen. The output is as follows:

1 0 0
2 0 0
3 0 0
4 1 2
5 1 2
6 0 0
7 3 4
8 5 6
9 7 8
10 7 8

I then used a random number generator to add a 1 or a 0 to a further 2 columns in the array. An example of an output is as follows:

1 0 0 1 0
2 0 0 0 1
3 0 0 1 1
4 1 2 1 0
5 1 2 0 1
6 0 0 1 1
7 3 4 1 1
8 5 6 1 1
9 7 8 1 0
10 7 8 0 1

I was wondering if anyone knew how to count the 1's and 0's I have in the 4th and 5th columns? For the above example, below the output of the array, I would like it to print the following to the screen:

Number of 0's present: 6
Number of 1's present: 14

I'm struggling with the code. Does anyone have any ideas? My current code is:

#include <iostream.h>
#include <fstream.h>
#include <stdlib.h>

int j;
int matrix[100][5] = {0};
int numCols = 3;
int numRows = 0;
float rand1, rand2, rand3, rand4;
void SetSeed();

int main () {

const float RANGE = 1.0;
SetSeed();

ifstream inFile;
inFile.open("input.txt");

  if (!inFile)
  {
  printf ("Unable to open input file");
  exit(1);
  }

while (inFile >> matrix[numRows][0])
{
printf ("%d\t", matrix[numRows][0]);
for (j = 1; j < numCols; j++)
{
inFile >> matrix[numRows][j];
printf ("%d\t", matrix[numRows][j]);
}

int counter;

if (matrix[numRows][1] == 0 && matrix[numRows][2] == 0){
   for (counter = 1;counter <= 1;counter++){
   rand1 = (float) rand() * RANGE / RAND_MAX;
   rand2 = (float) rand() * RANGE / RAND_MAX;
   }
   if (rand1 < 0.4){
   matrix[numRows][3] = 0;
   printf("\t%d", matrix[numRows][3]);
   }   
   if (rand1 >= 0.4){
   matrix[numRows][3] = 1;
   printf("\t%d", matrix[numRows][3]);
   }      
   if (rand2 < 0.4){
   matrix[numRows][4] = 0;
   printf("\t%d", matrix[numRows][4]);
   }      
   if (rand2 >= 0.4){
   matrix[numRows][4] = 1;
   printf("\t%d", matrix[numRows][4]);
   }
   }

else{
   
   for (counter = 1;counter <= 1;counter++){
   rand3 = (float) rand() * RANGE / RAND_MAX;
   rand4 = (float) rand() * RANGE / RAND_MAX;
   }
   if (rand3 < 0.5){
   matrix[numRows][3] = 0;
   printf("\t%d", matrix[numRows][3]);
   }   
   if (rand3 >= 0.5){
   matrix[numRows][3] = 1;
   printf("\t%d", matrix[numRows][3]);
   }      
   if (rand4 < 0.5){
   matrix[numRows][4] = 0;
   printf("\t%d", matrix[numRows][4]);
   }      
   if (rand4 >= 0.5){
   matrix[numRows][4] = 1;
   printf("\t%d", matrix[numRows][4]);
   }
   }
   
   
    
numRows++;
printf ("\n");
}

inFile.close ();
}

void SetSeed() {

FILE *seed_file;
long int seed_value;

seed_file = fopen("seed.txt","r");
fscanf(seed_file,"%d",&seed_value);
fclose(seed_file);
srand(seed_value);
seed_file = fopen("seed.txt","w");
fprintf(seed_file,"%d",rand());
fclose(seed_file);
}

Thanks for any help you can give me :)

delete lines 38 and 41 because tha loop only executes once, so there is no point to having a loop there.

line 41: just make it a simple else statement. If the value is not < 0.4 then there is only one other choice, That whole loop can be simplified to this:

if (matrix[numRows][1] == 0 && matrix[numRows][2] == 0){
   rand1 = (float) rand() * RANGE / RAND_MAX;
   rand2 = (float) rand() * RANGE / RAND_MAX;
   if (rand1 < 0.4){
   matrix[numRows][3] = 0;
   }   
   else{
   matrix[numRows][3] = 1;
   }      
   printf("\t%d", matrix[numRows][3]);

   if (rand2 < 0.4){
   matrix[numRows][4] = 0;
   }      
   else{
   matrix[numRows][4] = 1;
   }
   printf("\t%d", matrix[numRows][4]);
   }

else{

   rand3 = (float) rand() * RANGE / RAND_MAX;
   rand4 = (float) rand() * RANGE / RAND_MAX;

   if (rand3 < 0.5){
   matrix[numRows][3] = 0;
   }   
   else{
   matrix[numRows][3] = 1;
   }      
   printf("\t%d", matrix[numRows][3]);

   if (rand4 < 0.5){
   matrix[numRows][4] = 0;
   }      
   else{
   matrix[numRows][4] = 1;
   }
   printf("\t%d", matrix[numRows][4]);
   }


numRows++;
printf ("\n");
}

Edited 3 Years Ago by mike_2000_17: Fixed formatting

Cheers for that mate, my code looks a bit neater now and it makes more sense.

Do you have any tips for the counting question though?

Any help is welcomed, thanks!

one way is to use another matrix

int counters[2] = {0}

for(int i = 0; i < numRows; ++i)
{
   counters[ matrix[i][3] ]++; // count the number of 0s or 1s in the 4th column
   counters[ matrix[i][4] ]++; // count the number of 0s or 1s in the 5th column
}

The above uses the 0 or 1 in the matrix column to index into the counters array.

Ok, I'm thinking of placing the int counters[2]={0} at the top of my code as a global variable, and placing the code below it at line 89. Would this be appropriate placement? Or would you put them in all together at a different line?

I'm very unsure as to how to get the program to print out the results of the count? Do you have any tips?

Thanks.

>>I'm very unsure as to how to get the program to print out the results of the count? Do you have any tips?

Yes -- do it similar to how you did the other printf() lines

As for your first question -- give it your best shot and test your program to see if it works. If it doesn't work then try something else. Find out what kinds of solution(s) you can come up with.

Ok I'm really struggling with positioning, sorry.

I've placed the variable globally, and then placed the code as follows:

while (inFile >> matrix[numRows][0])
{
printf ("%d\t", matrix[numRows][0]);
for (j = 1; j < numCols; j++)
{
inFile >> matrix[numRows][j];
printf ("%d\t", matrix[numRows][j]);
}

for(int i = 0; i < numRows; ++i)
{
counters[ matrix[i][3] ]++; // count the number of 0s or 1s in the 4th column
counters[ matrix[i][4] ]++; // count the number of 0s or 1s in the 5th column
}

int counter;

I get 3 error messages:
1. Keyword 'int' cannot be declared as a variable
2. Terminating semicolon missing
3. 'numCols' has not been declared

However, none of these make sense. Hmm, I have tried, but I just can't get it?

your compiler should tell what lines they were on.
the first two are simple syntax errors
Perhaps the 'int' keyword problem is related to the undeclared variable 'numCols' where you ment to write:

int numCols;

but wrote

int int

which would give those exact three.

Do a string search on your code for int.

Ok I'm really struggling with positioning, sorry.

I've placed the variable globally, and then placed the code as follows:

while (inFile >> matrix[numRows][0])
{
printf ("%d\t", matrix[numRows][0]);
for (j = 1; j < numCols; j++)
{
inFile >> matrix[numRows][j];
printf ("%d\t", matrix[numRows][j]);
}

for(int i = 0; i < numRows; ++i)
{
counters[ matrix[i][3] ]++; // count the number of 0s or 1s in the 4th column
counters[ matrix[i][4] ]++; // count the number of 0s or 1s in the 5th column
}

int counter;

I get 3 error messages:
1. Keyword 'int' cannot be declared as a variable
2. Terminating semicolon missing
3. 'numCols' has not been declared

However, none of these make sense. Hmm, I have tried, but I just can't get it?

1) counting the number of 0s and 1s can not be done until after the entire file has been read in and after the 4th and 5th columns have been completed. You put the cart before the horse.

2) int counter; What is that?

sorry yes, I got rid of int counter;

Forget that!

I placed the code as follows:

else{
   int dad = matrix[i][1];    // 1 is "dad" column
   int mom = matrix[i][2];   // 2 is "mom" column

   int dadRowIndex = dad - 1;
   int momRowIndex = mom -1;

   rand3 = (float) rand() * RANGE / RAND_MAX;
   rand4 = (float) rand() * RANGE / RAND_MAX;

   if (rand3 < 0.5){
   matrix[i][3] = matrix[dadRowIndex][3];
   }   
   else{
   matrix[i][3] = matrix[dadRowIndex][4];
   }
   printf("\t%d", matrix[i][3]);
      
   if (rand4 < 0.5){
   matrix[i][4] = matrix[momRowIndex][3];
   }
   else{
   matrix[i][4] = matrix[momRowIndex][4];
   }
   printf("\t%d", matrix[i][4]);
}

i++;
printf ("\n");
}

for(int i = 0; i < i; ++i)
{
counters[ matrix[i][3] ]++; // count the number of 0s or 1s in the 4th column
counters[ matrix[i][4] ]++; // count the number of 0s or 1s in the 5th column
}


inFile.close ();
}

My program seems to run fine!! However, there is obviously no count being printed to screen.

Would I go something like:

printf("counters[ matrix[i][3] ]")
printf("counters[ matrix[i][4] ]")

or

printf("counters[ matrix[i][3] ]++")
printf("counters[ matrix[i][4] ]++")

Am I on the right track?

The loop below will never execute with i<i

for(int i = 0; i < i; ++i)
{
counters[ matrix[i][3] ]++; // count the number of 0s or 1s in the 4th column
counters[ matrix[i][4] ]++; // count the number of 0s or 1s in the 5th column
}


inFile.close ();
}

Also, there is no condition set for the count. All this is doing is incrementing a cell in counters specified by the value found in matrix[3].
If say there was a in matrix[1][3], that translates to counter[0]++.
Very convoluted and probably wont work reliably.

how about making it a sure thing with an old fashioned if/then?

if (matrix [3] ==0)
{
counter1++
}

Also, there is no condition set for the count. All this is doing is incrementing a cell in counters specified by the value found in matrix[3].
If say there was a in matrix[1][3], that translates to counter[0]++.
Very convoluted and probably wont work reliably.

matrix[?][3] and matrix[?][4] will always be either 0 or 1. All the OP needs to do is count the number of 0s and 1s in those two columns. So
counters[ matrix[?][4] ]++ is either counting the number of 0s when matrix[?][4] is 0 or 1s when [matrix[?][4] is 1. When all is done the number of 0s is accumulated in counters[0] and the number of 1s is accumulated in counters[1]. There is nothing convoluted about it once you understand the power of indirect addressing, and is useful in quite a few situations.

But you might be right that such a concept as indirect addressing is too advanced and complicated for beginning programmers.

Cheers guys, which do you think I should go for? Being a beginner as I am??

I'd go with the "if" statements. I like Ancient Dragon's solution and it's more efficient, but since it's new to you it may be a little confusing when you're reading it later. The "if" strategy is going to be clearer since it's familiar. Something like this:

if (matrix[i][3] == 0)
     counters[0]++;
else
     counters[1]++;

if (matrix[i][4] == 0)
     counters[0]++;
else
     counters[1]++;

Regarding how to display, this won't work:

printf("counters[ matrix[i][3] ]");

Besides not being right from a printf standpoint, you are printing this AFTER it's all been tallied, right? By that time you are out of the loop. Since i was a loop counter, it no longer has any meaning. Try this:

printf ("Number of zeroes: %d", counters[0]);

%d tells printf that it will replace the %d with a number. That number will be counters[0].
The result, if counters[0] equals 7, would be this:

Number of zeroes: 7

Hope this helps.

matrix[?][3] and matrix[?][4] will always be either 0 or 1. All the OP needs to do is count the number of 0s and 1s in those two columns. So
counters[ matrix[?][4] ]++ is either counting the number of 0s when matrix[?][4] is 0 or 1s when [matrix[?][4] is 1. When all is done the number of 0s is accumulated in counters[0] and the number of 1s is accumulated in counters[1]. There is nothing convoluted about it once you understand the power of indirect addressing, and is useful in quite a few situations.

But you might be right that such a concept as indirect addressing is too advanced and complicated for beginning programmers.

I personally have not done anything that REQUIRED indirect addressing. I'm sure there are some very compelling applications of it, but I don't think this is one of them. (My opinion, what's yours?)

Also, this particular program uses the DATA as a cell address. OK if there are only 1's and 0's
then you end up with counters[0] for the zero count and counters[1] having the 1's count.
What if there is something else like a character? The program would crash. If there is a 2 in there somehow, perhaps this would push counters[] out of range.

I think it's kind of clever that it's "self labeling" and all, but it's also a complex way to do an otherwise simple task. I am a firm believer of the KISS method. Make the code ONLY as comlex as it it needs to be.

Also, this particular program uses the DATA as a cell address. OK if there are only 1's and 0's
then you end up with counters[0] for the zero count and counters[1] having the 1's count.
What if there is something else like a character? The program would crash. If there is a 2 in there somehow, perhaps this would push counters[] out of range.

In this particular case he is not using data directly. The columns he is tallying were not read in from the data file. They were derived from a random number generator elsewhere in his program, which was written specifically by him to produce only zeroes and ones. He has complete control over this so a bad data file might cause problems elsewhere, but it would not cause a character or 2 to show up in either of those columns.

I do agree that often it can't hurt to test to make sure there is only a 0 or 1, and if for some weird reason it's something else, bail out of the program or something if assumptions are not met. However at this stage I doubt Andy is required to implement that.

Right, well the if statements it is then!

You say use...

if (matrix[i][3] == 0)
     counters[0]++;
else
     counters[1]++;

if (matrix[i][4] == 0)
     counters[0]++;
else
     counters[1]++;

However, I have decided today that if it is possible, I would like to make a better approach to the counting method.

Whilst previously I was just wanting to count the number of 0's and 1's that appear, I think I'd like to do something different. To explain:

In columns 4 and 5 we have one of these for each individual:

00
10
01
11

So for my count, I would like to count how many of these appear and display it to the screen. So in this example:

1 0 0 1 0
2 0 0 0 1
3 0 0 1 1
4 1 2 1 0
5 1 2 0 1
6 0 0 1 1
7 3 4 1 1
8 5 6 1 1
9 7 8 1 0
10 7 8 0 1

I would like the output to be:


00 = 0
10 = 3
01 = 3
11 = 4

Any ideas ??

Yup,

just expand the condition

if (matix[i][3] && mattrix[i][4] ==0)
{
//whatever count method for 00
}

then just mix and match whatever constraints you wish on the count.

Oops, make that:

if (matix[i][3]==0  && mattrix[i][4] ==0)
{
//whatever count method for 00
}

... so it would be:

if (matix[i][3]==0  && mattrix[i][4] ==0)
{
counters[00]++;
}

if (matix[i][3]==0  && mattrix[i][4] ==1)
{
counters[01]++;
}

if (matix[i][3]==1  && mattrix[i][4] ==0)
{
counters[10]++;
}

if (matix[i][3]==1 && mattrix[i][4] ==1)
{
counters[11]++;
}

Is this about right?

Do I have to declare any variables for this to work?

Also, how exactly would I print this out to screen I'm still confused with that.

And positioning?!?! OMG positioning. Ha. Sorry. Beginning programming can be frustrating sorry. Can you believe I have to do this project with just 1 week's classes of c++? I really do appreciate the help guys!

Also, I'm wanting my program to track 2 individuals out of the family tree.

So when the program starts, I want it to say, which 2 individuals are you interested in?

e.g.

>5
>9

Can I get the program to give me the counts of 00, 01, 10, 11's for each individual? Like...

Individual 5 count:

00 = 50
01 = 150
10 = 400
11 = 400

Individual 9 count:

00 = 60
01 = 140
10 = 380
11 = 420

This is of course I get the program to loop itself 1000 times.

Would the code be similar? How would it be altered?

... so it would be:

if (matix[i][3]==0  && mattrix[i][4] ==0)
{
counters[00]++;
}

if (matix[i][3]==0  && mattrix[i][4] ==1)
{
counters[01]++;
}

if (matix[i][3]==1  && mattrix[i][4] ==0)
{
counters[10]++;
}

if (matix[i][3]==1 && mattrix[i][4] ==1)
{
counters[11]++;
}

Is this about right?

Do I have to declare any variables for this to work?

Also, how exactly would I print this out to screen I'm still confused with that.

And positioning?!?! OMG positioning. Ha. Sorry. Beginning programming can be frustrating sorry. Can you believe I have to do this project with just 1 week's classes of c++? I really do appreciate the help guys!

Very close. The logic is right, the if statements are right. The only thing I would do is make the slight change of making counter a 2 dimensional array instead of a one dimensional array:

int counters[2][2];

instead of

int counters[2];

You would initialize all of these (counters[0][0], counters[0][1], counters[1][0], counters[1][1]) to 0 before tallying, as you did when it was just a one dimensional array. You would keep the same "if" statements, but would change the line inside the brackets after them, as in change this:

if (matix[i][3]==0  && mattrix[i][4] ==0)
{
counters[00]++;
}

to this:

if (matix[i][3]==0  && mattrix[i][4] ==0)
{
counters[0][0]++;
}

It's the same logic, but you had a syntax problem. For a 2-D array, you need 2 pairs of brackets, not just 1.

The only other suggestion I would make, and this is not to correct an error but rather to make the code a bit cleaner, is this: Your code is in the style of:

if (condition 1)
if (condition 2)
if (condition 3)
if (condition 4)

You could change this to

if (condition 1)
else if (condition 2)
else if (condition 3)
else (condition 4)

Again, this is not to correct an error, but it is preferred because it points out that one and exactly one of these code blocks will be performed and that the reader should consider that the four "if" statements are grouped together. It makes the logic easier to follow. You are very close!

Well, almost.
The whole clever thing with counter "labeling itself" is sort of out the window.

To make that work as written, you will have to change the counters declaration to counters[12].
(for 0 to 11).
You are declaring, but not using all of the remaining cells. rather inefficient.
all you need is 4 cells.
counter[0] =00
counter[1] = 01
counter[2] = 10
counter[3] =11

Brilliant!

Ok, I'm on the right track then. Where exactly in my code would you place the if statements? After the array has run obviously, but where exactly? Also, where would I place the

int counters [2][2];

??

And the code for printing the results to screen?

Well, almost.
The whole clever thing with counter "labeling itself" is sort of out the window.

To make that work as written, you will have to change the counters declaration to counters[12].
(for 0 to 11).
You are declaring, but not using all of the remaining cells. rather inefficient.
all you need is 4 cells.
counter[0] =00
counter[1] = 01
counter[2] = 10
counter[3] =11

That works too Andy. It's up to your personal preference. Either way is fine.

I personally have not done anything that REQUIRED indirect addressing. I'm sure there are some very compelling applications of it, but I don't think this is one of them. (My opinion, what's yours?)

I've seen very few times when indirect referencing is actually required and this is not one of them. For beginners the if statements work just great, and the OPs teacher would probably frown on using indirect referencing because it is too advanced for first semester students.

Also, this particular program uses the DATA as a cell address. OK if there are only 1's and 0's
then you end up with counters[0] for the zero count and counters[1] having the 1's count.
What if there is something else like a character? The program would crash. If there is a 2 in there somehow, perhaps this would push counters[] out of range.

That will not happen in this case because 0 and 1 are the only two possible values which the program inserts. If the program inserted other values then the counters array would have to be expanded to accommodate them.

I think it's kind of clever that it's "self labeling" and all, but it's also a complex way to do an otherwise simple task. I am a firm believer of the KISS method. Make the code ONLY as comlex as it it needs to be.

After you spend 20 years optimizing programs then you too will see the value in it.

To get a little off topic: lets say you write a program to count the number of times each letter of a paragraph occurs (English language, but similar scenario applied to most other languages too). That means there could be as many as 62 characters (26 upper-case, 26-lower case and 10 digits) plus all the punctuation charactes that are on the standard keyboard. One way to write the program is to have a series of 70 or so if-then-else statements. A second method is to use a 70+ case statements in a switch statement. The simplest way is to create an array of 255 integers then use each character in the paragraph as an index into the array

char sentence[]= "Once upon a time there were three little pigs.";
int counts[255] = {0};
for(int i = 0; sentence[i] != 0; i++)
   counts[sentence[i]]++;
// now array counts contains the values you want

Ok, I'm on the right track then. Where exactly in my code would you place the if statements? After the array has run obviously, but where exactly? Also, where would I place the

int counters [2][2];

??

You said you already got it working when you had it before as

int counters[2];

so that would be an OK place to keep the declaration. Just change it from:

int counters[2];

to

int counters[2][2];

and keep it in the same place. You said it worked before so you must have it in a decent place:

And the code for printing the results to screen?

See post number 14 in this thread for how to print an integer along with text using printf. Also see your code. You've done it several times with the 2-D matrix array. Same thing.

As I mentioned, either my suggestion of a 2-dimensional array of counters or JRM's way will work, but pick one and stick with it. Personally I think that the 2-D array is easier to folow since

counts[0][0] goes with 00
counts[0][1] goes with 01
counts[1][0] goes with 10
counts[1][1] goes with 11

I think that's easy to make sense out of and will thus be easier for both you and a reader to follow. So I'd go that route.

As for having a loop of 1000 and having the program go through it 1000 times and keep track of two particular people, that is certainly doable, but I recommend biting off one piece at a time. Change that while loop into a for loop as mentioned in the other thread, get that working, get the tallying and display working, get it all working for one pass through the program, THEN tackle going through the program 1000 times. It's about the same level of difficulty as the rest of this, so if you can get this working, you'll have the skill to add the 1000 times loop.

I have placed the counter just after the program closes the infile. I'm pretty sure this will work. I placed int counters[2][2] = {0}; as a global variable, and the code looks like this:

inFile.close ();


for(int i = 0; i < numRows; i++)
{
if (matrix[i][3]==0  && matrix[i][4] ==0) 
{ 
counters[0][0]++; 
}

else
if (matrix[i][3]==0  && matrix[i][4] ==1) 
{ 
counters[0][1]++; 
}

else
if (matrix[i][3]==1  && matrix[i][4] ==0) 
{ 
counters[1][0]++; 
}

else
if (matrix[i][3]==1 && matrix[i][4] ==1)
{
counters[1][1]++;
}
}
}

void SetSeed() {

I think this is right?? Would I place the printf statements directly under this to print the results of the counts to the screen?

However, you said in a previous post:

"You would initialize all of these (counters[0][0], counters[0][1], counters[1][0], counters[1][1]) to 0 before tallying, as you did when it was just a one dimensional array."

How would I do this? Or have I already done it by using int counters[2][2] = {0}; ??

Also, you told me to fix that while loop to a for loop. At the moment it looks like this:

while (inFile >> matrix[numRows][0])
{
printf ("%d\t", matrix[numRows][0]);
for (j = 1; j < numCols; j++)
{
inFile >> matrix[numRows][j];
printf ("%d\t", matrix[numRows][j]);
}

int counter;

But I'm really struggling to get a grasp on what you mean... Could you possible show me how I should change it? Thank you in advance!

Andy,

Part of the learning process in C++ is "cut 'n try".
Just compile the thing and see what happens.
If you have a good compiler, it will tell you what is wrong and where. (I use g++)

Troubleshooting code is something you will need to do even as a professional.

Don't be afraid! Dive in. Learn from your mistakes...I know all about doing that!

The worst thing that can happen is that you will get a bunch of compiler errors -or the program won't do what you expect when it runs.

There will be no stock market crash brought on by your program failing to perform!
COMPILE IT!

This article has been dead for over six months. Start a new discussion instead.