0
#include <iostream>
using namespace std;
int main(){
    //set variables
    string name1;string name2;string name3;string n1;string n2;string n3;
    int age1; int age2; int age3;

    //get names and ages
    cout << "Who Is The First Student?"<< endl;
    getline(cin, name1); //name 1
    cout << "What is " << name1<< "'s Age?"<< endl;
    cin >> age1; // age 1
    cout << "Who Is The Second Student?"<< endl;
    getline(cin, name2); //name 2
    cout << "What is " << name2<< "'s Age?"<< endl;
    cin >> age2; //age 2
    cout << "Who Is The Third Student?"<< endl;
    getline(cin, name3); // name 3
    cout << "What is " << name3<< "'s Age?"<< endl;
    cin >> age3; //age 3

    // gets modified names
    n1 = name1.substr(2, name1.size() -3);
    n2 = name2.substr(2, name2.size() -3);
    n3 = name3.substr(2, name3.size()-3);
    // Output formatting
    cout << "Name             Age             Modified"<<endl;
    cout << name1<< "             "<<age1<<"             "<<n1<<endl;
    cout << name2<< "             "<<age2<<"             "<<n2<<endl;
    cout << name3<< "             "<<age3<<"             "<<n3<<endl;
    return 0;
}

The output asks the first question which is for the name of the first student but it outputs as this:

Who Is The First Student?- John Doe- What is John's Age?- 19- Who Is The Second Student?- What is 's Age?-

It is skipping the user input of the second student's name and instantly asking for the age but I don't know why this is happening, is there something wrong with my code or do I have the formatting incorrect? I believe that I used the getline function correctly but I may be incorrect and unaware of it being skipped over by a more important function.

  • it will be beacause one of these `n1 = name1.substr(2, name1.size()-3);` results in an incorrect start offset (<0 or > length) or length – pm100 Jan 29 '23 at 23:39
  • `cin` on a `string` will take input up to the first space or newline. So `name1` will be set to `John`, and your program will attempt to read in `Doe` as `age1`. Use `std::getline` to get lines. However, you can't mix `std::cin >>` and `std::getline` easily. I'd recommend against trying at your level to try to mix them. The best fix action I can recommend is to use names without spaces. – JohnFilleau Jan 29 '23 at 23:41
  • as per here https://en.cppreference.com/w/cpp/string/basic_string/substr – pm100 Jan 29 '23 at 23:41
  • Inputting `Doe` as `age1` btw will set `std::cin` to an error state, which will prevent all future input until you clear the error state. The EASIEST fix here is to use names without spaces. – JohnFilleau Jan 29 '23 at 23:42
  • [What is a debugger and how can it help me diagnose problems?](https://stackoverflow.com/questions/25385173/what-is-a-debugger-and-how-can-it-help-me-diagnose-problems) – Jesper Juhl Jan 29 '23 at 23:55

2 Answers2

0

The std::string::substr() man page says this about the exception you are seeing:

Parameters
   pos   -  position of the first character to include
   count -  length of the substring

Exceptions
   [throws] std::out_of_range if pos > size()
Jeremy Friesner
  • 70,199
  • 15
  • 131
  • 234
0

The main problem of the program is that the operator >> reads only one word.

That is for example in these statements

cout << "Who Is The First Student?"<< endl;
cin >> name1; //name 1

You entered a string that contains two words "John Doe". But the operator >> reads only the first word "Jphn" in the variable name1.

So in the next input statement

cout << "What is " << name1<< "'s Age?"<< endl;
cin >> age1; // age 1

an error occurred because instead of a number the input buffer contains the word "Doe".

So as a result the variables name1, name2, and name3 do not contain what you are expecting. And these statements

n1 = name1.substr(2, name1.size()-3);
n2 = name2.substr(2, name2.size()-3);
n3 = name3.substr(2, name3.size()-3);

produce the run-time error.

Instead of the operator >> you should use standard function std::getline.

Here is a demonstration program based on the code of your program that shows what is the reason of the error

#include <iostream>
#include <string>

int main()
{
    std::string name1, name2;
    int age1;

    //get names and ages
    std::cout << "Input 3 Names Below:" << std::endl;
    std::cout << "Who Is The First Student?" << std::endl;
    std::cin >> name1; //name 1
    std::cout << "What is " << name1 << "'s Age?" << std::endl;
    std::cin >> age1; // age 1
    std::cout << "Who Is The Second Student?" << std::endl;
    std::cin >> name2; //name 2

    std::cout << "name1 = " << name1 << '\n';
    std::cout << "name2 = " << name2 << '\n';
}

The program output is

Input 3 Names Below:
Who Is The First Student?
John Doe
What is John's Age?
Who Is The Second Student?
name1 = John
name2 =

As you can see due to the error of reading a data in the variable age1 (the buffer contains the string "Doe") the object name2 is empty. So if you will use it in this statement

n2 = name2.substr(2, name2.size()-3);

then the runtime error will occur.

Here is another demonstration program that shows how the standard function std::getline can be used in your program.

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

int main()
{
    std::string name1, name2, name3;
    int age1, age2, age3;

    //get names and ages
    std::cout << "Input 3 Names Below:" << std::endl;

    std::cout << "Who Is The First Student?" << std::endl;
    std::getline( std::cin, name1 ); //name 1
    std::cout << "What is " << name1 << "'s Age?" << std::endl;
    std::cin >> age1; // age 1
    std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

    std::cout << "Who Is The Second Student?" << std::endl;
    std::getline( std::cin, name2 ); //name 2
    std::cout << "What is " << name2 << "'s Age?" << std::endl;
    std::cin >> age2; //age 2
    std::cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n' );

    std::cout << "Who Is The Third Student?" << std::endl;
    std::getline( std::cin, name3 ); // name 3
    std::cout << "What is " << name3 << "'s Age?" << std::endl;
    std::cin >> age3;

    std::cout << "name1 = " << name1 << '\n';
    std::cout << "name2 = " << name2 << '\n';
    std::cout << "name3 = " << name3 << '\n';
}

The program output is

Input 3 Names Below:
Who Is The First Student?
John Dow
What is John Dow's Age?
20
Who Is The Second Student?
Mary Poppins
What is Mary Poppins's Age?
21
Who Is The Third Student?
Bob Fisher
What is Bob Fisher's Age?
25
name1 = John Dow
name2 = Mary Poppins
name3 = Bob Fisher
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • this has nothing to do with the exception that gets thrown, this is due to and out of range on the substr ca – pm100 Jan 29 '23 at 23:52
  • 1
    @pm100 You are mistaken. – Vlad from Moscow Jan 29 '23 at 23:53
  • OK - with that specifc input, but if user enters "ed" as first name even with getline it will still fail . OP has to check lengths – pm100 Jan 30 '23 at 01:18
  • I used getline and it kind of works. the first output works and I can put in the full name without an error but after the first age is put in, it asks for both the name and age of the second person simultaneously and I am not sure why this is happening – jack is carbon Jan 30 '23 at 01:39
  • @jackiscarbon After using the operator >> to enter an age the input buffer contains the new line character '\n' and the next call of getline reads an empty string. You need to remove the character line std::cin.ignore( std::numeric_limits::max(), '\n' ); – Vlad from Moscow Jan 30 '23 at 08:55