using cin.get() function - c++

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++.

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.

The end character `\0` is it considered as one character or two characters?

As I was trying to understand more the behavior of some functions I took two examples :
char str[]="Hello\0World"
and
char str[100];
scanf("%s",str);// enter the same string "Hello\0world"
The problem here that in the first example I got Hello and in the second I got Hello\0world
why are the two characters \ and 0 interepreted as an end character of string in the first and not in the second one ?
\0 is an escape sequence, and while it consists of two characters in the source file, it is interpreted as a single character in the string, namely the null character. However, this special interpretation only happens in the source file; if you input \0 when you run the program, it gets interpreted literally as the two characters \ and 0.
Because when you enter "Hello\0World" for the scanf then you don't enter the same.
When you use \0 in the code that means a character with ascii code 0. Whereas when you're prompted these escape sequences are not interpreted. You actually entering a backslash and a zero character.
So your input will be equal to "Hello\0World" not Hello\0 World
\0 is one character. In first case it is written in code so treated as special sign, like new line (\n) or similar, so printing function stops here. In second case you are literally inputting two separate characters in one byte you have \ and in second 0 so it is not threaten as termination sign. If you want to place "real" \0 from keyboard look here How to simulate NUL character from keyboard?
This is a really good question! My assumption is that when you declare the string on line 3, as expected, the compiler is able to identify that there is an escape character and allocate the \0 appropriately. Next when you are reading from scanf, because your code is already compiled, the program has no way of knowing what characters will be entered and therefore doesn't treat the \ as an escape character and just treats it as a slash.
Here is a sample code I wrote based off of yours to try and solve this problem:
#include<stdio.h>
int main(){
char str1[]="Hello\0World";
printf("str1 = %s\n",str1);
char str2[100];
scanf("%s",str2);
printf("str2 = %s",str2);
}
In your first statement, char str[]="Hello\0World" '\0' is a NULL terminated. Strings consider '\0' as the end of the string.
In your second statement, scanf() takes the input until space occurs.
Overall '\0' is just a single character. '\' is used for ignorance
In the first case:
char str[]="Hello\0World"
the compiler has interpreted the string and place a null terminator (the \0) in the string.
In the second case:
char str[100];
scanf("%s",str);// enter the same string "Hello\0world"
You've entered the string, and there's been do compiler interpretation. It's the same as if you'd entered:
char str[]="Hello\\\0World"

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.

Checking ignore() for values

When you use ignore() in C++, is there a way to check those values that were ignored? I basically am reading some # of chars and want to know if I ignored normal characters in the text, or if I got the newline character first. Thanks.
I don't believe so - you'd have to "roll your own".
In other words, I think you'd have to write some code that read from the stream using get(), and then add some logic for keeping what you need and ignoring the rest (whilst checking to see what you're ignoring).
If you don't actually want to ignore the characters, don't use ignore() to extract them. get() can do the same job but also stores the extracted characters so that you can inspect them later.
If you provide the optional delim parameter to ignore(), then it can stop at a newline:
streampos old = is.tellg();
is.ignore(num, '\n');
if (is.tellg() != old + num) {
// didn't ignore "num" characters, if not eof or error then we
// must have reached a newline character.
}
There's a snag, though - when ignore() hits the delimiter, it ignores that too. So if you hit the delimiter exactly at the end of your set of ignored characters, then tellg() will return old + num. AFAIK there's no way to tell whether or not the last character ignored was the delimiter. There's also no way to specify a delimiter that isn't a single character.
I also don't know whether and when this is likely to be any faster than just reading num bytes and searching it for newlines. My initial thought was, "which part of the difference between ignore() and read() is non-obvious?" ;-)

istream get method behavior

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.