0

This is my first time on this website so bear with me. I am a novice c++ programmer as well.

I'll get straight to the point.

I'm trying to read an input file with a multiple data, but its not outputting properly. I'll give you small example of my problem. Basically within this file I have 3 separate strings listed on the same line (from left to right)

BNA Boston Red Stockings NA

The three separate strings are: BNA, Boston Red Stockings, and NA

The fact that Boston Red Stockings has 2 whitespaces makes it difficult for me. I can't just use getline because there is different string right after that on the same line NA, which would store Boston Red Stockings NA into string two which is not what I want. I want Boston Red Stockings stored into string two and NA stored into string three. I tried to be as explicit as possible. Any help would be appreciated. Thanks.

#include <iostream>
#include <fstream>
#include <string>
using namespace std;

int main() {
    string id, name, active;
    ifstream inFile;
    inFile.open("test.dat");
    inFile >> id;
    getline(inFile, name);
    inFile >> active;
    cout << endl << id << endl << name << endl << active << endl << endl;

    system("pause");
    return 0;
}

Here is the text file line: BNA Boston Red Stockings NA

5
  • Do the first and third strings ever have whitespaces? Commented Sep 13, 2014 at 0:22
  • Please add your code, so its easier to detect issues or help you. Commented Sep 13, 2014 at 0:24
  • Being more explicit would be to show us the code. Commented Sep 13, 2014 at 0:31
  • @polarysekt no the first and third string never have whitespaces Commented Sep 13, 2014 at 0:40
  • @VicM I've added my code Commented Sep 13, 2014 at 0:41

3 Answers 3

1

You should certainly use std::getline, contrary your initial intentions. std::getline will read the entire line for you, and put it into a single string. No other function in the standard C++ library will be able to do that, so easily, and conveniently.

But, you see, just because you, initially, placed the entire line into a single string, that does not prevent you in any way from taking that single string, and chopping it into three smaller strings.

You say that the first and the third word in the string never have whitespaces, so you are looking to grab the first and the last whitespace-delimited word, and then everything in the middle.

1) Use std::string's find() method to find the first whitespace in the string. Use rfind() to find the last space in the string.

2) Once you know where the first and the last space is, extracting everything before the first space, everything after the last space, and then everything between the two, becomes very easy.

3) You should also think about what should happen when

A) The string is empty B) The string begins or ends with spaces C) The string contains two or fewer spaces

You should be prepared to handle all possibilities, in order to produce a robust, proper, solution.

Sign up to request clarification or add additional context in comments.

Comments

1

Your problem is related to your input definition:

  • You have 3 strings to read
  • You have 5 words searated by whitespace
  • There are 6 ways to combine the words into strings

So how shall your programm guess which is the right conbination between:

BNA, Boston, Red Stokings NA
BNA, Boston Red, Stockings NA
BNA, Boston Red Stockings, NA
BNA Boston, Red, Stockings NA
BNA Boston, Red Stockings, NA
BNA Boston Red, Stockings, NA  

Basically there are two possibilities to proceed.

Alternative 1: Introduce separators (for example the comma as above).

You could then procedd as follows:

string team1, team2, team3; 
getline (cin /*or another sream*/, team1, ','); // use a delimiter
getline (cin, team2, ',');  // again stop reading at the delimiter
getline (cin, team3);  // here a delimiter is not expected, so read until NL.

Alternative 2: Use a fixed list of allowed values

If the list of expected input, with or without spaces is known, you could read the string, and let your programme make tries and verify if its guess correspond only to allowed values.

Here a small example :

set<string> teams { "BNA", "BOSTON RED STOCKINGS", "CHICAGO WHALES", "NA" };  // set of valid input strings  
string input; 
getline(cin, input);                                                // get input line 
transform(input.begin(), input.end(), input.begin(), ::toupper);    // convert to uppercase (case sensitive might be to error prone)
vector<string> parts { istream_iterator<string>{stringstream(input)}, istream_iterator<string>{} };  // tokenize in words 

                                            // test potential combination of words
for (int i = 1; i < parts.size() - 1; i++) {    // length in words of the first sub string 
    for (int j = 1; j < parts.size() - i; j++) { // length in words of the second sub string
        string s1,s2,s3; 
        for (int k = 0; k < parts.size(); k++) {        // construct substring; 
            if (k < i) s1 += (k == 0 ? "" : " ") + parts[k];
            else if (k < i + j) s2 += (k == i ? "" : " ") + parts[k];
            else s3 += (k == i + j ? "" : " ") + parts[k];
        }
        cout << "Possible entry: " << s1 << " // " << s2 << " // " << s3<<endl; 
        if (teams.find(s1) != teams.end() && teams.find(s2) != teams.end() && teams.find(s3) != teams.end())
            cout << "Valid entry found =======>" << s1 << " // " << s2 << " // " << s3 << endl;  // FOUND => DO SOMETING 
    }
}
// IF END OF LOOP BUT NO VALID VALUE COMBINATION FOUND, there is an error in the input

Comments

1

You can use string::find for first occurrence of space and get first value

Next use string::rfind to get the other two tokens

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.