How extract >> operator works in C ++

I am a computer science student, so I do not have much experience with the C ++ language (given that this is my first semester using this language) or coding in this regard.

I was given the task of reading integers from a text file in simple form:

19 3 -2 9 14 4 5 -9 -10 3 . . . 

This sent me on a journey to better understand the I / O operators, as I have to perform certain actions with this stream (duh.)

I looked everywhere and could not find a simple explanation of how the extract → operator works inside. Let me clarify my question:

I know that the extractor -> operator will retrieve a single continue element until it reaches a space, tab, or newline. I'm trying to figure out where the pointer (?) Or read-location (?) Would be AFTER it retrieves the item. Will it be on the last char of the element that was deleted or was deleted and therefore left? will it be in the space / tab / '\ n' itself? Perhaps the beginning of the next item to retrieve?

I hope I was clear enough. I lack all the appropriate jargon to describe my problem more clearly.


That's why I need to know this: (if anyone is interested ...) One of the requirements is to sum all the integers in each line separately. I created a loop to extract all integers one by one until it reaches the end of the file. However, I soon learned that the extract → operator ignores the space / tab / newline. I want to try to extract → an element and then use inputFile.get () to get the space / tab / newline. Then, if this is a new line, do what I have to do. This will only work if the flow pointer is in a good position to extract the space / tab / new line after the last extraction →.


In my previous question, I tried to solve it using getline () and sstring.


DECISION:

To answer my specific question about how the operator works, I had to accept Ben-Voigt's answer as the best. I used the other suggested solutions (using sstring for each line) and they really worked! (you can see this in my previous question link). However, I applied a different solution using Ben's answer, and it also worked:

  . . . if(readFile.is_open()) { while (readFile >> newInput) { char isNewLine = readFile.get(); //get() the next char after extraction if(isNewLine == '\n') //This is just a test! cout << isNewLine; //If it a newline, feed a newline. else cout << "X" << isNewLine; //Else, show X & feed a space or tab lineSum += newInput; allSum += newInput; intCounter++; minInt = min(minInt, newInput); maxInt = max(maxInt, newInput); if(isNewLine == '\n') { lineCounter++; statFile << "The sum of line " << lineCounter << " is: " << lineSum << endl; lineSum = 0; } } . . . 

As for my numerical values, the form is correct! Both spaces and \ n were caught: test

Thanks Ben Voigt :)

However, this solution is very format dependent and very fragile. If any of the lines has anything else before "\ n" (for example, space or tab), the code skips the new char line. Therefore, another solution using getline () and sstrings is much more reliable.

+5
source share
4 answers

After extraction, the stream pointer will be placed in spaces, which causes the extraction to stop (or another invalid character, in which case failbit will also be set).

In fact, it does not matter, since you are responsible for omitting this gap. The next extract will ignore the spaces until it finds valid data.

In short:

  • leading spaces are ignored
  • trailing space remains in the stream

There is also a noskipws modifier that can be used to change the default behavior.

+3
source

operator>> leaves the current character position in the file except for the last character (which may be at the end of the file). This does not necessarily help your problem; after the last value in the line there may be spaces or tabs. You can skip reading each character and check if it is a space other than '\n' , but a much more idiomatic input-oriented line-reading method is to use std::getline to read the line, then initialize std::istringstream before std::istringstream integers from a string:

 std::string line; while ( std::getline( source, line ) ) { std::istringstream values( line ); // ... } 

It also ensures that in case of a format error in the line, the error status of the main input does not change, and you can continue to the next line.

+2
source

According to cppreference.com, the operator>> standard delegates the work of std::num_get::get . This takes an input iterator. One of the features of the input iterator is that you can play it several times without promoting it. Thus, when a non-numeric character is detected, the iterator will point to that character.

+1
source

In general, istream behavior istream not defined in stone. There are several flags for changing istream behavior, which you can read here . In general, you care about where the internal pointer is; why do you use stream in the first place. Otherwise, you simply upload the entire file to a string or equivalent and manually check it.

In any case, returning to your problem, you can use the getline method provided by istream to retrieve the string. From a string, you can manually read it or convert it to stringstream and extract tokens from it.

Example:

 std::ifstream ifs("myFile"); std::string str; while ( std::getline(ifs, str) ) { std::stringstream ss( str ); double sum = 0.0, value; while ( ss >> value ) sum += value; // Process sum } 
+1
source

Source: https://habr.com/ru/post/1203947/


All Articles