std::cin skips white spaces - c++

So I am trying to write a function to check whether a word is in a sentence, by looping through a char array and checking for the same string of char's. The program works as long as the Sentence doesn't have any spaces. I googled around and they are all the same suggestions;
cin.getline
But however I implement it, it either doesn't run or skips the entire input and goes straight towards the output.
How can I account for spaces?
#include <iostream>
using namespace std;
bool isPartOf(char *, char *);
int main()
{
char* Word= new char[40];
char* Sentence= new char[200];
cout << "Please enter a word: ";
cin >> Word;
cout << endl << "Please enter a sentence: ";
//After Word is input, the below input is skipped and a final output is given.
cin.getline(Sentence, 190);
cout << endl;
if (isPartOf(Word, Sentence)==true)
{
cout << endl << "It is part of it.";
}
else
{
cout << endl << "It is not part of it.";
}
}
bool isPartOf(char* a, char* b) //This is the function that does the comparison.
{
int i,j,k;
for(i = 0; b[i] != '\0'; i++)
{
j = 0;
if (a[j] == b[i])
{
k = i;
while (a[j] == b[k])
{
j++;
k++;
return 1;
if (a[j]=='\0')
{
break;
}
}
}
}
return 0;
}
And I am not allowed to use strstr for the comparison.

Ok, I'll try to explain your problem:
Let's assume this is your input:
thisisaword
this is a sentence
When you use cin and give it any input, it stops at the newline character which in my example follows character 'd' in 'thisisaword'.
Now, your getline function will read every character until it stops newline character.
Problem is, the first character getline encounters is already a newline so it stops immediately.
How is this happening?
I'll try to explain it like this:
If this is your input given to a program (note \n characters, treat it like a single character):
thisisaword\n
this is a sentence\n
What your cin function will take and leave:
\n
this is a sentence\n
Now getline sees this input and is instructed to get every character until it meets a newline character which is "\n"
\n <- Uh oh, thats the first character it encounters!
this is a sentence\n
cin reads input and leaves "\n", where getline includes "\n".
To overcome this:
\n <- we need to get rid of this so getline can work
this is a sentence\n
As said, we cannot use cin again because it will do nothing.
We can either use cin.ignore() without any parameters and let it delete first character from input or use 2x getline(first will take remaining \n, second will take the sentence with \n)
You can also avoid this kind of problem switching your cin >> Word; to a getline function.
Since this is tagged as C++ I changed Char*[] to Strings for this example:
string Word, Sentence;
cout << "Please enter a word: "; cin >> Word;
cout << endl << Word;
cin.ignore();
cout << "\nPlease enter a sentence: "; getline(cin, Sentence);
cout << endl << Sentence;
OR
string Word, Sentence;
cout << "Please enter a word: "; getline(cin, Word);
cout << endl << Word;
cout << "\nPlease enter a sentence: "; getline(cin, Sentence);
cout << endl << Sentence;

How about using this:
std::cin >> std::noskipws >> a >> b >> c;
cin by default utilizes something like this:
std::cin >> std::skipws >> a >> b >> c;
And you can combine flags:
std::cin >> std::skipws >> a >> std::noskipws >> b;
Tell me if it works for you : )

By default operator>> skips whitespaces. You can modify that behavior.
is.unsetf(ios_base::skipws)
will cause is's >> operator to treat whitespace characters as ordinary characters.

Related

Getting whole line from files

