how this function read text into a struct? - c++

I am trying to understand what exactly the following function is doing. It is used to read a text file into a struct, called AEntry, which only contains four ints.
The file contains a list of lines. Each line holds four ints delimited with spaces (or tab).
when this function is called, a line of istream and a AEntry struct are passed in.
My question is how the delimitors, spacess or tabs, are filtered out? or my understanding is wrong.
istream& operator>>( istream &stream, AEntry& val )
{
stream >> val.kv;
stream >> val.col;
stream >> val.bo;
stream >> val.Offset;
return stream;
}

They're filtered out because that's the behavior of the default overloads of istream::operator>>. They stop at whitespace and discard it instead of incorporating it into the extracted output.

Related

Whitespace and specific characters when using operator >>

I have a custom String class that contains a char array, and I need to overload the >> operator for this class. For the life of me I can't figure out how to do two things.
1 - Read the user input until a ; is reached
2 - Include whitespace from user input
I cannot use namespace or c++'s built-in string. Unfortunately that rules out the use of getline and any of the convenient find functions (I think it does, anyway?). Some things I have tried:
std::istream& operator >> (std::istream& output, String& input) {
output >> input.str;
return output;}
This works but only up until the first whitespace, after which point it stops reading the user input.
std::istream& operator >> (std::istream& output, String& input) {
while (output != ';') {
output >> input.str;
}
return output;}
An istream I guess isn't equivalent to the user input so you cannot compare it to a char like I tried to in my while loop.
So, my questions are, how does one read input until a specified character is encountered, and how does one include all whitespace when using >> ?
The global operator>> for string/character input stops reading when it encounters whitespace, so it is not worthwhile to implement your custom operator>> in terms of the global operator>>.
You ruled out use of std::getline(), but you can use std::istream::getline() instead. Like std::getline(), it also has an optional delim parameter (the default is '\n'), and will read characters - including whitespace - until the delimiter or EOF is reached.
std::istream& operator >> (std::istream& input, String& output)
{
return input.getline(output.str, yourmaxstrsize, ';');
}

C++ Reading data from a file line by line

I am new to programming and I have this question. I have this file that I am opening
ifstream fin;
FILE * pFile;
pFile = fopen (fname,"r");
The file has 3 data each line. The first is an integer, the second is an alphabet and the third is an address(like computer memory address). How do I extract these line by line into 3 variables that I can process, and then repeat it with next line and so.
You should know that there are preferred C++ methods for manipulation of files over C stdio methods:
Using standard predefined streams: std::ofstream for output and std::ifstream for input.
Formatted/Unformatted I/O such as operator<<(), operator>>(), read() and write().
In-memory I/O for manipulation of extracted data.
What you need for this particular case is input stream functionality along with formatted input. The formatted input will be done through operator>>().
But before you get to that, you have to instantiate a file stream. Since you're using input, std::ifstream will be used:
std::ifstream in("your/path.txt");
The next thing to do is to create the three variables whose values you will extract into the stream. Since you know the types beforehand, the types you will need is an integer, character, and string respectively:
int num;
char letter;
std::string address;
The next thing to do is to use operator>>() to obtain the first valid value from the stream. The way it works is that the function analyses the type of the righthand operand and determines if the characters extracted from the file stream will create a valid value after parsing. When the stream hits whitespace, the new line character or the EOF (end-of-file) character (or a character that doesn't match that of the operand's type), extraction will stop.
What makes IOStreams powerful is that it allows chaining of expressions. So you are able to do this:
in >> num >> letter >> address;
which is equivalent to:
in >> num;
in >> letter;
in >> address;
This is all that is needed for this simple case. In more complex situations, loops and in-memory I/O might be needed for successful extractions.

How to extract data after passing istream var to a function

I am currently running a command line input program for class that extracts data from the command line argument, sticks it in an ifstream then passes it by reference to a function wherein I must extract information from the file.
First, I understand that"
ifstream coursesIn (argv[1]);
Will put my input filename into a courseIn variable of type ifstream. From here, I can perform operations such as .open(argv[1]); in order to extract the data necessary.
What comes next is that I'm to pass the variable to a function called processEnrollments(coursesIn)
whose prototype looks like:
processEnrollments (std::istream& courseFile);
Once I put the variable inside the function and am inside the function, my professor provided this code:
void processEnrollments (istream& courseFile, istream& enrollmentRequestsFile,
ostream& reportFile)
{
int numCourses;
courseFile >> numCourses;
// Create the arrays we need
//!! Insert your code here
}
Firstly, I have no idea what he is trying to do with the first two lines inside the function, and secondly, I can no longer perform my .open(argv[1]) method in order to extract the data from the filename.
Outside the function I believe I can get everything I need, but after passed, I'm at a loss.
thank you for any help provided!
You really need to read more about streams.
The declaration
ifstream coursesIn (argv[1]);
creates a variable coursesIn, so long you are right, but it also opens the file with the file-name provided by argv[1]. If you do like this you don't need to open it later.
As for the function, the first line in it declares an integer variable, and the second reads an integer from the file courseFile and stores it in the numCourses variable.
And lastly, remember that all input streams have the same base, so if you can read input from e.g. cin you can also read input from a file.

