Given a line, how do I print it without any spaces? - c++

Here is the problem I'm working on:
Given an inputted line of text, print it without any spaces.
This is my attempt at a solution:
#include <iostream>
int main()
{
using namespace std;
std::string text;
cin >> text;
for(int i=0; i<text.size(); i++) {
if(text[i]==' ') {
text.erase(text.begin()+i);
}
}
cout << text <<"\n";
}
This code prints the string and stop at the first space. What have I missed?

The question is actually a bit vague: by "without any spaces",
do you mean "without any white space" or "without any space
characters"; the expression is widely used with both meanings.
(The space character is white space, but so it a tab, or even
a new line.)
At any rate, std::cin >> text will never put any white space into
text; that's how it is defined. If you want to read
a complete line, you need std::getline. And while you're on
the right track with your loop, you don't test the character
immediately after the one you erased. This is a classic problem
when removing elements; when you remove an element, you don't
want to increment.
For the rest, of course: I'm assuming you're doing this as an
exercise: a professional would probably write:
text.erase( std::remove( text.begin(), text.end(), ' ' ), text.end() );
(or use std::remove_if and a functional object if the goal was
to remove all white space).
And finally, if you switch to using std::isspace: you cannot
call it directly with a char without risking undefined
behavior. You must convert your char to unsigned char
first.

From cin >> reference: http://en.cppreference.com/w/cpp/io/basic_istream/operator_gtgt2
The extraction stops if one of the following conditions are met: a whitespace character (as determined by the ctype<CharT> facet) is found. The whitespace character is not extracted. (...)
tl;dr - using cin >> text; will stop extraction at first whitespace. You should use e.g. getline(), as already mentioned.
BTW, as a mental excercise: why would your code be equal to the one below?
#include <iostream>
int main() {
std::string text;
std::cin >> text;
std::cout << text << '\n';
}

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

C++ c_str() doesn't return complete string

I'm doing a C++ assignment that requires taking user input of an expression (eg: 2 * (6-1) + 2 ) and outputting the result. Everything works correctly unless a space is encountered in the user input.
It is a requirement to pass the user input to the following method;
double Calculate(char* expr);
I'm aware the issue is caused by c_str() where the space characters act as a terminating null byte, though I'm not sure how to overcome this problem.
Ideally I'd like to preserve the space characters but I'd settle for simply removing them, as a space serves no purpose in the expression. I get the same result when using string::data instead of c_str.
int main(int argc, char **argv)
{
string inputExpr;
Calc myCalc;
while(true) {
cin >> inputExpr;
if(inputExpr == "q") break;
cout << "You wrote:" << (char*)inputExpr.c_str() << endl; // debug
printf("Result: %.3f \n\n", myCalc.Calculate( (char*)temp.c_str() ) );
}
return 0;
}
c_str works just fine. Your problem is cin >> inputExpr. The >> operator only reads until the next space, so you do not read your equation fully.
What you want to use is std::getline:
std::getline (std::cin,inputExpression);
which will read until it reaches a newline character. See the function description if you need a specific delimiter.
Problem is not with inputExpr.c_str() and c_str as such, c_str() returns pointer to a character array that contains a null-terminated sequence. While reading through cin, you get space or tab etc separating as multiple strings. Check with the content of the string that way to solve the intended operation
First, I think your Calculate() method should take as input a const char* string, since expr should be an input (read-only) parameter:
double Calculate(const char* expr);
Note that if you use const char*, you can simply call std::string::c_str() without any ugly cast to remove const-ness.
And, since this is C++ and not C, using std::string would be nice:
double Calculate(const std::string& expr);
On the particular issue of reading also whitespaces, this is not a problem of terminating NUL byte: a space is not a NUL.
You should just change the way you read the string, using std::getline() instead of simple std::cin >> overload:
#include <iostream>
#include <string>
using namespace std;
int main()
{
string line;
getline(cin, line);
cout << "'" << line << "'" << endl;
}
If you compile and run this code, and enter something like Hello World, you get the whole string as output (including the space separating the two words).

C++ while loop and string length

If I have the following C++ code:
#include <iostream>
#include <string>
int main()
{
std::string str;
while (std::cin>>str)
std::cout<<str<<"\n";
std::cout<<str.length(); // UPDATE: str.length
return 0;
}
When I run the program and don't type a string and press Enter, I get an empty output. Does that mean that the while loop ran and considered that there is an input even it was empty?
How can I terminate this loop?
Finally, why don't I get the length of the string in my output?
UPDATE: I want to solve the issue using string functions
Thanks.
Because "enter" produces "carrier return" symbol. It is invisible and just starts the new line.
You can use an istream object and use get() function, which return the number of characters read:
char ch;
while(cin.get(ch))
{
}
Write the code this way and set a breakpoint in line 4:
std::string str;
while (std::cin >> str)
{
std::cout << "you typed: " << str << "\n";
std::cout << "str.length(): " << str.length() << "\n";;
}
In the while loop, std::cin>>str will return true if std::cin successfully read data into str, else it will return false.
Since std::cin can always read data from the input stream, that means, while(std::cin >> str) will be an infinite loop, unless you press some key that generates EOF character. The combination of keys that produces EOF, depends on OS.There is one more thing that can produce EOF, which is if you close the input stream!
The input:
std::cin>>str
Reads one [white] space separated word from the stream.
White space include (space/tab and new line).
This means it ignores all white space until it gets a non-white space character. It then reads characters until it gets a white space character.
Thus if you just hit newline (enter) it will ignore the character. It keeps ignoring until it gets to a word.
If you want to make the loop finish. You have two choices. Look for a special word. Or inject an EOF character into the stream. On Unix/Linux this is done with <ctrl>-D on WIndows <ctrl>-Z

Weird c++ input escaping and space behavior

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/