1

I am a C++ beginner. Currently learning vectors. I am writing a program that calculates the average given the grades. The program I have written accepts only 5 grades. How can I modify the program so that the vector space is automatically allocated for any number of grades? That is, at the 'Enter grades:' prompt, I should be able to enter any number of grades and the average for those grades have to be calculated.

#include <iostream> #include <vector> using namespace std; int main() { vector<int> grades; int grade; cout << "Enter grades: "; for(int i = 1; i <= 5; ++i) { cin >> grade; grades.push_back(grade); } double total = 0; for(int i = 0; i < grades.size(); ++i) { total += grades[i]; } double avg; cout << "Average = " << total / grades.size() << endl; return 0; } 
2
  • You need to initialize total. Commented Jan 2, 2015 at 19:07
  • 1
    Also: Avoid declarations at the beginning of a function. Instead declare and define a variable, just before use. Commented Jan 2, 2015 at 19:11

3 Answers 3

3

It looks like you want the end-of-line (the user hitting "enter") to signify the end of the grades.

This code will pull that entire line into its own stream object which - unlike cin - will eventually reach an end.

std::string grades_full_line; std::getline(std::cin, grades_full_line); std::stringstream grade_stream(grades_full_line); 

You can now change your loop to use the stream itself as a conditional. It will evaluate to false when you reach the end.

for( grade_stream >> grade; grade_stream; grade_stream >> grade ) { grades.push_back(grade); } 
Sign up to request clarification or add additional context in comments.

8 Comments

Yes. This is exactly what I want. Unfortunately, I am unaware of what a stringstream is? I will research about it and get back.
@Babbzzz a stringstream is an iostream object - like cin - that uses a string as its source data as opposed to the keyboard or a file.
As far as I understand, the grades are entered as a string. That entire line is put into a stream. But what exactly happens 'for(grade_stream >> grade; grade_stream; grade_stream >> grade)' here? How can I do numerical computations on a string? How do I separate the grades?
@Babbzzz Try the code, it works. If you have more questions about how for loops or streams work, I'd recommend posting a new question. This site isn't really geared to forum-style discussions or interactive tutorials. Good luck!
I included the sstream directive and used this code. It did not work for me. :( Error: /home/abhilash/tutorial/cpp/gradesString/main.cpp|11|error: no matching function for call to ‘std::basic_string<char>::push_back(std::string&)’|
|
1

Vectors are pretty cool in that they can grow as needed (if you're using the push_back method as you are). So essentially, you're already there! Your code will handle as many grades as you can put in (within reason).

What you will have to change is to change your for loop to loop the dynamically selected number of times:

Change:

for(int i = 1; i <= 5; ++i) { cin >> grade; grades.push_back(grade); } 

to

cout << "How many grades" << endl; cin >> numOfGrades; for(int i = 0; i < numOfGrades; ++i) { cin >> grade; grades.push_back(grade); } 

This will loop the right number of times and get you what you want.

4 Comments

I want to avoid the use of numOfGrades as a user input.
Then your best bet is to use some sort of token value that will indicate that no more input is going to be sent (maybe -1). Have the loop keep accepting input and adding it to the vector until it receives a -1. This would need to be changed to either a while loop or more appropriately a do loop instead of a for loop.
Sorry, not that as well. Please take a look at the answer by Drew Dormann. I am looking for something of that sort.
Cool, that one works if all the grades are entered in a single line. The line can be as long as you want, but you can only delimit entries whitespace. If this is acceptable, then it works. Otherwise, you'll have to fall back to some other method.
0

You need to figure out a loop termination condition - some way for the user to let you know that he is done entering the grades. Once you incorporate that into the bounds on your push_back loop, your code, as it stands, works. Lets say you decide that a grade of -1 implies that the user is done entering grades. Then the following modification is all you need:

while(cin >> grade and grade != -1)//EDITED { grades.push_back(grade); } 

EDIT : As cdhowie mentions, you should sanitize the input received.

3 Comments

This will enter an infinite loop if the user enters something other than a number. The loop condition should be while (cin >> grade && grade != -1). (This also allows you to remove the zero-initialization of grade.)
Thank you. I have got an idea. The user enters the grades by separating it with a space. And when Enter is pressed, the user has finished entering. Can I use the Enter as a call for action in my program? How do I find the number of grades that have been entered using size()?
In that case, you would want to use getline to read in a full line and then tokenize it using istringstream. Here's an example showing the use of the latter.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.