Help changing array values

Pages: 12
I am in a beginning C++ class in college and I need some help with a project. The project is to design a C++ program that takes a user enter sequence of non-negative numbers and then output the number and output how many times each number is used. I am having trouble getting the count of each number and having it displayed. Any help is appreciated. Here's the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
using namespace std;

const int SIZE = 50;

void fill_array(int a[], int& limit);

int calc(int a[], int num, int limit);

void out(int a[], int limit);

int main()
{
	int a[SIZE]={}, limit = 0;

	fill_array(a, limit);

	out(a, limit);

	return 0;
}

void fill_array(int a[], int& limit)
{
	int num = 0;
	int next;
	cout << "Please enter a sequence of non-zero integers (up to 50)\n"
	     << "and this program will tell you the count of each different integer used\n";
	cout << "Enter a negative number to end sequence.\n";
	cin >> next;
	while((next > 0) && (num < SIZE))
	{
		a[num] = next;
		num++;
		cin >> next;
	}
	num = limit;
}

int calc(int a[], int num, int limit)
{
	int numcount = 0;
	for(int index = 1; index < limit; index++)
	{
		int check = a[index];
		int var = a[num];
		if(check == var)
		{
			numcount++;
			a[index] *= -1;	
		}
	}
	cout << numcount << endl;
	return numcount;
}

void out(int a[], int limit)
{
	int count;
	cout << "Number \t Count\n";
	for(int i=0; i < limit; i++)
	{
		if(a[i]>0)
		{
			cout << a[i] << "\t";
			count = calc(a,i,limit);
			cout << count << endl;
		}
	}
}

Check Line 37 - is that really what you want? Think carefully.

If your answer is yes, tell me what you are trying to do there.
In line 37 I was trying to set a variable equal to the amount of array values entered to by the user so I could just use the partially filled array in the following functions.
The reason why kfmfe04 asked about it is because that variable will be destroyed after the function completes. Either declare that variable (num) outside of the function or pass a pointer to that variable as function parameter.

However, you don't need it because you have "SIZE" which will have the same value.
Last edited on
Sorry my dumb mistake. I meant to assign the value of num to limit and it should be limit = num and since limit is a call by reference parameter the value will be carried over. Thanks for helping me out... just a stupid mistake I feel a little embarrassed right now.
Now when I want to display only one of an array value and the count it sometimes prints out multiple. Here is a sample run of the program:

Please enter a sequence of non-zero integers (up to 50)
and this program will tell you the count of each different integer used
Enter a negative number to end sequence.
12 12 1 4 1 4 45 45 1 3 7 -1
Number Count
12 2
1 2
4 2
1 2
4 2
45 2
45 2
1 2
3 2
7 2


I thought the if loop and the changing of the array parameters to a negative number would prevent this.
Line 53 prints numcount
but so does Line 67

Also, watch your results - they don't seem to be quite right for your inputs.

I see three 1's and only one 3 and one 7.
I think I might need a while loop instead of an if statement. Sorry I changed the program around a little.
Here's the new code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#include <iostream>
using namespace std;

const int SIZE = 50;

void fill_array(int a[], int& limit);

int calc(int a[], int num, int limit);

void out(int a[], int limit);

int main()
{
	int a[SIZE]={}, limit = 0;

	fill_array(a, limit);

	out(a, limit);

	return 0;
}

void fill_array(int a[], int& limit)
{
	int num = 0;
	int next;
	cout << "Please enter a sequence of non-zero integers (up to 50)\n"
	     << "and this program will tell you the count of each different integer used\n";
	cout << "Enter a negative number to end sequence.\n";
	cin >> next;
	while((next > 0) && (num < SIZE))
	{
		a[num] = next;
		num++;
		cin >> next;
	}
	limit = num;
}

int calc(int a[], int num, int limit)
{
	int numcount = 1;
	for(int index = 1; index < limit; index++)
	{
		int check = a[index];
		int var = a[num];
		if(check == var)
		{
			numcount++;
			a[index] *= -1;	
		}
	}
	return numcount;
}

void out(int a[], int limit)
{
	int count;
	cout << "Number \t Count\n";
	for(int i=0; i < limit; i++)
	{
		if(a[i]>0)
		{
			cout << a[i] << "\t";
			count = calc(a,i,limit);
			cout << count << endl;
		}
	}
}


