istream get method behavior - c++

I read istream::get and a doubt still hangs. Let's say my delimiter is actually the NULL '\0' character, what happens in this case? From what I read:
If the delimiting character is found, it is not extracted from the input sequence and remains as the next character to be extracted. Use getline if you want this character to be extracted (and discarded). The ending null character that signals the end of a c-string is automatically appended at the end of the content stored in s.
The reason I would prefer "get" over "readline" is because of the capability to extract the character stream into a "streambuf".

I dont' quite get your problem.
On the msdn website, for the get function, it says:
In all cases, the delimiter is neither extracted from the stream nor returned by the function. The getline function, in contrast, extracts but does not store the delimiter.
In all cases, the delimiter is neither extracted from the stream nor returned by the function. The getline function, in contrast, extracts but does not store the delimiter.
http://msdn.microsoft.com/en-us/library/aa277360(VS.60).aspx
I don't think your going to have a problem, since the msdn site tells that the delimiter is neither extracted from the stream, nor returned vy the function.
Or maybe I'm missing a point here?

If you have something like this, then delimiter will not get stuck in the input stream:
std::string read_str(std::istream & in)
{
const int size = 1024;
char pBuffer[size];
in.getline(pBuffer, size, '\0');
return std::string(pBuffer);
}
just an example if you have '\0' as delimiter and strings are not bigger than 1024 bytes.

Related

C++ fstream getline parameters

I am new to C++ and I want to ask a question about how to find a line in a file using fstream.
I only found this and would someone explain to me what these parameters mean?
file.getline(char *,int sz);
Thanks
If you mean std::basic_stream::getline(), you provide a pointer to character array and the size of that array. You have to create the array somewhere by yourself. If some line is longer than sz - 1, only part of it with length sz - 1 will be read.
If you don't know the maximum length of lines in the input file, it's better to use std::getline(), for example like this:
std::string line;
std::getline(file, line);
Directly from here:
The first variable:
Pointer to an array of characters where extracted characters are stored as a c-string.
The second variable:
Maximum number of characters to write to s (including the terminating null character).
If the function stops reading because this limit is reached without finding the delimiting character, the failbit internal flag is set.
streamsize is a signed integral type.

why there are two member functions?

