-1

How would you read a string if it was no longer than 20 characters and could contain spaces in C++? For example I have this kind of file:

3
Namama               4 5 12
Cool                 4 2 34
Not So Cool          4 2 45

I want to write it in the most basic way possible. And I would prefer using only C++ (no C thingies) in this case. This means I want to store it in std::string.

I could use istream::get or istream::getline but then I have to avoid the new line characters. This is problematic (and the code I'm writing is going to be shown to beginners).

What are your solutions for this problem?

Edit:

As asked I'm going to tell you what I have tried but I don't think it's going to be any good. I am not a C++ beginner and usually I would have used something like istream::get and char array but removing new line characters might seem too techy for some people.

So... Either reading char array or std::string using istream::operator>> fails because it stops reading when they see space character (and I may have to read several words). This means the following code fails:

char name[21];
std::cin >> name;

or...

std::string name;
std::cin >> name;

Another thing is that new line characters differ from system to system and actually Windows use two of them by default and I have tried using istream::ignore with 2 as an argument on Windows and that was the only way to ignore the new line and I came to conclusion that it's because Windows use two characters for a new line mark. That means it wouldn't work on Linux and it would have to be more complex... Again - bad for beginners.

Pijusn
  • 11,025
  • 7
  • 57
  • 76
  • 1
    What have you tried? Please show the code you have so far so people can help fixing/improving specific parts of it. – Mat Oct 06 '11 at 18:26
  • "new line characters differ from system to system" - the fix for that is to open the file in character mode instead of binary mode. Then whatever the local newline sequence is, it's translated to `\n` on read. – Steve Jessop Oct 06 '11 at 18:46
  • Do you only want the initial string, or do you want to parse the entire line, including the numbers? If you want the latter, I'd go for a holistic approach. – Kerrek SB Oct 06 '11 at 18:47
  • "new line characters differ from system to system" -- perhaps they do while they are stored on disk, but they do not differ in your C++ program. `'\n'` **always** represents the end of a line, and nothing else does. – Robᵩ Oct 06 '11 at 19:01
  • @SteveJessop and Rob there are two kinds of istream functions - formatted and unformatted. Their behaviour differs. – Pijusn Oct 06 '11 at 19:09
  • @Valdo: `istream::ignore(1000, '\n');` should work on any OS – Mooing Duck Oct 06 '11 at 19:16
  • @Valdo: there are, but the difference between text and binary mode is completely independent of the difference between formatted and unformatted operations on streams. – Steve Jessop Oct 06 '11 at 22:21

2 Answers2

2

If you want to read exactly 20 characters,

for(int i=0; i<3; ++i) {
    std::string result;
    int one, two, three;

    result.resize(20);
    if (!std::cin.read(&result[0], 20)) throw std::runtime_error("reading buffer failed!");

    if (!std::cin >> one >> two >> three) throw std::runtime_error("reading numbers failed!");
    if (!std::cin.ignore(1000, '\n')) throw std::runtime_error("ignore failed!");
}

If you don't want exactly 20 characters, how do you know when you've reached the end of the string?

Mooing Duck
  • 64,318
  • 19
  • 100
  • 158
  • haven't used iostream::read but the reference says that it's an unformatted input function and doesn't it mean that it is going to read the new line character left after the last reading? I still would have to use istream::ignore. Anyways, will try in a few minutes – Pijusn Oct 06 '11 at 18:50
  • @Valdo: I fixed it to read in 20 again, got confused with `.get()` for a moment. This will leave whatever is after the 20 characters, including a newline. – Mooing Duck Oct 06 '11 at 19:12
  • but it read new line as well. actually it causes some very weird behavior I don't understand but trying to figure it out. I have always thought that this function is for binary reading only (remembered using it) but apparently not. – Pijusn Oct 06 '11 at 19:20
  • @Valdo: It should read exactly 20 bytes, including spaces and newlines. What's the wierd behavior? – Mooing Duck Oct 06 '11 at 19:22
  • @Mooning Duck Well, it causes errors when reading the input. after it reads the first line, it fails to read the following lines... trying to figure out what is wrong now... – Pijusn Oct 06 '11 at 19:29
  • @Valdo: I added exceptions. That may or may not help. – Mooing Duck Oct 06 '11 at 19:35
  • Ok... Going to mark this one as an answer because it doesn't seem anyone has a suggestion that works without using istream::ignore. Too bad. it seems sad that you can't read string with spaces without getting into unformatted input. – Pijusn Oct 06 '11 at 19:41
0

One way to accomplish this would be to use istream::read into a temporary buffer of sufficient size, and then use that buffer to initialize a std::string.

char name[21];
std::cin.read(name, 20);
std::string nameString(name); // If you want it in a std::string

This reads exactly 20 characters, newlines and everything. If it's for an exercise, then this is at the very least very simple. If you sometimes want less than 20 characters, it is possible to determine how many extra were read and back the get pointer by std::istream::unget or equivalent.

Agentlien
  • 4,996
  • 1
  • 16
  • 27