Difficulty understanding for loop iteration results

Pages: 12
Jun 16, 2022 at 4:14am
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?
Jun 16, 2022 at 4:29am
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.
Jun 16, 2022 at 5:11am
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
Jun 16, 2022 at 5:11am
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?
Jun 16, 2022 at 5:36am
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.
Jun 16, 2022 at 6:42am
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 Jun 16, 2022 at 6:46am
Jun 16, 2022 at 9:20pm
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 Jun 16, 2022 at 10:10pm
Jun 16, 2022 at 10:18pm
 
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)
Jun 16, 2022 at 10:39pm
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 Jun 16, 2022 at 10:48pm
Jun 17, 2022 at 6:07am
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 Jun 17, 2022 at 6:11am
Jun 17, 2022 at 8:58am
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.
Jun 17, 2022 at 9:06am
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 Jun 17, 2022 at 9:07am
Jun 17, 2022 at 9:17am
:) 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 Jun 17, 2022 at 9:24am
Jun 17, 2022 at 9:23am
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

Jun 17, 2022 at 9:30am
Don't try this at home!


Just a simple linked list (without freeing used memory)...
Jun 17, 2022 at 9:51am
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 Jun 17, 2022 at 9:54am
Jun 17, 2022 at 9:56am
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 Jun 17, 2022 at 9:56am
Jun 17, 2022 at 12:00pm
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
Jun 17, 2022 at 12:16pm
@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 Jun 17, 2022 at 12:17pm
Jun 17, 2022 at 12:31pm
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