C++ Reading an multiline file with lines with arbitary lengths and format without using a stringstream

I have an input stream with the following lines:
# <int> <int>
<some_data_type> <some_data_type> <some_data_type> ..... <some_data_type>
<some_data_type_1> <some_data_type_2> <some_data_type_3> <some_data_type_1> <some_data_type_2> <some_data_type_3> .... <some_data_type_1> <some_data_type_2> <some_data_type_3>
In the above stream all three lines are different and have to be parsed differently. Currently,I am using a reading method as follows:
void reader( std::istream & is, DataStructure & d ){
std::string line;
getline(is,line);
std::stringstream s(line);
//parse line 1
getline(is,line);
std::stringstream line2(line);
//parse line 2
getline(is,line);
std::stringstream line3(line);
//parse line 3
}
Now the idea is not to make use of std::stringstream at all, as a line can arbitarily large and we donot want to load everything into memory twice. So, it would be better if it was possible to read from the input stream directly into the user given datastructure d.
An idea is to make use of std::istream_iterator but unfortunately the different lines have different parsing needs. For example, in the last line, three elements from the stream together constitute a single data element.
The only idea that seems plausible to me at this moment is to handle the stream buffer directly. It would be great if anyone could recommend a better way of doing this.
NOTE: Cannot make use of a tertiary data structure like std::stringstream. It is essential to read from the stream directly into the user provided data structure.
EDIT: Please note we are only allowed a single pass over the file.
Now the idea is not to make use of std::stringstream at all, as a line
can arbitarily large and we donot want to load everything into memory
twice. So, it would be better if it was possible to read from the
input stream directly into the user given datastructure d.
Olaf explained the extraction operator above but then we have a new requirement:
This will only work for the first line, where it is known there is a
fixed number of elements.
and
(2) Unfortunately, I have no discriminator beyond my knowledge that each instance of the data
structure needs to be instantiated with information stored in three
different lines. All three lines have different lengths and different
data elements. Also, I cannot change the format.
plus
(3) All information is treated as unsigned integer.
Now the next issue is that we don't know what the data structure actually is, so given what has come before it appears to be dynamic in some fashion. Because we can treat the data as unsigned int then we can use the extraction operator possibly, but read into a dynamic member:
vector<unsigned int> myUInts;
...
inFile >> currentUInt;
myUInts.push_back(currentUInt);
But then the issue of where to stop comes into play. Is it at the end of the first line, the third? If you need to read an arbitrary number of unsigned ints, whilst still checking for a new line then you will need to process white space as well:
inFile.unsetf(ios_base::skipws);
How you actually handle that is beyond what I can say at the moment without some clearer requirements. But I would guess it will be in the form:
inFile >> myMember;
char next = infile.peek()
//skip whitespace and check for new line
//Repeat until data structure filled, and repeat for each data structure.
Then do not use std::getline() at all. Define an istream operator for your types and use these directly
std::istream &operator >>(std::istream &f, DataStructure &d)
{
f >> d.member1 >> d.member2 >> ...;
return f;
}
void reader(std::istream & is, DataStructure &d)
{
is >> d;
}
There's no need fiddling with an std::istream_iterator or directly manipulating the stream buffer.

std::istream without command line?

Basically I have a thread reading from c++ std::istream using
istream& getline ( istream& is, string& str );
And when I bind the istream with cin, then it works fine when I type the input from standard command line as the input.
But I am wondering is there a way that I can make the read thread getline get the string without
using the actual command line ?
Basically I want to achieve this:
By just calling a function WriteToIStream with parameter str (instead of type str in command line) and the read thread getilne() can get the str.
void WriteToIStream(string& str)
{
//...
}
Many Thanks
cin is only one instance of an input stream, bound to the standard input. For your case, you can use an istringstream (or more generally a stringstream) which is an input stream to read from a string:
std::istringstream istr("foobar");
getline(istr, some_string_variable);
This requires the standard header <sstream>.