I am learning c++, however, I can not understand what is the difference BTW:
std::cin.get();
and
std::cin.getline();
although;I know how to use each of them, but can't understand why there are two?
I've read this explanation :
getlinereads the newline character then discard it; whereas .get()reads it then leaves it in the input queue ..!! why each of them does what it does ?
sorry for bad English :(
std::cin.get(), when called without parameters, reads one single character from input and returns it.
std::cin.getline(char* str, std::streamsize count) reads one line of input and copies it into the buffer str, followed by an extra null character to form a C-string. count must be the size of that buffer, i.e. the maximal number of characters (plus the null byte) it can copy into it.
To read a line without caring about the buffer size it may be better to use std::getline:
#include <string>
std::string line;
std::getline(std::cin, line);
Reads a line from cin into line.
See http://en.cppreference.com/w/cpp/io/basic_istream and http://en.cppreference.com/w/cpp/string/basic_string/getline .
"get" only retrieves a character, "getline" gets all characters to a line terminator. Thats the main difference.

Any way to get rid of the null character at the end of an istream get?

I'm currently trying to write a bit of code to read a file and extract bits of it and save them as variables.
Here's the relevant code:
char address[10];
ifstream tracefile;
tracefile.open ("trace.txt");
tracefile.seekg(2, ios::beg);
tracefile.get(address, 10, ' ');
cout << address;
The contents of the file: (just the first line)
R 0x00000000
The issue I'm having is that address misses the final '0' because it puts a /0 character there, and I'm not sure how to get around that? So it outputs:
0x0000000
I'm also having issues with
tracefile.seekg(2, ios::cur);
It doesn't seem to work, hence why I've changed it to ios::beg just to try and get something work, although obviously that won't be useable once I try to read multiple lines after one another.
Any help would be appreciated.
ifstream::get() will attempt to produce a null-terminated C string, which you haven't provided enough space for.
You can either:
Allocate char address[11]; (or bigger) to hold a null-terminated string longer than 9 characters.
Use ifstream::read() instead to read the 10 bytes without a null-terminator.
Edit:
If you want a buffer that can dynamically account for the length of the line, use std::getline with a std::string.
std::string buffer;
tracefile.seekg(2, ios::beg);
std::getline( tracefile, buffer );
Edit 2
If you only want to read to the next whitespace, use:
std::string buffer;
tracefile.seekg(2, ios::beg);
tracefile >> buffer;
Make the buffer bigger, so that you can read the entire input text into it, including the terminating '\0'. Or use std::string, which doesn't have a pre-determined size.
There are several issues with your code. The first is that
seekg( 2, ios::beg ) is undefined behavior unless the stream
is opened in binary mode (which yours isn't). It will work
under Unix, and depending on the contents of the file, it
might work under Windows (but it could also send you to the
wrong place). On some other systems, it might systematically
fail, or do just about anything else. You cannot reliably seek
to arbitrary positions in a text stream.
The second is that if you want to read exactly 10 characters,
the function you need is istream::read, and not
istream::get. On the other hand, if you want to read up to
the next white space, using >> into a string will work best.
If you want to limit the number of characters extracted to a
maximum, set the width before calling >>:
std::string address;
// ...
tracefile >> std::setw( 10 ) >> address;
This avoids all issues of '\0', etc.
Finally, of course, you need error checking. You should
probably check whether the open succeeded before doing anything
else, and you should definitely check whether the read succeeded
before using the results. (As you've written the code, if the
open fails for any reason, you have undefined behavior.)
If you're reading multiple lines, of course, the best solution
is usually to use std::getline to read each line into a
string, and then parse that string (possibly using
std::istringstream). This prevents the main stream from
entering error state if there is a format error in the line, and
it provides automatic resynchronization in such cases.

Why does istream::get set cin.fail when '\n' is the first character?

Why these two functions istream::get(char*, streamsize) and istream::get(char*, streamsize, char) set the cin.fail bit when they find '\n' as the first character in the cin buffer?
As can be seen here, that's the behavior of the two overloads mentioned above. I'd like to know what was the purpose in designing these functions this way ? Note that both functions leave the character '\n' in the buffer, but if you call any of them a second time, they will fail because of the newline character, as shown in the link. Wouldn't it make more sense to make these two functions not to leave the character '\n' in the buffer, as the overloads of the function istream::get() and istream::getline() do ?
With std::istream::getline, if the delimiting character is found it is extracted and discarded. With std::istream::get the delimiting character remains in the stream.
With getline you don't know, if the delimiting character was read and discarded or if just n - 1 characters where read. If you only want to read whole lines, you can use get and then peek for the next character and see if it is a newline or the given delimiter.
But if you want to read whole lines up to some delimiter, you might also use std::getline, which reads the complete line in any case.

using cin.get() function

char arr[100];
cin.get(arr,100);
Is this safe? Will the null-character be appended at the end even if I type more than 100 chars? or should I use cin.get(arr,99)?
When I type ENTER, is the end-of-line character part of the array or not?
The answers to both of your questions can be found here, but to reiterate:
The get method reads at most n - 1 characters. This means that the method expects the size of the buffer and not the number of characters to read. This method automatically appends a null character to the end.
The newline character is not extracted or stored in the array.
You may also want to consider using std::getline which you can use in conjunction with std::string.
1)is this safe. I mean will the null-character be appended
at the end. even if I typed more than 100 chars. or it must be cin.get(arr,99).
Taken from here.
The signature of get you are using looks like this:
basic_istream& get( char_type* s, std::streamsize count );
It will read at most count - 1 characters from the stream (in your case 99) or up until the delimiting character, which is by default \n. So if you type more than 100 characters, a call to get will read 99 of those characters and then append the null terminator \0 at the end.
2)also when I type ENTER, a newline get passed. so does this character is really a part of the array or not.
No, get read up until the delimiting character, so if you press ENTER, \n will be left in the stream as the next character to be read.
Advice:
Please use the site I linked to in order to understand how these functions work, and prefer std::string and std::getline if you are coding in C++.