My program Can read strings and integer, but the problem is when I add spaces for strings like names it does not execute the viewOrder() function. I am New to programming and start learning c++ as my frist language at 19 years old, hoping that someone can help me. I am doing an uniform ordering system.
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
struct orderDetails{
string name;
int studentNumber;
string address;
string dressCode;
int quantity;
};
void takeOrder(){
orderDetails order;
ofstream file ("database.dat" , ios::app);
cin.ignore();
cout << "Enter name: ";
getline(cin,order.name);
cout << "Enter Student Number: ";
cin >> order.studentNumber;
cin.ignore();
cout << "Enter Address: ";
getline(cin,order.address);
cout << "Enter Dress Code: ";
cin >> order.dressCode;
cout << "Enter Quantity: ";
cin >> order.quantity;
file << order.name << endl
<< order.studentNumber << endl
<< order.address << endl
<< order.dressCode << endl
<< order.quantity << endl;
file.close();
}
void viewOrder(){
ifstream database("database.dat");
orderDetails order;
while(database >> order.name >> order.studentNumber >> order.address >> order.dressCode >> order.quantity){
cout << endl << order.name << endl << order.studentNumber << endl << order.address << endl << order.dressCode << endl << order.quantity << endl;
}
}
int main(){
cout << "1.Take Order \n2.View Order \n3.Exit \nPlease Choose A Number: ";
int choice;
cin >> choice;
switch(choice){
case 1:
system("CLS");
takeOrder();
break;
case 2:
system("CLS");
viewOrder();
break;
default:
break;
}
return 0;
}
This is an old problem. You need to learn about the difference between formatted and unformatted input.
If you have a line of text like
abc def
and you read this into std::strings with
inputFileStream >> s1 >> s2
Then the input "abc" and "def" will be read into the to string-variables. Ok. But, the newline ('\n') at the end of the line will not be consumed. If you write an additional
inputFileStream >> s1 >> s2
to read the next line, then the inserter operator >> will skip the whitespace '\n' and read the strings as you would expect.
But, if you use std::getline after the initial formatted input, then, and remember that there is still a not-consumed '\n' at the end of the line, only an empty string and the newline will be read.
To overcome this situation, you can use std::ws. Please see here for a description. So, you simply add this in your std::getline statement.
Like this:
std::getline(ifs >> std::ws, line);
This will eat up all white spaces (including '\n') in front of the next text that you want to read.
To explain it better. This is a nested statement. So, first ifs >> std::ws is executed. This operation returns again ifs and then the std::getline will be done. You can of course also use ifs >> std::ws outside of the std::getline. That is in most cases better than calling ignore.
But remember. This is only necessary, if you switch from formatted to unformatted input.

C++ string.empty not working

I'm trying to use .empty() so pressing enter in the following code will not execute the if statement and the do-while loop will break. When I try this code, hitting enter does nothing: it just continues indenting until I enter more data. I looked up .empty() and I think I am using it correctly. Why isn't this code working?
void Student::read()
{
string g = " ";
cout << "Enter the students name: ";
getline(cin, new_name);
cout << endl;
do
{
cout << "Please enter a letter grade <E to quit>: ";
cin >> g;
if(!g.empty())
{
addGrade(g);
}
}while(!g.empty());
}
The problem is nothing to do with string.empty(), it is this line:
cin >> g;
That operation is whitespace delimited. That is to say, it skips all leading whitespace, and then once it has started consuming non-whitespace characters, it stops on the next whitespace if finds. So you can just press enter all day long, and it will be ignored, because pressing enter causes a newline character ('\n'), which is whitespace.
If you want line oriented input, use getline instead of operator>>.
getline(cin, g);
std:;string:empty() is working as expected in this. As Benjamin pointed out instead if you use getline(cin, g); in place of cin>>g you can achieve what you are expected:
int main()
{
string g = " ";
std::string new_name;
cout << "Enter the students name: ";
getline(cin, new_name);
cout << endl;
do
{
cout << "Please enter a letter grade <E to quit>: ";
getline(cin, g);
if(!g.empty())
{
std::cout<<"here";
//addGrade(g);
}
}while(!g.empty());
return 0;
}

String getline(cin,variable) function is skipping some lines of code

