Weird c++ input escaping and space behavior - c++

I'm having an unpleasant problem with my c++ example. Everything works fine until I enter something with a whitespace.
#include <iostream>
using namespace std;
int main (int argc, char * const argv[])
{
int iteration = 0;
while (true) {
char * input = new char[256];
scanf("%s", input);
cout << ++iteration << ": " << input << endl;
cin.get();
}
return 0;
}
So with this code, I can enter anything, but everything after whitespace is somehow like stored in buffer and used in the second iteration.
foo
1: foo
bar
2: bar
foobar
3: foobar
foo bar
4: foo
5: bar
Every single input reading function acts like this and it's driving me crazy. cin >> input, freads(), cin.get() etc. all do this.
It this frequent problem with user input, or am I doing something wrong here?

First of all, never use scanf. It's difficult to use that function and avoid buffer overflows. Replace input with a std::string, and read from std::cin.
Both scanf("%s", input) and cin >> input will read one word, delimited by whitespace. If you want to read a whole line, then use getline(cin, input).

About scanf %s format specifier:
This will read subsequent characters until a whitespace is found (whitespace characters are considered to be blank, newline and tab).
About istream::operator>> with str parameter:
Extraction ends when the next character is either a valid whitespace or a null character, or if the End-Of-File is reached.
So yes, this is standard behaviour for these functions.

Maybe try using std::getline instead?
http://www.cplusplus.com/reference/string/getline/

Related

Strange things with c++ string input

#include <iostream>
#include <cstring>
using namespace std;
const int BUFFER_SIZE = 80;
void getstr(char* &str);
int main()
{
char* str;
while(true)
{
getstr(str);
if (!strlen(str))
break;
}
delete [] str;
return 0;
}
void getstr(char* &str)
{
char temp[BUFFER_SIZE];
cout<<"Enter a string(empty line to quit): ";
cin.get(temp, BUFFER_SIZE);
while(cin.get()!='\n')
continue;
str = new char [strlen(temp)+1];
strcpy(str, temp);
}
I have a string reading loop above and entering an empty line to terminate the loop doesn't work(after entering an empty line program stops responding to any input). But when I replace a loop in getstr with single cin.get() all works fine. What's wrong?
istream::get() sets failbit when empty string is read.
This makes cin.get() return EOF and this because you couldn't break the loop while(cin.get()!='\n').
You can use ios::clear() to clear failbit.
cin.get(temp, BUFFER_SIZE);
cin.clear(); // add this
while(cin.get()!='\n')
continue;
cin.get(char* s, size_t n) Extracts characters from the stream and stores them in s as a c-string, until either (n-1) characters have been extracted or the delimiting character is encountered: the delimiting character being either the newline character ('\n') or delim (if this argument is specified).
The delimiting character is not extracted from the input sequence if found and remains there as the next character to be extracted from the stream (see getline for an alternative that does discard the delimiting character).
A null character ('\0') is automatically appended to the written sequence if n is greater than zero, even if an empty string is extracted.
So here is the problem. cin.get() need to read at least 1 character. You can close stdin by pressing Ctrl+D and Enter, after that, your program will be finished.
And BTW, you are using new N times, but you have only 1 delete. You need to delete the previous buffer
If you are going to use C++, you should really use cin/cout in an objectively consistent manner. For example:
string name;
cout << "What is your name: ";
getline (cin, name);
cout << "Your name is: " << name;
What you are doing is kind of a C/C++ hybrid (char arrays in leu of string objects, but using std namespace).
Now, I know this isn't your question, but what you are doing right now is slightly unorthodox which makes answering your question a bit difficult without putting the code in to and editor and debugging it.
Given the c++11 tag, I assume that you really want C++ code. The great thing is that C++ simplifies this a lot.
#include <iostream>
#include <string>
int main()
{
std::string str;
while(std::getline(std::cin, str) && !str.empty())
{
// do stuff
}
return 0;
}

Does getline() not extract the delimiter?

