1

I am trying to print the first, middle, and last names from a text file that is formatted like this:

Doe, John Bob
Young, Tim Joe
Washington, George Peter

Here is the expected output:

First name: John
Middle name: Bob
Last name: Doe

First name: Tim
Middle name: Joe
Last name: Young

First name: George
Middle name: Peter
Last name: Washington

I am able to get the middle name and last name correctly, but when I try to get the first name, it shows that it is the first and middle names. Here is the code:

#include <iostream>
#include <fstream>

using namespace std;

int main()
{
    //Variable for the text file
    ifstream infile;

    //Opens the text file
    infile.open("data.txt");

    //Variables for the names
    string name;
    string lastName;
    string firstName;
    string middleName;

    //Loops through all the names
    while(getline(infile, name))
    {
        //Looks for a comma and space in each name
        int comma = name.find(',');
        int space = name.find(' ', comma+2);

        //Splits the name into first, last, and middle names
        lastName = name.substr(0, comma);
        firstName = name.substr(comma+2, space);
        middleName = name.substr(space+1, 100);

        //Prints the names
        cout << "First name: " << firstName << endl;
        cout << "Middle name: " << middleName << endl;
        cout << "Last name: " << lastName << endl;
        cout << endl;
    }
    //closes the text file
    infile.close();

    return 0;
}//end main

Here is the output I get:

First name: John Bob
Middle name: Bob
Last name: Doe

First name: Tim Joe
Middle name: Joe
Last name: Young

First name: George Peter
Middle name: Peter
Last name: Washington
  • Did you try stepping through your code, **line-by-line**, with a debugger, while inspecting the values of every variable, at each execution step? – Algirdas Preidžius Nov 22 '19 at 00:20
  • Possible duplicate: [How to use string.substr() function?](https://stackoverflow.com/questions/2477850/how-to-use-string-substr-function) – manveti Nov 22 '19 at 00:26
  • The function `substr()` the second parameter is the number of characters that should be in the new string. The values you put into the length are returned from `std::string::find()` the value returned from this function is the position within the string (not the length from the start of the search). – Martin York Nov 22 '19 at 00:30

2 Answers2

1

You are misusing the substr() method, from the reference

The substring is the portion of the object that starts at character position pos and spans len characters (or until the end of the string, whichever comes first).

The second argument is the length of the substr. If you use

first = name.substr(comma+2, space-comma-2)

You should get your expected behavior.

William Miller
  • 9,839
  • 3
  • 25
  • 46
0

Simpler alternative:

#include <iostream>
#include <fstream>
#include <sstream>
#include <string>

// is evil. Avoid.
//using namespace std;

int main()
{
    std::ifstream infile("data.txt"); // open file

    std::string line;
    while(std::getline(infile, line)) // get a line
    {
        std::istringstream stream(line); // make an input stream out of the line

        std::string lastName;
        std::string firstName;
        std::string middleName;
        if (getline(stream, lastName, ',') // read up to the comma and discard the comma 
                && stream >> firstName // read up to the next space 
                          >> middleName) // read up to next space, but end of line comes first
        {
            std::cout << "First name: " << firstName << '\n'   // endl very expensive
                      << "Middle name: " << middleName << '\n' // save endl for when 
                      << "Last name: " << lastName << '\n'     // you really need it
                      << std::endl; //probably don't even need it here.
        }
    }
}// file closes automatically

Documentation for std::istringstream

Supplementary reading: Why is "using namespace std;" considered bad practice? and C++: "std::endl" vs "\n"

Note this doesn't handle names like John Jacob Jingleheimer Schmidt, but could easily be modified to do so.

user4581301
  • 33,082
  • 7
  • 33
  • 54