0

This is my problem: I read some lines from a txt. This txt is like this:

Ciao: 2000
Kulo: 5000
Aereo: 7000

ecc. I have to assign every word before(':') to a string and then to a map; and the numbers to a int and then to a map. The problem is that beginning from the second line, my string become ("\nKulo") ecc! I don't want this! What can I do?

This is the code:

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

        int main()
        {
            map <string, int> record;
            string nome, input;
            int valore;
            ifstream file("punteggi.txt");

            while (file.good()) {
                getline(file, nome, ':');
        //        nome.erase(0,2); //Elimina lo spazio iniziale
                file >> valore;
                record[nome] = valore;
                cout << nome;
            }
            file.close();

            cout << "\nNome: ";
            cin >> input;
            cout << input << ": " << record[input] << "\n";

            cout << "\n\n";
            return 0;
        }
Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
Francesco Bonizzi
  • 5,142
  • 6
  • 49
  • 88
  • Not related, but use `std::endl` instead of `"\n"`. – J.N. Feb 25 '12 at 15:36
  • You can use `std::string::substr` to skip the first character. – J.N. Feb 25 '12 at 15:37
  • @J.N. - there's a difference between using `std::endl` and `\n` - `std::endl` will cause the buffers to flush. – wkl Feb 25 '12 at 15:38
  • 1
    @J.N. - you were right in your first comment: this **isn't related**. I'll be deleting this distracting comment thread; please see the answers here: http://stackoverflow.com/questions/213907/c-stdendl-vs-n – Shog9 Feb 25 '12 at 16:32

2 Answers2

2

The issue you have is that std::getline() is an unformatted input function and as such doesn't skip leading whitespace. From the looks of it, you want to skip leading whitespace:

while (std::getline(in >> std::ws, nome, ':') >> valore) {
    ...
}

Alternatively, if there are leading spaces, you can ignore() all characters up to the end of line after reading a value.

BTW, since I saw someone over here recommending the use of std::endl: do not use std::endl unless you really intend to flush the buffer. It is a frequent major performance problem when writing files.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
Dietmar Kühl
  • 150,225
  • 13
  • 225
  • 380
1

Use the standard line reading idiom:

for (std::string line; std::getline(file, line); )
{
    std::string key;
    int n;
    std::istringstream iss(line);

    if (!(iss >> key >> n) || key.back() != ':') { /* format error */ }

    m.insert(std::make_pair(std::string(key.cbegin(),  std::prev(key.cend()),
                            n));
}

(Instead of the temporary string-from-iterators, you can also use key.substr(0, key.length() - 1), although I imagine that my version may be a bit more efficient. Or add a key.pop_back(); before inserting the data into the map.)

Kerrek SB
  • 464,522
  • 92
  • 875
  • 1,084
  • Correct me if I am wrong. Why not `m.insert(std::make_pair( key, n ) )` ? Haven't we extracted them in the `if` condition statement ? – Mahesh Feb 25 '12 at 15:50
  • @Mahesh: I thought you might want to strip off the colon! You can also say `key.pop_back()` in a separate statement, I suppose. The conditional just made sure that the last character was indeed a colon. – Kerrek SB Feb 25 '12 at 15:56