# 6.3 — Arrays and loops

Consider the case where we want to find the average test score of a class of students. Using individual variables:

That’s a lot of variables and a lot of typing -- and this is just 5 students! Imagine how much work we’d have to do for 30 students, or 150.

Plus, if a new student is added, a new variable has to be declared, initialized, and added to the totalScore calculation. Any time you have to modify old code, you run the risk of introducing errors.

Using arrays offers a slightly better solution:

This cuts down on the number of variables declared significantly, but totalScore still requires each array element be listed individually. And as above, changing the number of students means the totalScore formula needs to be manually adjusted.

If only there were a way to loop through our array and calculate totalScore directly.

Loops and arrays

In a previous lesson, you learned that the array subscript doesn’t need to be a constant value -- it can be a variable. This means we can use a loop variable as an array index to loop through all of the elements of our array and perform some calculation on them. This is such a common thing to do that wherever you find arrays, you will almost certainly find loops! When a loop is used to access each array element in turn, this is often called iterating through the array.

Here’s our example above using a for loop:

This solution is ideal in terms of both readability and maintenance. Because the loop does all of our array element accesses, the formulas adjust automatically to account for the number of elements in the array. This means the calculations do not have to be manually altered to account for new students, and we do not have to manually add the name of new array elements!

Here’s an example of using a loop to search an array in order to determine the best score in the class:

In this example, we use a non-loop variable called maxScore to keep track of the highest score we’ve seen. maxScore is initialized to 0 to represent that we have not seen any scores yet. We then iterate through each element of the array, and if we find a score that is higher than any we’ve seen before, we set maxScore to that value. Thus, maxScore always represents the highest score out of all the elements we’ve searched so far. By the time we reach the end of the array, maxScore holds the highest score in the entire array.

Mixing loops and arrays

Loops are typically used with arrays to do one of three things:
1) Calculate a value (e.g. average value, total value)
2) Search for a value (e.g. highest value, lowest value).
3) Reorganize the array (e.g. ascending order, descending order)

When calculating a value, a variable is typically used to hold an intermediate result that is used to calculate the final value. In the above example where we are calculating an average score, totalScore holds the total score for all the elements examined so far.

When searching for a value, a variable is typically used to hold the best candidate value seen so far (or the array index of the best candidate). In the above example where we use a loop to find the best score, maxScore is used to hold the highest score encountered so far.

Sorting an array is a bit more tricky, as it typically involves nested loops. We will cover sorting an array in the next lesson.

Arrays and off-by-one errors

One of the trickiest parts of using loops with arrays is making sure the loop iterates the proper number of times. Off-by-one errors are easy to make, and trying to access an element that is larger than the length of the array can have dire consequences. Consider the following program:

The problem with this program is that the condition in the for loop is wrong! The array declared has 5 elements, indexed from 0 to 4. However, this array loops from 0 to 5. Consequently, on the last iteration, the array will execute this:

But scores[5] is undefined! This can cause all sorts of issues, with the most likely being that scores[5] results in a garbage value. In this case, the probable result is that maxScore will be wrong.

However, imagine what would happen if we inadvertently assigned a value to array[5]! We might overwrite another variable (or part of it), or perhaps corrupt something -- these types of bugs can be very hard to track down!

Consequently, when using loops with arrays, always double-check your loop conditions to make sure you do not introduce off-by-one errors.

Quiz time

Question #1

Print the following array to the screen using a loop:

Hint: You can use std::size (as of C++17) or the sizeof() trick (prior to C++17) to determine the array length.

Show Solution

Question #2

Given the array in question 1:

Ask the user for a number between 1 and 9. If the user does not enter a number between 1 and 9, repeatedly ask for an integer value until they do. Once they have entered a number between 1 and 9, print the array. Then search the array for the value that the user entered and print the index of that element.

You can test std::cin for invalid input by using the following code:

Show Solution

Question #3

Modify the following program so that instead of having maxScore hold the largest score directly, a variable named maxIndex holds the index of the largest score.

Show Solution

 6.4 -- Sorting an array using selection sort Index 6.2 -- Arrays (Part II)

### 368 comments to 6.3 — Arrays and loops

• Sam

Here is my solution for Question #2

• - Line 13: Initialize your variables with brace initializers.
- Compile-tile constants should be `constexpr`.
- Declare 1 variables per line for better readability.
- Inconsistent formatting. Use your editor's auto-formatting feature.

• Sam

fixed!

• Formatting is still inconsistent

Looks good otherwise. I'd put line 13 right after line 9.