So I was taking input some integers and then taking input some sentences.
This code works fine:
#include<bits/stdc++.h>
using namespace std;
main(){
int c,b,n,i;string s;
cin>>n>>b>>c;
for(i=0;i<n;i++){
cin>>ws;
getline(cin,s,'\n');
cout<<s;
}
}
Example:
3 3 3
This is weird
This is weirdDefinitely makes
Definitely makesNo sense
No sense
However, when I try to omit the cin>>ws inside the forloop, it doesn't work properly, eg this code segment,
#include<bits/stdc++.h>
using namespace std;
main(){
int c,b,n,i;string s;
cin>>n>>b>>c;
for(i=0;i<n;i++){
getline(cin,s,'\n');
cout<<s;
}
}
Example:
3 3 3
This is weird
This is weirdDefinitely makes
Definitely makes
..and terminates there instead of taking all three inputs.
Why is that? cin>>ws extracts all whitespace from the input but isn't getline() doing that too? So why does it not work properly when I omit cin>>ws in the forloop?
std::getline() extract characters until it extracted the first delimiter character (by default '\n'). The delimiter is not stored in the result but it is extracted. It does not extract whitespace in general or multiple delimiter characters.
As an aside: always check whether input works after trying to read a value.
In the example printed, the issue is is that after formatted input, i.e., using the >> operator, whitespaces are not extracted. That is, the first calls to std::getline() extracts the empty string terminated by the initial newline. It generally is necessary to extract trailing whitespace when switching between formatted and unformatted I/O. That is, You'd want code like
if (cin>>n>>b>>c >> std::ws) {
for(i=0;i<n;i++){
if (getline(cin,s,'\n')) {
cout << "i=" << i << ":'" << s << "'\n";
}
}
}
I can't recommend input operations without adding check for success. The output is changed to make it more easily visible what is going on: try the code with/without this particular std::endl to see what is happening.
When you use cin >> it doesn't remove any whitespace after the input. This means the newline that terminated the first 3 inputs is still in the buffer, waiting to be read by the first getline. Since there's nothing before the newline, the first getline delivered an empty string. Your output should have included a newline so you could have seen the empty line, then it would have made sense.
Originally the code you posted showed a cin >> ws just before the for loop which would have eliminated this problem.
The default delimiter for getline() is '\n', so there is no need to include that in the getline call, though, it should not change the functionality.
See for example Same as getline(input, str, input.widen('\n')), that is, the default delimiter is the endline character.
The change in formatting from the integer input to the getline() input leaves some whitespace (endl) after the integer as explained by #DietmarKühl.
You can change the getline() call to eliminate the delimiter to
getline(cin,s);
which will cause getline() to use '\n' as the default delimiter.
I have modified the 'n' variable to count and removed the other integers to make the code a little simpler to read:
#include <iostream>
int main()
{
int i; // index
int count; // number of strings to accept
std::string str;
std::cout << "Input the number of strings you would like me to process: " << std::endl;
std::cin >> count;
if (std::cin >> count >> std::ws) {
for (i = 0; i < count; i++) {
if (getline(std::cin, str)) {
std::cout << "i=" << i << ":'" << str << "'\n";
}
}
}
}
Cin doesn't extract all white spaces, it just gets the first word until the first white space. It is like having a getline with a space delimiter(not quite but close to).
Getline takes the whole line and has the default '\n' delimiter like mentioned above.
Ex:
string a = "Stack Overflow is awesome";
can give you Stack and getline will give you everything at that line

Reading sentences as string inputs from users

