Difficulty understanding for loop iteration results

Pages: 12
Hi, I am extremely new to C++, I apologise in advance if my question is long winded or difficult to follow but here I go. I am reading through a book called C++ for Dummies. In one of the examples used in the Arrays section we are given some code that asks the user to input numbers and the program will print out the average of those numbers. I don’t have a problem understanding the code itself but I do have a question regarding the results of a ‘for’ loop used in the program a couple of times. The first time it is used is here like this:

1
2
3
4
5
6
7
8
 void displayArray(int nValues[100], int nCount)
{
    for(int i=0; i<nCount; i++)
    {
        cout.width(3);
        cout<<i<<"="<<nValues[i]<<endl;
    }
} 


In the program this gets printed out, If the numbers entered were 5,4,5,6 for example, the printout would read:
0 = 5
1 = 4
2 = 5
3 = 6

However, when the ‘for' loop is used again like this:

1
2
3
4
5
6
7
8
9
  int averageArray(int nValues[100], int nCount)
{
    int nSum=0;
    for(int i=0; i<nCount; i++)
    {
        nSum+=nValues[i];
    }
    return nSum/nCount;
}


The nCount ends up equalling 4 (I know this because I added a small piece of my own code that I have not included here that gave my the print out of nSum and nCount).
My question is why doesn’t nCount equal 3? I understand the ‘for’ loop goes through four iterations but as the first number is 0 so why isn’t 3 the final number in this variable?
How many numbers are stored in your array? It looks like you have 4 numbers stored, so nCount will be 4.

The for loop is counting from 0 to 3.
Also watch out for integer division with code like this. Integer division truncates, so 9/11 is zero for example. If there is an average involved make the type of nsum and the function return double
If nCount entered that routine as 4 ... then it will stay as 4 thoughout. You don't change its value anywhere.

Are you sure that you are asking about the right variable?
I think I have worked out my problem. The program asks for a negative number to be entered to end the input cycle of numbers so this becomes the 5th number entered but number four in the array. For example I entered the numbers 5,4,5 and 6 and -1 to end the loop that asks for numbers to be entered (the negative number is not included as an entered number, it just acts as the prompt to leave that loop) resulting in this:

0 = 5
1 = 4
2 = 5
3 = 6
4 = -1

I apologise for the lack of info to work this out but I was hesitant to put all the code in as it would have been a lot, next time I will try to be clearer in my questions. Thank you everyone for your help.
Where the numbers come from is irrelevant from the point of view of displayArray and averageArray. As long as the values for nValues (the array of all the values) and nCount (the number of values) are passed to the functions correctly they will do their work correctly (assuming they are correctly implemented).

1
2
3
4
int arr[] = {2, 5, 8};
displayArray(arr, std::size(arr));
std::cout << "average: " << averageArray(arr, std::size(arr)) << "\n"; 
  0=2
  1=5
  2=8
average: 5
Last edited on
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <iostream>



//void displayArray(int* nValues, int nCount){
void displayArray(int nValues[100], int nCount){
  for(int i=0; i<nCount; i++) {                     
    std::cout.width(3);                             
    std::cout<<i<<"="<< nValues[i] <<std::endl; 
  }
  std::cout << sizeof(nValues)/sizeof(int*)<< '\n';
  //std::cout << std::size(nValues) << '\n';
}

int main () {
  int arry[] = {4, 5, 36};                        
  std::cout << sizeof(arry)/sizeof(int)<< '\n';
  std::cout << std::size(arry) << '\n';
  displayArray(arry, std::size(arry));
}


I didn't want to respond to this, but I think it's important.

The first parameter for displayArray is nonsense, because it will always degrade to a pointer to an int.

Please correct me if I'm wrong. I'm not much of C++ programmer.
Last edited on
 
void displayArray(int nValues[100], int nCount)
is equivalent to
 
void displayArray(int nValues[], int nCount)
which is equivalent to
 
void displayArray(int* nValues, int nCount)
Regardless of how you write it the argument that is passed is always an int*.

So it seems to be a very poor way to write the first parameter.
Last edited on
I agree that writing the parameter as int nValues[100] is unnecessary and misleading because the number 100 is simply ignored.

int* nValues has the advantage that it more clearly shows that the argument is passed as a pointer.

int nValues[] has the advantage that it more clearly shows the intention, that the argument is supposed to be (a pointer to the first element in) an array rather than a pointer to a single object.
Last edited on
Yes - you can't even use std::size(nValues) because nValues is treated as a pointer. I also prefer [] for 1-d array and * for a pointer.
you can't even use std::size(nValues) because nValues is treated as a pointer

Which is why std::size should be prefered over the sizeof hack. It's better to get a compilation error that you can easily fix right away rather than a silent bug.
Last edited on
:) Always prefer a compilation error to a run-time issue...

Why not just use std::array (or std::vector) instead of a c-style arrays. Then there's no need to pass a separate param for number of elements (which could be incorrect)... Teach these first before c-style arrays.

Last edited on
Don't try this at home!

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>

struct Iint {
   int value;
   Iint* next = 0;
};


double average( Iint* nValues )
{
   double sum = 0;
   int num = 0;
   for ( ; nValues; nValues = nValues->next )
   {
      sum += nValues->value;
      num++;
   }
   return sum / num;
}


int main()
{
   Iint* nValues = 0;
   for ( int i : { 2, 6, -3, 5 } ) nValues = new Iint{ i, nValues };
   std::cout << average( nValues ) << '\n';
}


2.5

Don't try this at home!


Just a simple linked list (without freeing used memory)...
seeplus wrote:
Just a simple linked list (without freeing used memory)...


Sighs!

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
#include <iostream>

struct Iint {
   int value;
   Iint* next = 0;
   Iint( int v, Iint* n ) : value( v ), next( n ) {}
};


void byeBye( Iint* n )                 // Just for @seeplus
{
   if ( n ) { byeBye( n->next );   delete n; }
}


double average( Iint* nValues )
{
   double sum = 0;
   int num = 0;
   for ( ; nValues; nValues = nValues->next )
   {
      sum += nValues->value;
      num++;
   }
   return sum / num;
}


int main()
{
   Iint* nValues = 0;
   for ( int i : { 2, 6, -3, 5 } ) nValues = new Iint( i, nValues );
   std::cout << average( nValues ) << '\n';
   byeBye( nValues );
}


Last edited on
Why not just use std::array (or std::vector) instead of a c-style arrays.

As a function parameter a pointer and a size is more flexible because it can accept a varying number of elements from either raw "c-style" arrays, std::array or std::vector.
Last edited on
C++20: we can use std::span; it has minimal overhead and is safer than passing a pointer and a size.
https://en.cppreference.com/w/cpp/container/span
@Peter87

It may be a better choice. The question is why they're teaching new programmers to use c-style arrays.

These writers and professors can teach basic programming principles just fine using std::array and std::vector.

Instead they repeat the lie c++ is too hard for beginners.

I'm not a C++ programmer, but it was an excellent first for me.

The college kid at work was surprised when I wrote him a python program. I had to admit it was the first python program I ever wrote.
Last edited on
It may be a better choice. The question is why they're teaching new programmers to use c-style arrays.

These writers and professors can teach basic programming principles just fine using std::array and std::vector.


std::vector is an entirely c++ entity (good though it is). std::array I would find very difficult to find a use for.

"Basic programming principles" suggest that you should use something (a) simple and (b) relatively language-agnostic ... a c-style array fits the bill. (It's also about the only type of array you could use in mixed-language processing).
Pages: 12