0

Currently trying to store some information from a text file, the text file is in the format of number/text/text/number, and I want to save them as an int, string, string, and a float respectively. In the file they are actually separated by a /, so an example of the text file could look like 173/hello/goodbye/13.4

This is the code I have so far

    int main(){

    string menuname;
    int a;
    float d;
    string b;
    string c;
    bool error = false;
    ifstream openFile;

    do{
        cout  << "Please enter the name of the menu you would like to open: ";
        cin >> menuname;
        menuname +=  ".txt";

        openFile.open(menuname.c_str());
        if(openFile.fail()){
            cerr << "Unable to open file, please re-enter the name.\n";
            error = true;
        }
    }while(error == true);

    openFile >> a;
    openFile >> b;
    openFile >> c;
    openFile >> d;
    cout << itemno << category;
    }

I'm not 100% sure what is causing the issue, but I have a feeling it could be to do with the string, as if i just use openFile >> a;with the next 3 it shows correctly, but after adding openFile >> b;it shows the whole line instead of just the word/phrase next to it.

Thecube
  • 71
  • 8
  • The >> operator delimits input by whitespace. You don't want it delimited by whitespace so you need to use something else. There are lots of choices: see http://stackoverflow.com/questions/7302996/changing-the-delimiter-for-cin-c – Jerry Jeremiah May 04 '16 at 09:38

3 Answers3

0

Don't use operator>> for formatted string input. It reads strings quite greedily.

If you have a custom delimiter, prefer to getline() the delimited strings.

Then format them into the correct data type.

StoryTeller - Unslander Monica
  • 165,132
  • 21
  • 377
  • 458
  • I was thinking of trying that with the `getline()`, but i'm not very advanced with programming yet and was not sure if not having a / would cause problems, as when I have finished my programs it will hopefully be reading multiple different lines and saving them all separately in the same format. – Thecube May 04 '16 at 09:41
  • @Thecube You should pass `'/'`as the delimiter to `getline`. It's fairly simple, and if you run into trouble you can always ask another question on SO. – StoryTeller - Unslander Monica May 04 '16 at 09:45
  • Okay, for the last variable on the first line, there is no `/` after it, so would having the delimiter as whites pace there work the same? – Thecube May 04 '16 at 09:52
  • When using `getline()`, is it possible to store int's and floats, or can I only store the strings? – Thecube May 04 '16 at 10:17
  • @Thecube, you don't have to pass anything if you want the last delimiter to be a newline (it's the default one). `getline` only works with strings. You can parse the string after extracting it. – StoryTeller - Unslander Monica May 04 '16 at 10:30
0

Using getline() and adding a delimeter '/' can fix this but when you use it to read in a text file, the values that will be read will be of type string by default. You have to convert it to int and float as what your program wanted by using the function of cstdlib, atoi() for int and atof() for double/float. See the code below:

#include<iostream>
#include<fstream>
#include<cstdlib> 

using namespace std;

int main()
{
 string menuname;

 string a, b, c, d;

 bool error = false;
 ifstream openFile;

 do
 {
  cout << "\n Please enter the name of the menu you would like to open: ";
  cin >> menuname;
  menuname += ".txt";

  openFile.open(menuname.c_str());

  if (openFile.fail())
  {
   cerr << "\n Unable to open file, please re-enter the name.\n";
   error = true;
  }
 } while (error == true);

 cout << endl;

 getline(openFile, a, '/');
 getline(openFile, b, '/');
 getline(openFile, c, '/');
 getline(openFile, d, '/');

 int aNum = atoi(a.c_str());
 float dNum = atof(d.c_str());

 cout << " " << a << " " << b << " " << c << " " << d;
 cout << "\n Trying to add an int and a double: " << aNum + dNum;

 return 0;
}

The textfile I created contains: 123/Hello/Goodbye/12.3

It will output:

123 Hello Goodbye 12.3 
Trying to add an int and a double: 135.3

I'm just new to C++ as well, if anyone found something wrong in the code I edited please correct me.

LinkedRom
  • 165
  • 1
  • 3
  • 14
  • Yeah your answer needs a little help, cause there is no trailing delimiter. test on the input: "1/one/one/1.0\n2/two/two/2.0" note that `d` will contain: "1.0\n2". Additionally, you're simply reading into `string`s, you tell him what to do with those above, but if you're going to provide an example at least make it complete. You appear to have come from JavaScript, you did not insert JavaScript, so please remove those tags from your answer. You can see the proper way to do this in [my answer](http://stackoverflow.com/a/37027777/2642059). – Jonathan Mee May 04 '16 at 12:31
  • Thanks, I think I am getting the `getline()` to work, although now I have multiple lines and am trying to store it in an array, I am currently using `for (int i = 0; i < 5; i++){ getline( openFile, a[i], ':');`, which seems to be doing nothing when i output the a[i] array – Thecube May 04 '16 at 17:44
0

An extraction operator should generally only be used when you are extracting an object. If that's what you're actually doing let me know and I'll edit this answer.

You could simplify your input by using a trailing delimiter, then you could use getline for each input. But as it is we can still work around what you have:

openFile >> a; // There is no leading delimiter, and the delimiter is not numeric therefore we can simply use the extraction operator
openFile.ignore(numeric_limits<streamsize>::max(), '\n'); // We must also purge the delimiter
getline(openFile, b, '/'); // This will include white spaces in b
getline(openFile, c, '/'); // This will include white spaces in c
openfile >> d; // Again using the extraction operator, but because there is no trailing delimiter no need to purge

Live Example

This extraction method is very fault tolerant, in fact the only thing I think it can't handle is escaped delimiters. If you need support for that, let me know, but at that point I'd lean toward using a regex_token_iterator

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288