Problems on Lines 42 and 43 (at least).
Line 50 is a bad idea.
The reason why you are outputting duplicates is because your array "a[]" that you are iterating through contains duplicates of the same number. I recommend creating a struct with int value and count variables. Whenever a user enters a number that number is either put into a struct and inserted into a vector or if it exists in the vector its count is increased. Then all you need to do is ouput the contents of the vector and their respective counts.
After you fix Lines 42, 43, and 50, you will only have the problem that GodPyro mentioned.

If you want to minimize changes to your code to get it fixed, you can use an stl set - set<unsigned> in particular:
http://www.cplusplus.com/reference/stl/set/

For a new value, before printing, check to see if it is in set<unsigned>.
If it's there, don't print.
If it's not there, print and put the value in the set.

Of course, if you wanted to redo the entire algorithm, you can get away with just using an stl map<unsigned,unsigned> and do away with your array and counting completely.

I just coded that up - using your formatting, it comes out to 47 lines and output looks like this:


Please enter a sequence of non-zero integers (up to 50)
and this program will tell you the count of each different integer used
Enter a negative number to end sequence.
12 12 1 4 1 4 45 45 1 3 7 -1
Number 	 Count
1	3
3	1
4	2
7	1
12	2
45	2

What I was trying to do starting the numcount at 1 is assume that if the number comes up there will be at least one of it and what I was trying to do with the a[index] *= -1 is if it finds a duplicate change that to a negative number so when it comes to 62 it wouldn't pass the boolean expression but it seems to only be running the numcount one so it only gets a value of 2 and so I was thinking there must be a way to make it run for the entire array so every number if found will turn into a negative number and not be printed on the screen.
Once you modify a[index] *= -1, you cannot count that value any more!!! In other words, the check on Line 47 will always return false, subsequently. This explains why none of your results show greater than 2.

In calc(), a[] is an input for your for() loop. By modifying a[] inside with a[index] *= -1, it also acts as an output. Be extremely careful about doing that.

In 99% of the cases, I would avoid doing that inside a loop - either use the array as input or as output. Otherwise, you could end up with serious debugging headaches.

How would I go about only changing the array element after it counts the number?
You could do it inside calc(), using a second loop, but even that is dangerous, from a developer's point of view.

Why? When you see a function called calc(), would you expect it to change the values of something you pass it? In other words, if you call calc() multiple times, would you expect it to do the same thing?

You have to ask yourself this because once you write code and put it away for a while before playing with it again, you don't want any "surprises" (aka bugs) in your code.

For a "hack", you could do it, but be aware of what you are doing - it's not really a good habit, if you are serious about programming.
I see what your saying. Would a better alternative be to have a function that saves the number count in a separate array and then another function that deletes the duplicates in the first array and then output both arrays?
I recommend using the strategy that I suggested by creating a struct, converting the input into that struct, then either inserting or incrementing a vector containing that struct. This way it is neat, logic safe and you will not have problems with memory.
Last edited on

stl set:
http://www.cplusplus.com/reference/stl/set/

Copy and Paste this program and run it.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
#include <iostream>
#include <set>

using namespace std;

void tryToPrintOnce( int x, set<unsigned>& alreadyPrinted )
{
  bool notPrintedAlready = (alreadyPrinted.find( x )==alreadyPrinted.end());
  if ( notPrintedAlready ) {
    cerr << x << endl;
    alreadyPrinted.insert( x );	
  }
}

main()
{
  int x = 5;

  set<unsigned> alreadyPrinted;

  cerr << "first time ";
  tryToPrintOnce( x, alreadyPrinted );

  cerr << "second time ";
  tryToPrintOnce( x, alreadyPrinted );
  cerr << "\n";
}


You should get this:
first time 5
second time 


See if you can understand the code.

If you do, you should be able to modify this code to do what you want.
If you don't understand it, please feel free to ask questions.

Of course, we can make it more OO by putting it in a class, but I'm keeping it simple here to see if you can learn how to use an stl set.
Last edited on
Thanks so much. Really easy fix since what I was trying to do was not get duplicates to be printed out again.
Pages: 12