I have been trying to implement a simple code which takes a sentence as an input from the user, stores it in a string and displays it back.
Here are the issues:
1. When T = 1, the program exits immediately.
2. When T>1, the loop runs for only T-1 times.
I think the usage of cin to store the value of T is an issue here. Is the value of T entered being stored as a string due to some buffer capacity of cin?
#include <iostream>
#include <string>
int main()
{
int T;
std::cin >> T;
while (T--)
{
std::string song;
getline(std::cin, song);
std::cout << song << std::endl;
}
return 0;
}
How do you terminate the input that becomes T? With a newline. What happens with that newline after you read into T? It's still left in the input buffer. What will happen when you next call std::getline, what is the first character it will read? The newline, and what happens next? The loop iterates and then T is zero (for the first case where T was originally 1) and the loop and then the program exits.
The solution to this problem is to ignore characters up to and including the newline.
Add a getchar after cin as the \n after the input of T stays in buffer.
std::cin >> T;
getchar();
This is a strange way to do it. So you ask the user to tell the program, before any other input, how many lines will follow? Why not simply:
std::string s;
while (getline(std::cin, s)) {
std::cout << s << std::endl;
}
(This will simply echo every line (press enter to end the line) until end-of-file (Ctrl-d).
Either way, the problem with your code is the while (T--): so why don't you try to see what your T is, and what your getline gives you on each iteration? (I will let you figure it out on your own). Why not use the idiomatic:
for (int i = 0; i < T; ++i)
?
P.S. If you want to read sentences, and not lines, you might want to consider reading up to a delimiter (for example .). getline will do that for you, too:
getline(std::cin, s, '.');

To take sentence as a input in c++

I am trying to take the input of the two sentences one after the other,but while printing it is printing a blank space and in the next line it is printing the first sentence and the loop is exiting.
Here is my code:
int main()
{
char b[100000];
char c[100000];
int t;
cin>>t;
while(t--)
{
cin.getline(b,100000);
cin.getline(c,100000);
cout<<b<<"\n"<<c<<"\n";
}
}
The input:
1
run run
good sentence
The output:
Blankspace
run run
cin >>t;
This will prompt the user for some input. Assuming the user does what's expected of them, they will type some digits, and they will hit the enter key.
The digits will be stored in the input buffer, but so will a newline character, which was added by the fact that they hit the enter key.
cin will parse the digits to produce an integer, which it stores in the num variable. It stops at the newline character, which remains in the input buffer.
cin.getline(b,100000);
cin.getline(c,100000);
Later, you call cin.getline(b,100000);, which looks for a newline character in the input buffer. It finds one immediately, so it doesn't need to prompt the user for any more input. So it appears that the first call to getline didn't do anything, but actually it did.
Big arrays are not good idea. Try use std::string instead.
#include <iostream>
#include <string>
int main() {
std::string lineOne;
std::string lineTwo;
std::getline(std::cin, lineOne);
std::getline(std::cin, lineTwo);
std::cout << lineOne << "\n" << lineTwo;
return 0;
}
The reason is that cin>>t stops at the first non-numeric character, which is the newline. The next cin.getline(b,100000) will read this newline character into b and "run run" to c.
To avoid this, you can first read the newline character into somewhere else. Like
cin >> t;
// read the newline character
getchar();
while(t--){...}

String.size() returns incorrect number if there is space in the string

I'm trying to write a program that returns the number of characters in a string. As I was writing my program, I've noticed that there's a bug in the string class.
Say my program is this:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string input;
cout << "Input string: ";
cin >> input
cout << "Number of characters: " << input.size() << endl;
return 0;
}
If my input is Test String, I should see the number 11 as the output.
However, the output I get is this:
Number of characters: 4
It seems like the size() method does not work when there is space in the string.
My question is, is there another way to get the number of characters in a string? I tried length() method but the result was the same.
That's because your
cin >> input;
only reads up to the first whitespace character.
If you want to get the a whole line, use the following code:
std::string s;
std::getline(std::cin, s);
This is not a bug, and more particularly, actually has nothing to do with the string class.
It has to do with the istream class (cin). cin's operator>> performs "formatted input," which is to say, input delimited by whitespace. After you hit enter, you read out "Test" into a string, leaving "String" in the input buffer. "Test" is, in fact, four characters long.
Consider using std::getline or istream::getline to read entire lines of input with more control. Be sure to read the documentation for these methods carefully, as they have different behavior with respect to what is left in the input stream which can then cause results you may not expect if mixed together with oeprator>> usage.
This is a result of the meaning of cin >> input, which stops reading when any whitespace is found. If you want to keep reading until the end of a line, try getline.
After taking input correctly, you can get the length of the string or char pointer(char*)(including whitespaces) by using strlen(string_name), this will return the length.