0

In my class we recently got introduced to STL vectors. My professor has given us a program that uses arrays, and we are to convert it to use std::vectors instead. He would like us to use iterators, so we're not allowed to use square brackets, the push_back member function, or the at member function. Here's one of the for loops from the program I have to convert:

void readData(Highscore highScores[], int size)
{
    for(int index = 0; index < size; index++)
    {
        cout << "Enter the name for score #" << (index + 1) << ": ";
        cin.getline(highScores[index].name, MAX_NAME_SIZE, '\n');
        
        cout << "Enter the score for score #" << (index + 1) << ": ";
        cin >> highScores[index].score;
        cin.ignore();
    }
    cout << endl;
}
`

I'm just not quite understanding how to convert them. so far, I was kind of able to get this: for (vector <Highscore> :: iterator num = scores.begin(); num < scores.end(); num++)for the for loop. It doesn't quite make sense to me so I was hoping I can get some more tips or even more information on how to convert them. I don't want an answer, simply just a tip. Thank you! (if its of any help, this is the program I am having to convert and these are the four headers we have to use

void getVectorSize(int& size);
void readData(vector<Highscore>& scores);
void sortData(vector<Highscore>& scores);
vector<Highscore>::iterator findLocationOfLargest(
                                const vector<Highscore>::iterator startingLocation,
                                const vector<Highscore>::iterator endingLocation);
void displayData(const vector<Highscore>& scores);

above are the headers that have to be used (having to use these instead of the programs headers)

#include <iostream>
using namespace std;

const int MAX_NAME_SIZE = 24;

struct Highscore{
    char name[MAX_NAME_SIZE];
    int score;
};

void getArraySize(int& size);
void readData(Highscore highScores[], int size);
void sortData(Highscore highScores[], int size);
int findIndexOfLargest(const Highscore highScores[], int startingIndex, int size);
void displayData(const Highscore highScores[], int size);

int main()
{
    Highscore* highScores;
    int size;
    
    getArraySize(size);
    
    highScores = new Highscore[size];
    
    readData(highScores, size);
    sortData(highScores, size);
    displayData(highScores, size);
    
    delete [] highScores;
}



void getArraySize(int& size){
    cout << "How many scores will you enter?: ";
    cin >> size;
    cin.ignore();
}



void readData(Highscore highScores[], int size)
{
    for(int index = 0; index < size; index++)
    {
        cout << "Enter the name for score #" << (index + 1) << ": ";
        cin.getline(highScores[index].name, MAX_NAME_SIZE, '\n');
        
        cout << "Enter the score for score #" << (index + 1) << ": ";
        cin >> highScores[index].score;
        cin.ignore();
    }
    cout << endl;
}



void sortData(Highscore highScores[], int numItems) {
    for (int count = 0; count < numItems - 1; count++){
        swap(highScores[findIndexOfLargest(highScores, count, numItems)],
             highScores[count]);

    }
}



int findIndexOfLargest(const Highscore highScores[], int startingIndex, int numItems){
    int indexOfLargest = startingIndex;
    
    for (int count = startingIndex + 1; count < numItems; count++){
        if (highScores[count].score > highScores[indexOfLargest].score){
            indexOfLargest = count;
        }
    }
    return indexOfLargest;
}



void displayData(const Highscore highScores[], int size)
{
    cout << "Top Scorers: " << endl;
    for(int index = 0; index < size; index++)
    {
        cout << highScores[index].name << ": " << highScores[index].score << endl;
    }
}
moi
  • 467
  • 4
  • 19
  • Is this for use after the function you posted, or instead of? Since it seems like perhaps instead of, your vector won't have elements before you "read" them, so don't iterate over it. Use a similar for loop with a maximum size, and then consider `push_back` and the Highscore constructor. – chrisb2244 Aug 22 '21 at 05:06
  • Is it a requirement to use the same arguments and return types for each function? (Apart from vectors instead of arrays?) For example, could you use `std::vector readData(int size)`? Or should that function remain as a void return and pass the vector by reference? – chrisb2244 Aug 22 '21 at 05:18
  • @chrisb2244 the function should remain as a void return passing the vector through reference. – Eduardo Munoz Alvarez Aug 22 '21 at 05:21
  • @JamIT My apologies, he does not wanting us to use this as he emphasized that he would like us to work with iterators. Sorry for the confusion. – Eduardo Munoz Alvarez Aug 22 '21 at 05:35
  • 1
    That (and the explanation) are an absolute must for inclusion in the question. Otherwise people will stumble across the question and its answers in the future and play a few rounds of WTF?!? – user4581301 Aug 22 '21 at 05:38
  • @EduardoMunozAlvarez, _has given us a program to convert from arrays to STL vectors_. **A program** is not an array, so you can't convert **a program** to STL vector. So is your question about converting arrays to STL vectors or is it about changing assigned functions so that they make use of STL vectors instead of arrays? – Enlico Aug 22 '21 at 05:45
  • @Enlico Yes, the question was converting arrays to STL while changing the function. Once again, sorry. – Eduardo Munoz Alvarez Aug 22 '21 at 06:12
  • Unless you know the number of entries to read beforehand, the requirement is a bit nonsensical; however if you do, just `resize()` the vector to the desired size and you're good to use iterators. You could even use a ranged for loop which technically uses iterators, but I'm pretty sure that isn't the expected solution: `size_t index = 0; for (auto& highScore : highScores) { ++index; ... cin.getline(highScore.name, MAX_NAME_SIZE, '\n'); ... }`; you could also use `emplace_back`, but this is even less likely to be accepted, since it's not using iterators and is close to `push_back` ;) – fabian Aug 22 '21 at 08:13
  • I've tried to revise a bit to better reflect the impressions I've gotten from the comments. Feel free to revert (then improve) any parts that were off the mark. – JaMiT Aug 22 '21 at 21:30

3 Answers3

3

You maybe looking for one of two things. If you want to add something to a vector, the function is push_back

vecScores.push_back(value) ; //in a for loop.

https://www.cplusplus.com/reference/vector/vector/push_back/

If you want to add something to a map, you could just use the form of

mapScore[index]=value ; // in a for loop.

https://www.cplusplus.com/reference/map/map/operator[]/

kalyanswaroop
  • 403
  • 4
  • 5
  • I forgot to mention this in the post, but im restricted from using square brackets, the push_back() function, the at() function, etc. Would there perhaps be another way? – Eduardo Munoz Alvarez Aug 22 '21 at 05:15
  • You could use vecScores.assign For an example, see https://www.cplusplus.com/reference/vector/vector/assign/ See the third.assign part of the example. Hopefully, that's allowed in your assignment ! (Pun intended) – kalyanswaroop Aug 22 '21 at 05:19
  • Well, at the least, you'll have to use vecScores.resize to set the size. Then, you could get the iterator using iter = begin() and set using *iter. You could do ++iter to go the next and then set that, etc, all the way till != end(). See https://www.cplusplus.com/reference/vector/vector/begin/ Wish you all the best. I'm out for the weekend ! – kalyanswaroop Aug 22 '21 at 05:52
2

Probably your professor wants you to write something like this:

void readData(std::vector<Highscore>& highScores)
{
    for (auto it = highScores.begin(); it != highScores.end(); ++it) {
        cout << "Enter the name for score #" << std::distance(highScores.begin(), it) << ": ";
        cin.getline(it->name, MAX_NAME_SIZE, '\n');

        cout << "Enter the score for score #" << std::distance(highScores.begin(), it) << ": ";
        cin >> it->score;
        cin.ignore();
    }
    cout << endl;
}

where it is the iterator that's incremented via ++it from highScores.begin() to just before highScores.end(); then you access the members of the highScores's element "pointed by" it via it->member.

Here's a complete demo.


By the way, considering how much your professor likes void(some_type&) functions (and using namespace std;, if that was not your own idea), I would doubt you have much to learn from him. You better buy a good book.

Enlico
  • 23,259
  • 6
  • 48
  • 102
1

I would do it like this, also get used to typing std:: Why is "using namespace std;" considered bad practice?

Also be careful with signed/unsigned, be precise about it. If something can't have a negative value use unsigned types (or size_t)

#include <iostream>
#include <string>
#include <vector>

struct HighScore
{
    std::string name;
    unsigned int score;
};

// use size_t for sizes (value will always >0)
std::vector<HighScore> GetHighScores(size_t size)
{
    std::vector<HighScore> highScores;
    std::string points;

    for (size_t index = 0; index < size; index++)
    {
        HighScore score;
    
        std::cout << "Enter the name for score #" << (index + 1) << ": ";
        std::cin >> score.name;
            
        std::cout << "Enter the score for score #" << (index + 1) << ": ";
        std::cin >> points;

        // convert string to int
        score.score = static_cast<unsigned int>(std::atoi(points.c_str()));
    
        highScores.push_back(score);
    }
    std::cout << std::endl;

    return highScores;
}


int main()
{
    auto highScores = GetHighScores(3);
    return 1;
}
Pepijn Kramer
  • 9,356
  • 2
  • 8
  • 19