Search

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 conditional 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

1) Print the following array to the screen using a loop:

Hint: You can use the sizeof() trick to determine the array length.

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:

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.

Quiz solutions

1) Show Solution

2) Show Solution

3) Show Solution

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

217 comments to 6.3 — Arrays and loops

  • Tony

    Hi Alex, nice tutorials! I have made the second exercice and I've done something a bit different. Could you tell me if this way is good or should I change my code?

    EXERCISE TWO:

    • Alex

      Since it's such a short program, doing everything in main() is okay. But you should practice splitting things into functions, or you'll run into problems when you start tackling larger programs.

      • Tony

        Thank you Alex, I'll practice these functions indeed. Had to read this chapter again because this is my first time ever learning a programming language. Many users said c++ was a bad language to start with, but your tutorials are very well written and documented with a lot of examples and quizzes. That's just amazing and this language is just... fantastic!

        I guess I'll keep on reading and practicing now... Keep going on this amazing job!

  • James Ray

    Solution for 3:

  • James Ray

    My solution for 1 and 2:

  • I have a quick question about this line

    Can you please explain why is it

    Why would we need to put

    Is it important?

    Thank you

    • Alex

      array size = array length * element size.

      Using algebra, we can rearrange this equation: array length = array size / element size. sizeof(array) is the array size, and sizeof(array[0]) is the element size, so our equation becomes array length = sizeof(array) / sizeof(array[0]). If you don't divide by the element size, then your length will be set the array size, which is incorrect.

  • Ian

    Sup Alex,

    Quick comment for Q3.

    In this for loop, would it be more proper to start the search from element 0 instead of element 1?

    Or did I miss something?

    Cheers,
    Ian

    • Alex

      Yes, my mistake. One common "trick" when looking through an array for the largest number is to set your largest number to the first element rather than 0, which allows you to start your search at element index 1 instead of 0. I was originally going to do that here, but shifted tactics for simplicity and forgot to update the array indices.

      Thanks for pointing the error out.

  • B1

    hi Alex
    about determine the (Length) of the array
    by this method

    how using the (array itself) + (index 0) will give you the array’s length ?
    i don’t get this concept, i see it so bizarre
    can you please explain this mechanism ?

    • Alex

      Taking sizeof(array) gives you the size of the entire array, which is equal to length * element size.
      Taking sizeof(element) gives you element size.

      So by dividing (length * element size) by (element size), we're left with the array length.

      • B1

        i didn't understand your replay quite well
        so i gone to the compiler and then understand the whole thing

        sizeof(array) = 20
        sizeof(array[0]) = 4
        20 % 4 = 5
        now i realize what was the cause of my confusion
        it's the sizeof operator
        cause i know it's for (Memory) computing,
        so how computing the memory gives you the length of array ?
        but i know now it's possible to know the length with it also
        if used well

        thank you so much Alex
        and sorry for the trouble

        • Alex

          Again, total array size = element size * length. Using basic algebra, if we know any two of those values, we can calculate the third. We know array size (sizeof(array)) and element size (sizeof(array[0])), so we can calculate length. length = array size / element size.

  • Soumil

    In question 2, when we input a character other than an integer, causing the input to fail, how is the while condition to execute the loop again satisfied? Since the input failed, the variable number isn't assigned any value. So how is it compared to the numbers 1 and 9?

    • Alex

      You are correct -- that was a mistake on my part. Variable number needs to be initialized to 0, so that it has a deterministic value if input fails. I've updated the example accordingly. Nice catch!

  • Satwant

    In the second problem,inside the DO loop, need a else statement for input validation. if not we get multiple lines for inputs like "45.55"
    Here is full code:

  • Mar Kos

    Hi Alex,
    as Ye Kyaw Tun (on July 16, 2016) I´m quite confused about the 3rd quiz: "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."
    This sounds to me like the goal is to print the index and NOT the score. Otherwise - since we don´t print or save the index anywhere - it´s technically exactly the same thing as maxScore (changing a few names doesn´t do a thing)! So what´s the point / what am I missing?

    • Alex

      The goal is still to print the largest score. In the provided program, maxScore holds the actual largest score. In the answer you're supposed to write, maxIndex is intended to hold the array index of the largest score. If you have the array index of the largest score, you should be able to print the largest score.

  • Kanwar Ujjwaldeep Singh

    hi alex!
    In QUIZ Q2. can't we use goto statement if the input is invalid as its more compact and readable.

    Also because it is more understandable than this

    // if the user entered an invalid character
            if (std::cin.fail())
            {
                std::cin.clear(); // reset any error flags
                std::cin.ignore(32767, 'n'); // ignore any characters in the input buffer
            }

    if not...please tell and explain this above statemnts too.
    Thanks!

    • Alex

      Where would you goto?

      Arbitrarily jumping to a prior point in the code generally isn't considered more readable -- it may understandable in trivial cases, but it doesn't scale well. That's why most programmers avoid its use altogether.

  • Brian

    GREAT tutorials!

    In the solution to Quiz 3, shouldn't the for-loop initialize the student to 1?
    As its written, I think the for-loop always starts with the comparison

  • Ekanem

    Hi. lol, i'm very new to this. My code works but it seems terribly simple compared to the solution in number 2. Just for future reference abd learning purposes, is there a reason why I shouldn't write code like this again in future?

    int main()
    {
        const int arrayLength(9);
        int array[arrayLength] = { 4, 6, 7, 3, 8, 2, 1, 9, 5 };
        
    tryAgain:
        cout<<"Please pick a number between 1 and 9: "<<endl;
        int x;
        cin>>x;
        
        if (x < 1)
        {
            goto tryAgain;
        }
        else if (x > 9)
        {
            goto tryAgain;
        }
        else
            cout<<array[x-1]<<endl;
        
        return 0;
    }

    • Alex

      Use of goto should generally be avoided if a normal loop will suffice (such as a do loop, do while, for loop, etc...). The resulting code will generally be more readable and maintainable. It's not as big a deal with simple code such as this, but better to start learning good habits now.

  • Matt

    Under "Loops and arrays", in the second code example, you wrote:
    "int maxScore = 0; // keep track of index of our largest score".

    The comment is inaccurate. maxScore only keeps track of the biggest score, not the index for the biggest score.

  • "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."

    Hey Alex,

    if we try to access value [5], which we haven't declared, don't we get the default 0 value?

    • Alex

      No. The array only initialized elements 0 through 4. Element 5 is not initialized because it's not part of the array, and was not provided an initializer.

  • Aditya Upadhyay

    Hey Alex,
    Is it possible to make 2-D arrays in which every row has different number of column.

    For example a[5][x]
    like 1 row has 4 columns
    2 row has 6 columns.

    And also pls move this leave a comment section to the top of comments.

  • Eugene

    Hey Alex,

    just wanted to thank you for the work that you have done.
    These lesson a very well explained compared to other sites where it seams that the guys who wrote them lessons wanted to write em the most quickest way. You take your time to explain correctly things as they should be explained, with examples & stuff.

    We appreciate your effort.

  • KIRPAL SINGH A/L HARWAN SINGH

    i was trying out this code: why is the value of array index 10 true when the size of array is only 10 and not 11.

    #include<iostream>
    using namespace std;

    bool check(int getNumber, int from_setNumber_index)
    {
        return getNumber==from_setNumber_index;
    }

    int main()
    {
        int setNumbers[10]={0,1,2,3,4,5,6,7,8,9};

        int getNumber;
        cout<<"\nPlease enter a number : ";
        cin>>getNumber;

        int index=0;

        for(index; index<=10; index++)
        {
            bool check_getNumber = check(getNumber, setNumbers[index]);
            cout<<"num "<<index<<": "<<check_getNumber<<"\n";

            if(check_getNumber==1)
            {
                cout<<"correct \n";
            }

        }

        return 0;
    }

    • Alex

      You're walking off the end of your array and accessing whatever is in memory beyond the last element of the array. Because you're assigning this to a bool, that garbage value is being interpreted as a bool. Since all non-zero values evaluate to true, and the garbage value is more likely than not to be non-zero, you'll most often get a value of true (but occasionally you may get a false).

      • KIRPAL SINGH A/L HARWAN SINGH

        refering back to my question...

        bool check_getNumber = check(getNumber, setNumbers[index]);

        the above function will make a copy of data from  check(getNumber. setNumber[index]) and paste the values in the parameter below

        bool check(int getNumber, int from_setNumber_index)

        in this function i returned getNumber==from_setNumber_index  which should be false when it reads array index 10 which is beyond the size of the array. So if the array index 10 has garbage value such as "85693" when compared with getNumber it should return 0...

        sorry for my broken english... can you help me?

  • Kattencrack Kledge

    In Quiz #2, is it still good practice if I searched the index of the inputted number while printing my array at the same time, even if it costs me little extra space in the CPU?:

  • Ye Kyaw Tun

    Dear Admin,

    In quiz number 3, when i am practizing, i found that i  the last line which produces output is wrong.  
    std::cout << "The best score was " << scores[maxIndex] << '\n';

    only variable "maxIndex" is required to get the index of largest score.

    Thank you very much,
    Best Regards,
    Ye Kyaw Tun

    • Alex

      The sample program that you are given to modify prints the max score. So your program that uses maxIndex should also print the max score (not the index of the max score).

  • Lam Gia Khang

    I don't know what the number 32767 mean in this code:

    Can we use another number?

    • Alex

      It means to ignore up to 32767 characters, which is more than you're likely to ever encounter before you run into a '\n'. You can use a different number if you want, but there isn't much point.

  • Huiying

    #include<iostream>
    using namespace std;

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

        int minscore=100;
        for(int student=0;student<numstudents;++student)

                if (scores[student]<minscore)

                minscore=scores[student];
            cout<<"The best scores are"<<minscore<<endl;

    return 0;
    }

    Hi, this is my code to find the minimum score in an array, but say if i want to find the k lowest score(where k can be any unknown integer), then how would i modify the code above to do it?

  • jo

    Hey, first things first: great tutorial, learned quite a lot in a short time! Thanks a lot!

    I did not read all the comments, so I hope this was not mentioned before:

    Imho the first example under "Loops and arrays" has a little mistake:

    The first line should be:  int scores[] = { 84, 92, 76, 81, 56 };
    instead of:                int scores[numStudents] = { 84, 92, 76, 81, 56 };

    since arrray size is given by the initalization list and we calculate numStudents in the second line, which itself includes a little typo:

    There is a 's' missing in the sizeof(score[0]) at the end of that line.

  • Darren

    I feel I'm getting a bit picky with this one. It's about code maintainability.

    With the following code:

    in order to add a new test score to the scores array you would have to both increase the numStudents as well as adding the new score. What would happen if you did one but not the other of those things? If you just added an entry to the array initialiser then the compiler will complain about the list having too many values. This is good we like compiler errors as we can generally fix them quickly. However, if we just increased the numStudents value then the code will compile without error or warning; it is syntactically correct. However, the averageScore will be computed incorrectly as we have actually added a score of zero to the array. This is a subtle bug and may not be picked up on straight away.

    What we want to happen is that someone should able to add an entry to the scores array initialiser and have the rest of the program work out the details. This can be done in the following way:

    By allowing the compiler to automatically detect the length of the array (using empty square braces) we can add entries to scores with impunity, and by using the sizeof(array)/sizeof(array[0]) trick the program computes the length of the array to be used elsewhere. The subtle bug has been avoided. But what if some numpty deletes all the initialiser entries? Not a problem as we get a compiler error (good thing) about invalid use of an empty initialiser on an array with an unspecified bound.

    Now the reason I said I was getting picky is that you wouldn't use primitive arrays to do this in the first place once you learn about the standard template library (STL) container classes e.g. vector, list, and so on. (Also some may find the sizeof(array)/sizeof(array[0]) trick somewhat "hacky").

    • Darren

      Btw Alex, I'm commenting here because I'm refreshing my knowledge about C++ and I am impressed with your tutorials. There's a lot of fundamental stuff and best practices I had forgotten that I've only been reminded about by reading your blog.

      (was that just the right amount of ass kissing or too much?:))

      • Alex

        One foot on each side. 🙂

        Unfortunately, C++ is a nuanced language, which necessitates a lot of best practices and caveating.

    • Alex

      You make a great point. I've updated the examples to derive the size rather than declare it explicitly, since it reduces the number of things that need to be modified if the array size is changed.

  • Jatin

    I think there is a typo in the solution of problem 1.You wrote "using namespace std;" and then later in the loop you wrote "std::cout". If you wrote std::cout there should not be any need of "using namespace std;".

  • Nyap

    if you put a number thats out of the range of an array, could you mess with other programs memory? and if so, could I write a virus that makes itself start on boot and c̶o̶m̶p̶l̶e̶t̶e̶l̶y̶ to a certain extent ruin the host computer?

    • Alex

      Not on a modern operating system. If you try and access memory not owned by your process, the OS will terminate your application.

  • Pooja

    Hello Alex,

    Once again thanks for such a nice tutorial.
    Have been stuck in a do-while condition check. Can you please let me know what mistake I am doing?

    As far as I enter valid inputs (Eg: 0,1,2,3...) it works fine. When I enter an invalid input (Eg: loop, example...) it runs into a infinite loop even if I enter a valid input in next step.

    Output looks like:

    Please help me to find out what condition check has to be put for while loop here.

    • Alex

      This code, defining a variable length array:

      is illegal in C++ (though some compilers will allow it since it's legal in C99).

      When I fixed that issue and ran your program, I didn't get an infinite loop. The other problem I see is that array[i] is undefined if the input from cin fails, but you're passing it as a parameter to bIsNumberValid. That's likely to lead to unexpected behaviors.

      Finally, you should get rid of the variable prefix names (b, u32), especially for functions.

  • Deondre

    Hey Alex,

    Thanks for the tutorials, they're really helpful!

    If I remember correctly, couldn't you also use .at() with arrays to ensure that the index is valid? For example if you had a five element array;
    [int array[5] = {1, 2, 3, 4, 5 };]
    and attempted to access the 6th element in the array, if you used [array[5] = 6;], you'd get unexpected results, but if you used [array.at(5) = 6] the compiler would throw an error message without altering any of the data in that memory slot.

  • ZNI

    how can i solve this problem ? Guys, please help meeee T^T

    Write a program that use a structure named as Book containing members ISBN, year, price and title. The program able to prompt the user to enter items for three different books and calculate the total price and price after discount. Discount is given as below:
    •    If the total price is greater than or equal to 100, the discount is 20%
    •    If the total price is between RM50 and RM99, the discount is 10%
    This program have three functions:
    1.    Functions to receive input about the books
    2.    Functions to calculate the total price and discounted price
    3.    Function to print the summary of books and value that need to pay by the customer
    To solve the problem you need to use looping control structure and array.

    • Elpidius

      Hey ZNI, try this:

      Here are some sub-chapters (aside from this one) that you can refer to if you have any trouble with the code mentioned above:
      http://www.learncpp.com/cpp-tutorial/24a-fixed-width-integers/
      http://www.learncpp.com/cpp-tutorial/4-4b-an-introduction-to-stdstring/
      http://www.learncpp.com/cpp-tutorial/47-structs/
      http://www.learncpp.com/cpp-tutorial/57-for-statements/
      http://www.learncpp.com/cpp-tutorial/61-arrays-part-i/

      I hope this helps you!

      • Rachel Murray

        Hi, after going through all tutorials from start to this page I found your solution to question 2 confusing you haven't covered cin.fail(), cin.clear() or cin.ignore() from a learning point of view I found this very confusing when you could have shown a solution using all the topics covered in previous tutorials. Will the solutions to other quiz be similar in this regard?

        • Alex

          For the most part, I try not to use concepts that I haven't explained in depth. In this case, I'm providing you with a fairly small snippet of code that has comments indicating what each line does. You don't have to understand how it works to use it, just what it does. This might be a little challenging, but I'm okay with that.

          I do think it's worth writing a lesson about handling invalid input prior to this lesson though. I'll look into that.

  • saeid

    in quiz2 i write my own code to show who got that score from tutorials that i learned from you:

    is this good coding or i wrote useless code?

    • derpasaurus

      I would change some things, such as they will result in issues. Firstly, use a switch statement for getName(int):

      Also, the do while part:

      will have issues. What if you type 0, for Saeed or -8? Change it to

    • derpasaurus

      Forget the part about the do while. Im mistaken.

  • Aymen

    For the second task would the following still be correct:

    Its less code but I don't want to compromise on functionality. I then sent it to cout after the for loop.

Leave a Comment

Put all code inside code tags: [code]your code here[/code]