• Anastasia

Hi!
Wouldn't it be better to initialiaze the variable maxScore (Loops and arrays, 2d example, line 10) with the value of the first (0) index of the array, instead of the value 0 and then start the for loop from the second (1) index?

for example:

While using 0 as the initial value the first check (in the if condition) will always be true in case the array consists of positive numbers and if all the values are negative the result won't make much sense. Something I am missing here?

• If you're sure that `scores[0]` exists, ie. `numStudents > 0`, your version is indeed better.

• Samira Ferdi

Hi Alex and Nascardriver!

This is my getNumber(). What do you think?

• Hello!

- Line 5, 10, 12, 13: Magic numbers/strings. Declare constants for min and max or pass them as arguments.
- Line 6, 13, 23: You don't need `<<` here. String literals can be appended at compile-time by writing them one after the other.

Using `<<` will append the strings at run-time.

• Samira Ferdi

So, you mean that MIN = 0 and MAX = 9, so in line 10 would be

?

and for line 5 would be

?

• Use those constants/variables in the strings too. If 2 values refer to the same thing, they should be represented by the same constant/variable in code.

• Samira Ferdi

Thank you! I see.

• Nirbhay

Typo in Arrays and off-by-one errors:

"The problem with this program is that the **condition(al)** in the for loop is wrong!"

• Alex

Fixed. Thanks!

• Samira Ferdi

Hi Alex! I just wanna thank you because you've covered the debugging section. I don't realize that I did a off-by-one error and I was confused about the result and I don't know what is happen. But, I remember your suggestion to used debugger and finally I've found that I did off-by-one error. So, I just wanna thank you for your hardwork!

• Alex

Awesome! Glad you were able to make good use of the debugging capabilities.

• Marc

I'm just wondering if there is a way to view our input stream and buffer via Visual Studio. I've seen some example that utilize <fstream>. IE, opening a file and checking locals while debugging. It's from my curiosity how we utilize iostate and check user input if its a valid type.

• v5l

Hi, I'm on VS2019 and it looks like that

doesn't need to be included to use

My only include is

and it works perfectly.

• This behavior isn't guaranteed, don't rely on it. If you use something, include its header.

• - Initialize your variables with brace initializers.
- Limit your lines to 80 characters in length for better readability on small displays.
- Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
- Inconsistent formatting.
- Use single quotation marks for characters.
- `while` wants a bool. Use `while (true)`.
- Use ++prefix unless you need postfix++.
-

• Thanks nascardriver

• Jonathan

Attempt to arrange array in ascending order!

• Looks good, just a couple of notes:
- Line 13-14 can be replaced with `std::swap`.
- You're comparing signed- to unsigned integers. If your compiler supports it already, use `std::ssize`, otherwise add a cast to int.

