简体   繁体   中英

How can I convert for loops into for-each loops?

My task is to convert my for loops into for-each loops.

The task begins with creating a two dimensional array 6x30. This represents 6 classes of 30 students each. Each position in the array contains a random number between 55 and 100 which represents a student score.

Next I display that array to the console.

Next I calculate the average score of each class.

Next I find the highest average among the 6 classes and display that to the screen.

I am using Xcode on MacBook Pro.

Question: How can I properly convert my for loops into for-each loops?

My code is below:

#include <iostream>
#include <iomanip>

using namespace std;

const int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;

void bubbleSort(int arr[], int n){
    for (int i = 0; i < n - 1; i++) {
        for (int j = 0; j < n - i - 1; j++) {
            if (arr[j] < arr[j + 1])
                swap(arr[j], arr[j + 1]);
        }
    }
}

void classGradeGeneration() {
    int arrayOne[NUM_CLASSES][NUM_STUDENTS_PER_CLASS], classAverage[NUM_CLASSES];
    //Generating random average student scores until array filled
    for (int classNumber = 0; classNumber < NUM_CLASSES; classNumber++) {
        for (int column = 0; column < NUM_STUDENTS_PER_CLASS; column++) {
            arrayOne[classNumber][column] = rand() % 46 + 55;
        }
    }
    //Displaying array of student scores
    for (int classNumber = 0; classNumber < NUM_CLASSES; classNumber++) {
        cout << "Class " << classNumber + 1 << ": ";
        for (int column = 0; column < NUM_STUDENTS_PER_CLASS; column++) {
            cout << setw(3) << arrayOne[classNumber][column] << " ";
            classAverage[classNumber] += arrayOne[classNumber][column];
        }
        cout << endl;
    }
    cout << endl;
    int averageScore, averageOfClasses[NUM_CLASSES];
    //Displaying average class scores
    for (int temp = 0; temp < NUM_CLASSES; temp++) {
        averageScore = classAverage[temp] / NUM_STUDENTS_PER_CLASS;
        cout << "Class " << temp + 1 <<" Average score: " << averageScore << endl;
        averageOfClasses[temp] = averageScore;
    }
    cout << endl;
    bubbleSort(averageOfClasses, NUM_CLASSES); // Sorting average scores highest to lowest

    cout << endl;
    cout << "The highest average score is: " << averageOfClasses[0];
    cout << endl;    
}

int main () {
    srand(time(NULL));
    classGradeGeneration();
    cout << endl << endl;
}

Below is a sample output:

样本输出

You may use range-based for with std::array since C++11

constexpr int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;
std::array<std::array<int, NUM_STUDENTS_PER_CLASS>, NUM_CLASSES> arr;
for (/*const*/ auto& ln : arr) {
    std::cout << "LINE" << std::endl;
    for (/*const*/ auto& elem : ln) {
        std::cout << "elem" << std::endl;
    }
}

or for_each if you want

std::for_each(arr.begin(), arr.end(), [](/*const*/ auto& line) {
    std::cout << "LINE" << std::endl;
    std::for_each(line.begin(), line.end(), [](/*const*/ auto& elem) {
        std::cout << "elem" << std::endl;
        });
    });

But I prefer range-based for in this case.

If you use c-style array then for_each arguments will be pointers, not iterators.

int arr[NUM_CLASSES][NUM_STUDENTS_PER_CLASS], classAverage[NUM_CLASSES];
std::for_each(std::begin(arr), std::end(arr), [](/*const*/ auto& line) {
    std::cout << "LINE" << std::endl;
    std::for_each(std::begin(line), std::end(line), [](/*const*/ auto& elem) {
        std::cout << "elem" << std::endl;
        });
    });

So your code may look like this

constexpr int NUM_CLASSES = 6, NUM_STUDENTS_PER_CLASS = 30;
std::array<std::array<int, NUM_STUDENTS_PER_CLASS>, NUM_CLASSES> arr;

// set random values
for (auto& ln : arr) {
    for (auto& elem : ln) {
        elem = std::rand() % 100;
    }
}

// calculate
float avgScore = 0.0F;
for (const auto& ln : arr) {
    const auto avgGroupScore = std::accumulate(std::begin(ln), std::end(ln), 0.0F) / (std::end(ln) - std::begin(ln));
    avgScore = std::max(avgScore, avgGroupScore);
    std::cout << "avg group score=" << avgGroupScore << "; current avgScore=" << avgScore << std::endl;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM