0

I've tried a lot of things and keep changing this code but I can't get it to stop require two inputs before it accepts a value for 'score'. Also, I've been having trouble finding a way to stop the cin from 'score' and 'answer' from allowing the user to hit enter without entering a value. The only way I've seen to do that is to accept them both as strings, but I was hoping to avoid that.

#include<iostream>
#include<iomanip>
#include<limits>**strong text**

using namespace std;

//void enterdata(string*, int*);

int main(){
// string names[];
// int testscores[];
 string name;
 int score;
 char answer;

 cout<<"This program asks the user to enter a list of names and test scores,"<<endl;
 cout<<"then sorts the list into ascending order according to the scores"<<endl;
 cout<<"and calculates the average test score."<<endl;

// enterdata(names, testscores);

 do{
   cout<<"Please enter a name: ";
   getline(cin, name);
   while(name.empty()){
    cout<<"No entry detected. Please enter a name: ";
    getline(cin, name);
   }
   cout<<name<<endl;
   cout<<"Please enter a test score: ";
   cin>>score;
   while(!(cin>>score) || score<0){
    cin.clear();
       cin.ignore(numeric_limits<streamsize>::max(), '\n');
       cout<<"Input not valid. Only positive integers will be accpeted."<<endl;
       cout<<"Please enter a test score: ";
   }
   cout<<score<<endl;
   cin.sync();
   cout<<"Would you like to enter another student name and test score? [y/n] ";
   cin>>answer;
   while(answer!='y' && answer!='n'){
       cout<<"Input not valid. Only y or n will be accepted."<<endl;
       cout<<"Would you like to enter another student name and test score? [y/n] ";
       cin>>answer;
   }
   cout<<answer<<endl;
   cin.sync();
  } while(answer == 'y');

 return 0;
}
BigB63
  • 23
  • 7
  • Possible duplicate of [Why does std::getline() skip input after a formatted extraction?](https://stackoverflow.com/questions/21567291/why-does-stdgetline-skip-input-after-a-formatted-extraction) – user0042 Oct 01 '17 at 19:04
  • I don't know. It seems to be acting differently than that question. It isn't skipping the input. The program won't move to it's next step without accepting a value. As long as I input a positive number and hit enter, the second time I enter a number and hit enter, cin accepts a value and moves on to the next step in the program. – BigB63 Oct 01 '17 at 19:35
  • You are reading the integer twice in these two lines - cin>>score; while(!(cin>>score) || score<0){ Also, be careful when switching between cin and readline - when reading integer using cin, it does not read the newline, so it gets picked up by the next readline(). – Harmeet Oct 01 '17 at 20:21
  • Okay, @Harmeet, so is that not the appropriate statement to run error checking? The statement !(cin>>score) seems to be catching the error for me every time I enter something other than a number. Say, I hit the letter f for a test score, it throws back the invalid statement immediately and tells me to reenter a test score. I only seem to have the double input issue when I try to input integers. Is there some other statement/condition I should be entering? – BigB63 Oct 01 '17 at 20:54

1 Answers1

2

The error is here:

while(!(cin>>score) || score<0){ //------ Here!
    cin.clear();
    cin.ignore(numeric_limits<streamsize>::max(), '\n');
    cout<<"Input not valid. Only positive integers will be accpeted."<<endl;
    cout<<"Please enter a test score: ";
}

You are using the input stream again when you say cin>>score, and therefore the program prompts for more input! Think of it like a function call (hint: operator overloading!). I presume you wrote this (that is, !(cin>>score) because you want to test the stream for errors. In a small program like this, I wouldn't sweat it (school exercise?)

As to the second part of you question, about hindering enter from having an effect (the annoying newline), I'm quite sure you can't do this easily. I'd politely ask whether you really want to spend time on this though (and if it is a school exercise, everyone else is going to have the same issue)

Here is the cleaned and corrected code:

#include <iostream>
#include <iomanip>
#include <limits>
#include <string>

using std::cout;
using std::cin;
using std::string;
using std::endl;

//void enterdata(string*, int*);

int main() {
  //string names[];
  //int testscores[];
  string name;
  int score;
  char answer = 'y';

  cout << "This program asks the user to enter a list of names and test scores," << endl;
  cout << "then sorts the list into ascending order according to the scores" << endl;
  cout << "and calculates the average test score." << endl;

  //enterdata(names, testscores);

  while(answer == 'y') {
    cout << "Please enter a name: ";
    std::cin >> name;
    while (name.empty()) {
        cout << "No entry detected. Please enter a name: ";
        std::cin >> name;
    }
    cout << name << endl;
    cout << "Please enter a test score: ";
    cin >> score;
    while (score<0) {
        cin >> score;
        cin.clear();
        cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        cout << "Input not valid. Only positive integers will be accpeted." << endl;
        cout << "Please enter a test score: ";
    }
    cout << score << endl;
    cin.sync();
    cout << "Would you like to enter another student name and test score? [y/n] ";
    cin >> answer;
    while (answer != 'y' && answer != 'n') {
        cout << "Input not valid. Only y or n will be accepted." << endl;
        cout << "Would you like to enter another student name and test score? [y/n] ";
        cin >> answer;
    }
    cout << answer << endl;
    cin.sync();
 } 
return 0;
}
  • Yeah, this is for a school project. I've been trying to get the main do-while loop right before I do the rest of it. I'll probably have to change some of the declarations once I put it in with the rest of the program. The project is on pointers and it requires me to dynamically allocate an array/arrays containing names and test scores then, using pointers, sort the array/arrays in ascending order according to test score while keeping the names associated with their respective test scores. then I have to cout the sorted list of names and scores and cout the average test score. – BigB63 Oct 01 '17 at 20:33
  • Anyway, as part of the project, we have to do fail checks for the inputs and call for reentry of valid data instead of allowing the program to terminate on cin errors. – BigB63 Oct 01 '17 at 20:36
  • Also, I appreciate the effort to help, but the code you gave me isn't working either. On Eclipse, it's only asking me for an integer value instead of printing any of my couts, and on C++ Shell, it's endlessly reprinting the first value of the name and a test score of 0 when I give an invalid response when entering a test score. – BigB63 Oct 01 '17 at 20:46
  • @BigB63 I doubt you're required to handle any other errors than invalid input, for example names containing numbers or numbers containing letters. But if you really have to, you can make it error-proof by using 3 member functions of 'cin' and exceptions. That'll handle all the errors the input stream could introduce. To see all the possible errors, see the overview of member functions and exceptions at [cplusplus.com](http://www.cplusplus.com/reference/istream/istream/) (The "state" row of the large table). –  Oct 01 '17 at 20:51
  • @BigB63 I just copied the code over to VS2017 and it compiles and runs fine even with level 4 warnings. Are you sure you copied it correctly? –  Oct 01 '17 at 20:59
  • I just copied and pasted it directly into a test.cpp I have set up to run as an independent program. Maybe there's something different about Eclipse and Mingw than what is going on in VS2017. Unfortunately, I'm not familiar with VS yet, and I just got back into school for after a long gap. The project is due tonight so I don't have the extra time to spend getting to know VS. – BigB63 Oct 01 '17 at 21:06
  • Is the only way to get it to reject an an empty value (just hitting enter), to declare all the inputs as string and use getline then convert the number values back to integers? – BigB63 Oct 01 '17 at 21:09
  • So just started a new project in VS2017 and entered your code and it's working there, but does not do an empty check on the name, which is a requirement in the project. From what I understand, the user isn't supposed to be allowed to hit enter without a value and it just move to the next line without asking them to re-enter a value. – BigB63 Oct 01 '17 at 21:16
  • You're probably building to release, which removes many debug-mode safeguards, and thus the loop-problem. To prevent the infinite loop when the input type and data type mismatch, you can call cin.fail(), which returns a bool (that is, while (cin.fail() || score<0)). –  Oct 01 '17 at 21:20
  • The empty check on the name string is redundant because the flow of the program will never continue to the empty check before a value is entered, and thus, the string is not empty. See how each time you hit enter without having typed anything, the cursor just moves to the next line? –  Oct 01 '17 at 21:25
  • It's also possible that Eclipse is just a pain to work with. It is currently set to build to debug, but it hasn't thrown anything. This also isn't the first project I've had where I have to save my work, exit Eclipse and restart just to get it to stop throwing errors or executing code I've already changed or erased. – BigB63 Oct 01 '17 at 21:25
  • Do you build before you run the program? Usually, "start debugging" will both build and launch it, but it's not always so. –  Oct 01 '17 at 21:28
  • So just tried it in eclipse an I remember why I wasn't using cin.fail(). I don't know what to include up top to make it work. Eclipse isn't recognizing it. – BigB63 Oct 01 '17 at 21:30
  • I usually save and build every time, but my run button is set to save and build every time a change has been made to the program. – BigB63 Oct 01 '17 at 21:33
  • cin is a global object of type istream, defined in . If you have cin in scope, you'll have its member function fail(). Or? –  Oct 01 '17 at 21:36
  • It was telling me it was fail, but then I noticed I had an extra parentheses at the end of fail. That fixed it. – BigB63 Oct 01 '17 at 21:46
  • So now that I have that working, anytime I enter a letter, it screws up the program and throws out a value of 0 for the test score after telling me my input was invalid. – BigB63 Oct 01 '17 at 21:53
  • I'll continue this with PM's, I have an improved solution.Will you join me at https://chatstep.com/#CPP ? –  Oct 01 '17 at 22:01