If you need to sort an list in the future, you can use `std::sort` (Unless you're asked to do it manually).

• Torraturd

This is what I got

• Hi!

* Initialize your variables with brace initializers.
* Limit your lines to 80 characters in length for better readability on small displays.
* Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
* Use single quotation marks for characters ('\n' instead of "\n", ' ' instead of " ").

Looks good otherwise!

• Lorenz

Quiz 1: you create a const int arrayLength for storing the length of the array,
does it make any sense to skip it and calculate the size of the array in the for loop?

• You can skip it.

• Jim

You can skip it, but in Visual Studio I get a warning due to the different variable types:

"Comparison of integers of different signs: 'int' and 'size_t' (aka 'unsigned int')"

It's not really an issue here given that you are controlling the value of i in the loop and know it isn't negative, but it's a good thing to be aware of. For example, try changing i to -1 and watch what happens:

For me, the comparison doesn't work and my code inside the for loop is skipped.

So, you can use a cast to make sure the comparison will work:

which is essentially what creating a new variable for the size is doing:

Just something to keep in mind

Also keep in mind -- sometimes legibility is more important than being concise or "clever" with your code. Even though I might be able to write things in a very concise manner, it might not be the best approach if it makes my code harder to understand. So, even though calling std::size in the for loop initializer might save a line of code, you might decide sticking the size in a separate variable and then using that variable in the for loop communicates your intent a bit more clearly.

• > For me, the comparison doesn't work and my code inside the for loop is skipped.
Comparing signed to unsigned promotes the signed type to unsigned. -1 in unsigned is the maximum value of the unsigned type, hence your loop doesn't execute.

If you create a separate variable, you should still add a cast. If you used brace initialization, you would've received a warning similar to that caused by the comparison.

• Matt

Hey guys, any help understanding this (assuming it's some sort of syntax issue):

The following does not compile and instead gives error:

However, this compiles just fine and outputs the correct value 5 to the console:

• Uniform initialization disallows narrowing conversions (eg. unsigned to signed, double to int, etc.). Use a @static_cast to tell the compiler that you're doing it on purpose.

• paparob76

Hi,

In Quiz question 2, the program won't compile. I entered it as above, but I get the following errors:
||=== Build: Debug in 6.3.2 (compiler: GNU GCC Compiler) ===|
C:\Users\robert\6.3.2\main.cpp||In function 'int main()':|
C:\Users\robert\6.3.2\main.cpp|14|error: this 'if' clause does not guard... [-Werror=misleading-indentation]|
C:\Users\robert\6.3.2\main.cpp|16|note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'|
||=== Build failed: 1 error(s), 0 warning(s) (0 minute(s), 0 second(s)) ===|

This is referring to the lines:

lines 7 and 10.

What does guard mean in this context?
Thanks!

• Alex

In this context, guard means subject to the condition of the if statement.

I think it may be complaining about your indentation for the "std::cin.ignore" line, as the indentation makes it look like this line is part of the if statement, when in actuality it's not.

• paparob76

Hi Alex,

Thanks for the explanation. I noticed that in question 2, the bit of code you gave for testing the number input is not the same code as in the answer given. There are {} in the if statement. Once i put those in it worked fine.

• Alex

Yeah, I see why I did that. In the question for #2, it's only talking about how to handle the error case -- but in the sample solution, it's useful to remove any extra data in both the error and non-error cases, so the second line was moved out so it always runs. I extended the comment in the solution to provide more context that this was intentional.

• Arthur

• * Line 29, 34: Initialize your variables with brace initializers. You used copy initialization.
* Line 18-23 should be moved above line 14.
* Inconsistent Formatting.

Your code is getting better. Keep it up!

• paparob76

Hi,

In quiz question 1, i get an error at build time saying that 'size' is not part of 'std'. I #included <iterator> and am using CodeBlocks, which is C++17 compatible. Any ideas?

Thanks

• Arthur

I had the same problem/error in code::blocks , I followed the instruction from

https://solarianprogrammer.com/2017/11/22/install-codeblocks-gcc-windows/

I used the described 'simple approach'  to get gcc8 and installed the nuwen Mingw distribution , then followed the instructions to direct code::blocks to use the updated compiler.

there was instruction at the start of the tutorial to enable c++17 in 'installing an IDE' the instructions indicate if it dose not work to try updating compiler.

• paparob76

Ok, but Im running Windows7, and am limited to the 32bit compiler. It says in the website that gcc 8 is 64 bit. I installed CodeBlocks as instructed on this site and set the options to the C++17 standard. Is there an updated 32 bit gcc compiler i should use instead of the one that came with CodeBlocks?
Thanks!

• Arthur

im not sure on that one , I am on windows 7 but 64 bit, I could look around a little but was having trouble myself finding an updated version. Ill post back if I find something...

• Arthur

what I found is "MinGW-w64 - for 32 and 64 bit Windows"

https://mingw-w64.org/doku.php

not sure if it is the same as what I 'installed' so cant really vouch for it or anything , just what I found. I imagine it is very similar though and that 'installing' is actually unpacking it on root drive  C:\

https://sourceforge.net/projects/mingw-w64/

• paparob76

Thanks, i will try that. I will post if it worked.

• paparob76

Hi,
So i downloaded and installed MinGW from sourceforge. The problem now is that when i try to setup the compiler path, it changes the \ to / when trying to find the exe in the bin folder. I suspect this is why it cannot run the exe. Any help would be appreciated.
Thanks.

• Arthur

did you find and follow installation directions? for mingw ? when I did the setup in code blocks I only had to point code::blocks to the installation directory directly on C:\ then slightly change the names for the 'program files' you just type the names of the exe in you dont have to find each one.
this is what it looks like in mine

"Global Compiler Settings"

Toolchain executables

Selected compiler
GNU GCC Compiler

compilers instalation directory------------

C:\MinGW  (use the ... button and show code blocks where it is)

C compiler:               gcc.exe
C++ compiler:             g++.exe

debugger:   GDB/CDB debugger default

Resource compiler:    windres.exe
Make program:            make.exe

you dont have to navigate and find each exe , they should be in the bin directory and Code::blocks should be able to find them there try the names I listed here I got them from the first website instruction I posted, what I installed is MinGW & it should be exactly the same for you except perhaps the installation directory.

• paparob76

Thanks for all your help. I pointed CB to all the right paths and exe. I followed the online  install procedures. What concerns me is CB changing the \ to a / in the error message. Im signing up for CB forum to figure this out. This isn't the place for this problem.
Thanks again.

• Arthur

no problem , I was going to suggest the codeblocks forum if you still had troubles. I would suggest that you compare the global compiler settings to what I posted, though I suppose it could be different for 32 bit.  you may want to know though that my log console displays a forward slash in a successful build , right in front of the exe.

"C:\Program Files (x86)\CodeBlocks/cb_console_runner.exe"

• paparob76

Hi Arthur,

I just want you, and any others that have this problem, to know that these settings are correct. I was using the i686-w64-mingw32-c++ and the other programs associated with the i686-w64 names. Silly, I guess. When I pointed to the right \bin and programs everything was ok. I even checked the version of g++ and it is 8.1. As a side note, I was reading your posts on my cell phone, so I couldn't understand when you posted the paths etc, since i could only see 4 characters per line. Now I'm on my computer and after reading what you posted I changed everything and it worked. Thanks!

• Arthur

good that you got it sorted out , I had to get code::blocks working at this part of the tutorial too so who knows maybe the post here will help someone else...

• J

Hello!

Here's what I came up with for quiz 2. Probably a silly question, but when declaring a variable inside a for-loop, is it better practice to give it a uniform initialization or a copy initialization?

• Hi!

* Line 86: Initialize your variables with brace initializers. You used copy initialization.
* Line 75: Don't pass 32767 to @std::cin.ignore. Pass @std::numeric_limits<std::streamsize>::max().
* Line 66, 81, 83: Booleans are false or true.
* @matchValue: The program should still work properly when modifying @arrayOfNumbers. Have a look at the solution.

> is it better practice to give it a uniform initialization or a copy initialization?
Always use uniform initialization.

• Kol

For quiz3 I came up with this code:

• Envy

The 4th code snippet that should determine the maxScore mentions in line 6 that the <iterator> header is required for std::size() but it isn't included after/before <iostream>.

• Alex

Fixed. Thanks!

• Output : 5

Output : 20
Why this happens.

• You're accessing indexes that don't exist until you run into memory that's 0.

• Yes i know that. But why it stops at 20 when the array is const. But at 5 when its not. Does tge presence of const affects where it encounters \0.

• The value of the memory after @arr and whether it exists or not is undefined.
Every change in your code, compiler or system could change the outcome.

• FarKiD

Hi, in quiz 2, there are no values considered for array [0], also most of my inputs, don't match the array numbers, for example when I put 8, it gives back 4, or when I put 2 in std::cin, it puts 5 on screen, instead of 7

• Arrays start at index 0

• FarKiD

I do understand, but consider these 3 times I ran the program :

https://imgur.com/a/ZY1fiTN

• That's the expected behavior. What don't you understand about it? Which output did you expect?

• FarKiD

isn't 2 supposed to give 7? how does it even give back 5?
and I just put 4, and I get a 0? I don't even have a zero in my array!

• It prints the index of the number you give it, not the other way around.

• FarKiD

I think I got it, thanks for your time, you are awesome :)

• Max Morgan

For quiz 2, I tried the method below. Guess was only known in the scope of my first function. Is there a way to bring the value of guess into main so that I can reference it in this second for loop? EDIT: I moved guess above the function and it works, but I know this is bad because it's a global variable. Thank you Nascar and Alex

• * Line 22, 24, 26, 30, 36: Initialize your variables with brace initializers. You used copy initialization.
* Line 5: Initialize your variables with brace initializers.
* Line 38: Limit your lines to 80 characters in length for better readability on small displays.
* Remove the ifs in @main

@enterNum never returns false, ie. the return value is unused. Change it to return @guess.

• buront

In the first example of loops and arrays,I tried to initialize const int by using {std::size(scores)}.
But it get an error about size.However, using = means no error.
Why is this?

• Alex

This happens because std::size returns an object of type size_t. A size_t is an unsigned value, whereas your integer is signed. Uniform initialization disallows narrowing conversions, and converting an unsigned value to a signed one is considered a narrowing conversion. Copy initialization still works because narrowing conversions are allowed.

• buront

Thanks Alex!

• magaji::hussaini

My solution snippets:
quiz1 & quiz2:

quiz3

• Quiz 2
* Line 5, 6: Initialize your variables. Enable compiler warnings and fix them.
* Line 8: @while wants a bool, give it a bool.
* Line 13

is easier to understand
* Use your editor's auto-formatting feature

Quiz 3
Looking good, apart from the formatting and that "if" floating around

I see you're using short ints. If you want to save memory, you might as well use @std::int_fast8_t.

• magaji::hussaini

Thanks!  ...copy that.

• Shawn

On quiz 3.

for (int student = 0; student < numStudents; ++student)

couldnt it be:

for (int student = 1; student < numStudents; ++student)

since you have maxIndex = 0; (skips first cycle).

• Alex

Yep. Quiz answer updated. Thanks for pointing that out.

• CoderC++

Why my shit broken?

#include <iostream>
#include <string>
using namespace std;

int main()
{
//Declaring Variables
int userDays;
float userTemp;

//Declaring the array
int array1[365] = {}; //Array for the Year

/*
DO { Please input temp for
Specific Day (1 - 365)

Enter 999 to quit.
}

While (user days <365)
enter temp
enter 999 to quit

*/

do
{
cout << "Please enter the Day you are inputing (1-365)" << endl;
cin >> userDays;

//Line Spacing
cout << "\n";
cout << "\n";

cout << "Please enter the Temperature" << endl;
cin >> userTemp;
cout << "\n\n";

array1[userDays] = userTemp;
}

while ((userDays <= 365) && (userDays >= 1));
for (int j = 0; j < 366; j++)
{
if (array1[j] != 0)
{
cout << "Day: " << userDays << endl;
cout << "Temperature: " << array1[userDays] << endl; //displays information

cout << "\n\n";
}
}

//prints the array from Void
return 0; //kills variables
}

• Sohini Ghosh

I tried to solve the 2nd question with a slightly different approach, but it is producing an infinite loop. Can you please help me out?

The solution to your problem is in lesson 1.4.

• marvix

Hi! This is my solution for quiz 2, any advice?

• Hi Marvix!

* Line 5: Use a while(true) loop
* Line 11: Don't pass 32767. Read the documentation of @std::basic_istream::ignore
* Line 23, 31, 32, 33: Initialize your variables with uniform initialization
* @findIndex will crash if @array doesn't contain @ins. You're checking @ins before calling @findIndex, so this won't happen. Either add a comment to @findIndex explaining that the caller must verify that the array contains @ins or pass the array's length to @findIndex and check there.
* Line 23: unsigned will cause you more trouble than good
* Line 24: Comparison of short to int
* Use ++prefix unless you need postfix++
* Line 24:

• hoon

Hi

• Hi Hoon!

* Initialize your variables with uniform initialization.
* Don't pass 32767 to @std::cin.get. Read the documentation or the lesson that introduced it.
* Missing trailing line feed in line 41

Structure and logic look good

• hoon

Have a good night

• Nayab Anjum

Did i do something wrong in below code for question 2?
Also both mine and your code doesnot work if we type any character(e.g 'e'). How do we fix this error? Kindly reply asap.

• Hi Nayab!

* Don't use "using namespace"
* Initialize your variables with uniform initialization
* Don't pass 32767 to @std::cin.ignore. See the documentation.
* Use ++prefix unless you need postfix++
* Line 31 is not part of the conditional block. Use the auto-formatting feature of your IDE and use curly brackets for if-statements.
* Inconsistent use of '\n' and @std::endl

> mine and your code doesnot work if we type any character
What do you mean by "doesn't work"? What do you expect the program to do, what does it actually do?

• My solution
2.
#include<iostream>

int main()
{
int number;
while(true)
{
std::cout<<"Enter an number between 1 and 9: ";
std::cin>>number;
if((number>=1)&&(number<=9))
break;
if(std::cin.fail())
{
std::cin.clear();
std::cin.ignore(32767,'\n');
}
}
int array[]={1,2,3,4,5,6,7,8,9};
int length=sizeof(array)/sizeof(array[0]);
for(int index=0;index<length;++index)
std::cout<<array[index]<<" ";
std::cout<<"\n";
for(int index=0;index<length;++index)
{
if(array[index]==number)
std::cout<<"The index of element "<<number<<" is "<<index<<std::endl;
}

return 0;
}
3.
#include<iostream>

int main()
{
int scores[]={84,92,76,81,56};
const int numStudents=sizeof(scores)/sizeof(scores[0]);

int maxIndex=0;

for(int student=0;student<numStudents;++student)
{
if(scores[student]>scores[maxIndex])
maxIndex=student;
}
std::cout<<"The best score was stored in index "<<maxIndex<<"\n";

return 0;
}

• Hi!