My program skips some code when I use the getline(cin,variablehere) function. I don't know whats wrong with the code. See the output below
#include <iostream>
#include <string>
using namespace std;
int main()
{
string getfirstname;
string lastname;
string address;
int contactnumber;
cout << "Enter First name : ";
getline(cin, getfirstname);
cin.ignore();
cout << "Enter Last name : ";
getline(cin, lastname);
cin.ignore();
cout << "Enter Address : ";
getline(cin, address);
cin.ignore();
cout << "Enter Contact number : ";
cin >> contactnumber;
cin.ignore();
CurrentNumberOfContacts += 1;
cout << "Successfully added to contact list!" << endl << endl;
cout << "Would you like to add another contact ? [Y/N] ";
cin >> response;
//more lines of codes below
return 0;
}
I have inputed 'int' as data type because it will contain numbers only
I recommend removing all the cin.ignore() commands.
One of the problems with user input is that the >> operator does not take the RETURN character out of the stream so if you follow it with a getline() the getline() will read the RETURN character instead of what you want to type in.
So I would change all your getline() to this:
// cin >> ws will skip any RETURN characters
// that may be left in the stream
getline(cin >> ws, lastname);
Also remove all of your cin.ignore() commands. They are not doing anything useful when used after a getline() command and if you change your getline() commands as I showed they should not be necessary at all.
So this should work:
int main()
{
string getfirstname;
string lastname;
string address;
char response;
int contactnumber;
int CurrentNumberOfContacts = 0;
cout << "Enter First name : ";
getline(cin >> ws, getfirstname);
cout << "Enter Last name : ";
getline(cin >> ws, lastname);
cout << "Enter Address : ";
getline(cin >> ws, address);
cout << "Enter Contact number : ";
cin >> contactnumber;
CurrentNumberOfContacts += 1;
cout << "Successfully added to contact list!" << endl << endl;
cout << "Would you like to add another contact ? [Y/N] ";
cin >> response;
//more lines of codes below
return 0;
}
Strictly speaking not all of your getline() functions need to employ the cin >> ws trick. I suppose the (incomplete) rules are as follows:
If you use a std::getline() after a >> then use:
std::getline(cin >> ws, line);
Otherwise just use:
std::getline(cin, line);
cin >> and getline do not cooperate very well. They have different strategies for how to deal with whitespace. getline removes the newline character, but cin >> leaves it. This means that after you use cin >> to read something, there will be a newline character left waiting in the input stream for the next getline to "use". Which means it will read an empty line into the string.
2 things. First, you don't really need cin.ignore() in this case as your using
getline().
before
cin >> variable
Second, I don't know why your program doesn't run, but I would suggest using a
getline()
call and see if that works. But I see no reason why your code is not working.
The answer provided by #Galic is quite good but If you want to read a line of characters without discarding the leading spaces you need another solution.
You could do:
char a='\n';
while (a=='\n')
{
cin.get(a);
}
cin.unget();
before doing your first getline. This assumes no trailing space resulting from a previous cin and that your first input line is not empty.

Can't get char from cin.get()

I'm working through some beginner exercises on c++, and this has me stumped. I can enter a number, but I don't get the option to enter a character afterwards, and it skips to the final line.
I know I can use cin >> symbol, but i would like to know why this isn't working.
#include<iostream>
using namespace std;
int main() {
cout << "Enter a number:\n";
int number;
cin >> number;
char symbol;
cout << "Enter a letter:\n";
cin.get(symbol);
cout << number << " " << symbol << endl;
return 0;
}
You should remove '\n' from stream, remained after entering the number:
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
Without it you will read newline character. You could check that with:
std::cout << (symbol == '\n') << std::endl;
\n will remain in the buffer after the first cin. You can solve this problem by adding an empty cin.get() between two consecutive reads.
cin.get(string1,maxsize);
cin.get();
cin.get(string2,maxsize);
Or you can use fflush:
cin.get(string1,maxsize);
fflush(stdin);
cin.get(string2,maxsize);

Using a space for canceling a simple loop

Here is my code for this simple assignment:
Write the code that will read character input from the user until a blank (a space) is entered. Print how many characters were entered. Keep in mind the user may decide to enter a blank as his first character.
Why is the space not ending the loop?
#include <iostream>
using namespace std;
int main(){
char answer;
int count=1;
do{
cout << "please enter number " << count;
cin >> answer;
count++;
}while(answer!=' ');
cout << "you entered " << count-1 << "numbers." << endl;
return 0;
}
The cin >> operations skip all kinds of whitespace by default. You can use cin >> noskipws; before your loop to disable whitespace skipping or use cin.get() instead:
cin.get(answer);
You should be aware that newlines and carriage returns are no longer skipped now, so you have to handle them separately. Also, you should check the stream status to react to end-of-file:
do {
cout << "Please enter number " << count << endl;
do {
cin.get(answer);
} while (cin && (answer == '\r' || answer == '\n'));
count++;
} while (cin && answer != ' ');