In c++, there are several ways of taking input. What is the difference between the two following cases?
char x;
x=cin.get();
/* The above code can be a one-liner */
vs
char x;
cin.get(x);
In this case they're the same (in terms of behavior of get and the character extracted from the stream). From documentation:
std::istream::get
int get();
istream& get (char& c);
"Extracts a single character from the stream.
The character is either returned (first signature), or set as the value of its argument (second signature)."
There basically is no difference between these two cases
cin.get(void) returns a char from the input stream
cin.get(char &c) returns void but sets the passed variable to a char read from the input stream
If you are really picky about memory, cin.get(char &c) will maybe save you 1 allocation for a char being a return type, however I would prefer use the one-liner char x = cin.get();
Related
In general, I need to check if a given string is a number. So I thought my function will check:
1. If the first char is '-' I want to check if there are only digits after it.
2. If the first char is 0 the length of the string has to be less than 3.
The problem: I cannot find a way to get the first char in the string, like if I would do it in C (just look if it is equal to ASCII number), nor in Java, where I would compare strings with equals().
Here's a handy utility function to parse numbers based on streams:
template <class T>
bool try_parse_number(std::string_view s, T& v, const std::locale& locale)
{
std::stringstream stream;
stream.imbue(locale);
stream << s;
stream >> v;
return !stream.fail();
}
Requires the includes <sstream>, <string_view> and <locale>, although you could strip the locale handling out.
You can further create a custom locale and a number facet to control number parsing to a greater degree.
I think in java it will be much easier since using a function --> s.charAt(0). you can easily take the first character of that string and can store that character and later you can compare that to anything.
I'm taking input using cin and storing it into a char variable. My question is if there is any input that could cause cin.fail() to return true.
I know that trying to store input such as "foo" into an int variable will fail, but is there any case in which this is possible with a char variable?
The overloads for operator>> which take a char follow the normal behavior of a formatted input function, that is they call rdbuf()->sbumpc() or rdbuf()->sgetc() to perform the extraction. Naturally, if eof is encountered, then eofbit is set. If one of the functions throw an exception, then badbit is set. If either of these are set, then failbit is set. There's no evidence to indicate that the operation would fail otherwise. (This is covered under section [istream] in the C++11 draft standard.) For other types, like int, do_get() is used to convert the character (similar to scanf). Of course, the conversion can fail, but no conversion is needed if the input is already a char.
Now the comments are misleading. CTRL+C would kill the application in Linux. CTRL+Z would send a character that signals EOF on some operating systems.
You can even use an emoji and it would work:
#include <iostream>
int main()
{
char c;
if (std::cin >> c)
std::cout << "Huzzah!";
}
With input 😁 outputs "Huzzah!" as expected.
I guess not because a char variable with just take only the first character from the given input, no matter how long the input or of what type it is (int,long,double..)
No, failbit is only set if there's a logical error reading the input stream, AKA, someone rips out the USB flashdrive containing the file from which you're reading. ;)
I'm reading over a C++ class for parsing CSV files in one of my programming books for class. I primarily write in C# for work and don't interact with C++ code very often. One of the functions, getline, uses an uninitialized char variable and I'm confused as to whether it's a typo or not.
// getline: get one line, grow as needed
int Csv::getline(string& str)
{
char c;
for (line = ""; fin.get(c) && !endofline(c); )
line += c;
split();
str = line;
return !fin.eof();
}
fin is an istream. The documentation I'm reading shows the get (char& c); function being passed a reference, but which char in the stream is returned? What's the initial value of c?
The initial value of c is undefined but it does not matter what the initial value of c is since the call to get will set the value. Since there is a sequence point after the left hand side of the || and && operators we know that all the side effects of get will have been effected and endofline will see the modified value of c.
could you say me what is the mistake in my following code?
char* line="";
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
I'm trying to get a line as an input from the console.But everytime while using "scanf" the program crashes. I don't want to use any std, I totally want to avoid using cin or cout. I'm just trying to learn how to tak a full line as an input using scanf().
Thank you.
You need to allocate the space for the input string as sscanf() cannot do that itself:
char line[1024];
printf("Write the line.\n");
scanf("%s",line);
printf(line,"\n");
However this is dangerous as it's possible to overflow the buffer and is therefore a security concern. Use std::string instead:
std::string line;
std::cout << "Write the line." << std::endl;
std::cin >> line;
std::cout << line << std::endl;
or:
std::getline (std::cin, line);
Space not allocated for line You need to do something like
char *line = malloc();
or
Char line[SOME_VALUE];
Currently line is a poor pointer pointing at a string literal. And overwriting a string literal can result in undefined behaviour.
scanf() doesn't match lines.
%s matches a single word.
#include <stdio.h>
int main() {
char word[101];
scanf("%100s", word);
printf("word <%s>\n", word);
return 0;
}
input:
this is a test
output:
word <this>
to match the line use %100[^\n"] which means 100 char's that aren't newline.
#include <stdio.h>
int main() {
char word[101];
scanf("%100[^\n]", word);
printf("word <%s>\n", word);
return 0;
}
You are trying to change a string literal, which in C results in Undefined behavior, and in C++ is trying to write into a const memory.
To overcome it, you might want to allocate a char[] and assign it to line - or if it is C++ - use std::string and avoid a lot of pain.
You should allocate enough memory for line:
char line[100];
for example.
The %s conversion specifier in a scanf call expects its corresponding argument to point to a writable buffer of type char [N] where N is large enough to hold the input.
You've initialized line to point to the string literal "". There are two problems with this. First is that attempting to modify the contents of a string literal results in undefined behavior. The language definition doesn't specify how string literals are stored; it only specifies their lifetime and visibility, and some platforms stick them in a read-only memory segment while others put them in a writable data segment. Therefore, attempting to modify the contents of a string literal on one platform may crash outright due to an access violation, while the same thing on another platform may work fine. The language definition doesn't mandate what should happen when you try to modify a string literal; in fact, it explicitly leaves that behavior undefined, so that the compiler is free to handle the situation any way it wants to. In general, it's best to always assume that string literals are unwritable.
The other problem is that the array containing the string literal is only sized to hold 1 character, the 0 terminator. Remember that C-style strings are stored as simple arrays of char, and arrays don't automatically grow when you add more characters.
You will need to either declared line as an array of char or allocate the memory dynamically:
char line[MAX_INPUT_LEN];
or
char *line = malloc(INITIAL_INPUT_LEN);
The virtue of allocating the memory dynamically is that you can resize the buffer as necessary.
For safety's sake, you should specify the maximum number of characters to read; if your buffer is sized to hold 21 characters, then write your scanf call as
scanf("%20s", line);
If there are more characters in the input stream than what line can hold, scanf will write those extra characters to the memory following line, potentially clobbering something important. Buffer overflows are a common malware exploit and should be avoided.
Also, %s won't get you the full line; it'll read up to the next whitespace character, even with the field width specifier. You'll either need to use a different conversion specifier like %[^\n] or use fgets() instead.
The pointer line which is supposed to point to the start of the character array that will hold the string read is actually pointing to a string literal (empty string) whose contents are not modifiable. This leads to an undefined behaviour manifested as a crash in your case.
To fix this change the definition to:
char line[MAX]; // set suitable value for MAX
and read atmost MAX-1 number of characters into line.
Change:
char* line="";
to
char line[max_length_of_line_you_expect];
scanf is trying to write more characters than the reserved by line. Try reserving more characters than the line you expect, as been pointed out by the answers above.
I'm working on writing my own string class and am having trouble with overloading the += operator for a MyString being +='d to a char. I figured this would work but with no luck. Here's the implementation I tried. Any assistance on getting it to work correctly will be much appreciated.
MyString& MyString::operator +=(char c)
{
char derp[1] = {c};
strcat(value, derp);
return *this;
}
This is not going to work for several reasons:
derp is not a null-terminated array, which it has to be if you pass it as a parameter to strcat
There is no check that the buffer that value represents can actually hold more data; neither is there a facility to make sure that the buffer is always null-terminated (which again it needs to be because you are passing it to strcat)
Even if you correct the above, your string class will never be able to include the character \0 as part of a string value because that will be mistaken for a null terminator; in technical terms, your string class would not be "binary safe"; to fix this you need to drop strcat and similar functions entirely and switch to memcpy and friends
Apart from the above, overloading operator += like this allows for code such as
MyString str("foo");
foo += 80; // this compiles, but should it?
Finally, the str*** family of functions is going to get needlessly slower as your strings are getting larger (because they have to scan the string from the beginning each time in order to determine where it ends). Keeping your own length variable and switching to mem*** is going to fix this issue as well.
The use of strcat is incorrect as it requires a null terminated source string and is being provided with a buffer with no null terminator.
value will only be capable of holding a finite number of characters, and there is no attempt to increase the size of value.
Assuming value is large enough and you retain the length of the string inside your instance, I'd say:
value[size] = c;
value[size+1] = '\0';