1

After using a >> to input a float value, getline ceases to work correctly and reads trash. How can I avoid this?

   string settingsFile = "TerrainSettings.txt";

   ifstream settingsStream;

   settingsStream.open(settingsFile.data());
   assert (settingsStream.is_open());

   string line;

   getline(settingsStream,line); // fine here
   getline(settingsStream,line); // fine here
   getline(settingsStream,line); // fine here

   float frequency;
   float octaves;
   float amplitude;

   settingsStream>>frequency; // fine here

   getline(settingsStream,line); // here it gets trash, why? 

   settingsStream>>octaves; // trash

   getline(settingsStream,line);

   settingsStream>>amplitude;

Edit: An inclusion of ignore(), generates the following error:

   settingsStream>>frequency;

   settingsStream.ignore(256,'\n');

   getline(settingsStream,line); // fine here 

   settingsStream>>octaves; // trash here

   getline(settingsStream,line);

   settingsStream>>amplitude;

sample input:

/*Settings for Terrain Rendering, please input values on their respective lines*/
/**/
Frequency:                
24
Octaves:                   
120
Amplitude:                 
1.25
andandandand
  • 21,946
  • 60
  • 170
  • 271

1 Answers1

2

First of all, start using std::strings and std::getline. Secondly, the reason for the trashing is that there's still a newline in the buffer. If you expect the user to be entering values one line at a time, you should use istream::ignore to skip everything up to and including the next newline character. For example:

std::string s;
float f;
std::cin >> f;
std::cin.ignore(big_num, '\n');
std::getline(std::cin, s);

What big_num should be depends on your expectations about the input. If you don't mind writing a lot and want to be on the safe side, use std::numeric_limits<std::streamsize>::max(). If you do mind writing a lot, make a constant of the suitable type that you use everywhere.

For example, the above code will parse the following so that f = 5.0f, s = Hello!.

5
Hello!

However, it will parse the following exactly the same way:

5 Hi!
Hello!

If you want to preserve the Hi!, you shouldn't ignore things, and instead define a proper grammar that you'll use to parse the document.

Cactus Golov
  • 3,474
  • 1
  • 21
  • 41
  • Thanks, but you answered the unedited version of the question. I changed the code to std:getline and std::string seconds before you posted. A single ignore of newline gets trash on the following read of amplitude. I'll re-edit the question. – andandandand Feb 17 '12 at 22:43
  • @omgzor: You have to ignore between *every* read of a float and a `getline`. Here's an example that parses your given input just fine: http://ideone.com/INel1 – Cactus Golov Feb 17 '12 at 22:47