how to avoid blank input by using getline()? - c++

When I just press enter without input anything, getline() function also receive the blank input. How to fix it to not allow blank input(Has character and/or number and/or symbol)?
string Keyboard::getInput() const
{
string input;
getline(cin, input);
return input;
}

You can keep re-doing the getline as long as the input is blank. For example:
string Keyboard::getInput() const
{
string input;
do {
getline(cin, input); //First, gets a line and stores in input
} while(input == "") //Checks if input is empty. If so, loop is repeated. if not, exits from the loop
return input;
}

Try this:
while(getline(cin, input))
{
if (input == "")
continue;
}

string Keyboard::getInput() const
{
string input;
while (getline(cin, input))
{
if (input.empty())
{
cout << "Empty line." << endl;
}
else
{
/* Some Stuffs */
}
}
}

Related

Creating a text file with a certain string and using it to compare in the future

I want to create a text file for first run carrying the password and use the code to check the entire string for the password entered previously.
The current code returns true value for the 1st few alphabets even if the whole password isn`t entered.
int Manager::ManagerView1()
{
Passwordsearch:
system("cls");
string search;
int offset,ErrorVar;
string line;
ifstream Myfile;
Myfile.open("Password.txt");
cout << "Enter your Password :\n";
cin >> search;
if (Myfile.is_open())
{
while (!Myfile.eof())
{
getline(Myfile,line);
if ((offset = line.find(search, 0)) != string::npos)
{
cout << "Password Accepted ..\n";
system("pause");
}
else
{
cout << "Password Incorrect. \nPress\n 1.) Go back to the main screen\n 2.) Re-Enter Password \n";
cin >> ErrorVar;
if (ErrorVar == 1)
{
system("PAUSE");
return 1;
}
else if (ErrorVar == 2)
{
system("PAUSE");
system("cls");
goto Passwordsearch;
}
else
{
cout << "Wrong option !! Please try again\n";
system("PAUSE");
return 1;
}
}
}
}
}
This is the password file that i want to check the string from:
Your problem is because of how the find function works. It looks for the sub-string contained in search.
You have to extract the complete password from the file, and then compare using equality instead of just searching for a sub-string.
When you use string.find(param1, param2) it just tells you if a string in this case "Anonymous" does contain text you put as a first paramater inside find() function.
If you want to avoid that you shouldn't be using *find()* at all.
Instead, you should do comparing.
First you read the string from txt file and store it in a string line. Then you ask user to enter password after he enters password, you check if your string line is eqaul to password .
std::string my_pass = "Anonymous";//Get it from file.
std::string input_pass = "";
std::cin >> input_pass;
if(input_pass==my_pass){
std::cout << "PASSWORD CORRECT\n";
}

Having trouble validating a file over and over again

One of the things my program needs to do is validate a file using the isValid function entered by user and it will keep doing this until exit is entered and if I enter nothing but valid file names there are no problems. But when I enter an invalid file name followed by a valid file name it still says the file is invalid and I cannot figure out why and I have tried debugging it and what not and still cannot find the problem. Any help would be greatly appreciated!
# include <iostream>
#include <string>
#include<fstream>
#include<vector>
using namespace std;
void Open_file(string name)
{
ifstream my_file;
my_file.open(name.c_str());
}
bool isValid(ifstream& file, string name)
{
if ((name.substr(name.length() - 4)) != (".htm"))
{
return false;
}
cout << file << endl;
if (file.good())
{
return true;
}
else
{
return false;
}
}
string File_title(ifstream& my_file)
{
string title;
string line;
size_t first_title;
size_t second_title;
string str;
while((getline(my_file,line)))
{
str = str + line;
}
first_title = str.find("<title>");
second_title = str.find("</title>");
title = str.substr(first_title + 7, (second_title) - (first_title + 7));
return title;
}
void Output_function(ifstream& my_file)
{
string line;
ifstream MyFile("titles.txt");
string g = File_title(my_file);
while(getline(MyFile, line))
{
if((g == line))
{
return;
}
}
ofstream out_title("titles.txt", fstream::app);
out_title << g << endl ;
}
void Clear_file()
{
ofstream out_title("titles.txt");
out_title << "" << endl;
}
int main()
{
string file_name;
while (file_name != "exit")
{
cout <<"please enter a HTML file name or hit 'exit' to quit and " << endl;
cout << "if you want to clear file please enter 'clear': ";
getline(cin,file_name);
ifstream my_file(file_name.c_str());
cin.ignore(256, '\n');
if(file_name == "clear")
{
Clear_file();
break;
}
while ((isValid(my_file, file_name) == false))
{
cin.clear();
cout <<"Invalid file name, please enter a valid file name: ";
getline(cin,file_name);
ifstream my_file(file_name.c_str());
}
Open_file(file_name);
Output_function(my_file);
my_file.close();
}
}
ifstream my_file(file_name.c_str());
This doesn't replace the my_file you'd already created in an outer scope. It just makes a new local variable that lives for like a nanosecond.
You'll have to close then re-open the existing my_file, being sure to reset its error flags too.
The logic you are using to exit the loop is flawed.
You need to check the value of file_name right after it is entered, not after it is processed in the while loop once.
You need to use something along the lines of:
while ((file_name = get_file_name()) != "exit")
{
...
}
where
std::string get_file_name()
{
std::string file_name;
cout <<"please enter a HTML file name or hit 'exit' to quit and " << endl;
cout << "if you want to clear file please enter 'clear': ";
getline(cin,file_name);
return file_name;
}
Other improvements:
The call to cin.ignore() is going to be a problem line since std::getline does not leave the newline character in the input stream. You'll have to type Enter one more time. You should remove it.
You don't need the cin.clear() line. You need cin.clear() only if an error was detected in reading from the stream -- such as when using cin >> var; when the input stream did not have the right data suitable for var.
You don't need to open the file if the file is not valid.
You don't need multiple lines ifstream my_file(file_name.c_str());. You only need it once, just before the call to Output_function(my_file).
You don't need to explicitly call my_file.close(). The file will be closed and the end of the scope.
Here's a simplified version of main.
int main()
{
string file_name;
while ((file_name = get_file_name()) != "exit")
{
if(file_name == "clear")
{
Clear_file();
break;
}
while ( isValid(my_file, file_name) == false )
{
cout <<"Invalid file name, please enter a valid file name: ";
getline(cin,file_name);
}
Open_file(file_name);
ifstream my_file(file_name.c_str());
Output_function(my_file);
}
}

Searching text file for specific user-inputted string

I'm trying to write a program which opens a text file full of words (a "dictionary" minus the definitions) and stores these values in strings to compare them against a user input to determine whether the user input is spelled correctly.
I go the program to work and do what I wanted, but I can't seem to figure out one specific detail. I want the program to continue running until the user enters "exit" as an input. The only problem is that my program continues spewing out either "input is spelled correctly" or "input is not spelled correctly" ad infinitum without giving the user a chance to input more values in.
How do I make it so the program only outputs one of these two options only once and then prompts the user for another input instead of a never-ending stream of the same statement? Thank you in advanced!
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string line; //holds values from txt file
string input; //holds user-inputted values
ifstream inputFile; //fstream operator declaration
bool isFound = false; //bool value to indicate if the string has been found
inputFile.open("dict.txt", ios::in);
if (inputFile)
{
cout << "Enter word to spellcheck (or exit to end)\n";
getline(cin, input);
while (input != "exit")
{
while (getline(inputFile, line))
{
if (input == line)
{
isFound = true;
break;
}
else
{
isFound = false;
}
}
inputFile.close();
if (isFound)
{
cout << input << " is spelled correctly.\n";
}
else
{
cout << input << " is not spelled correctly.\n";
}
}
if (input == "exit")
{
cout << "Ending program...\n";
}
}
else
{
cout << "Cannot open file\n";
}
return 0;
}
Inside the body of the
while (input != "exit")
loop the user is never asked to update the value of input. Moving getline(cin, input) into the while condition like this:
while (getline(cin, input) && input != "exit")
will solve that problem.
Then next problem is the handling of the dictionary file. It is closed in the middle of the loop, so subsequent reads from it will instantly fail. OP could reset the read pointer to the beginning of the file with inputFile.seekg(0);, but why reread the file every time.
Instead read the dictionary file into a std::set with more or less the same code as used in the search:
std::set<std::string> dictionary;
while (getline(inputFile, line))
{
dictionary.insert(line);
}
at the beginning of the program and search the set for the user's input in the loop.
if (dictionary.find(input) != dictionary.end())
{
cout << input << " is spelled correctly.\n";
}
else
{
cout << input << " is not spelled correctly.\n";
}
This should do the trick, you just need to move your getline block in the while loop, and move the file close statement outside the while loop:
#include <iostream>
#include <fstream>
#include <string>
#include <cstdio>
using namespace std;
int main()
{
string line; //holds values from txt file
string input; //holds user-inputted values
ifstream inputFile; //fstream operator declaration
bool isFound = false; //bool value to indicate if the string has been found
inputFile.open("dict.txt", ios::in);
if (inputFile)
{
while (input != "exit")
{
// Rewind file back to beginning every time
inputFile.clear();
inputFile.seekg(0,std::ios::beg);
cout << "Enter word to spellcheck (or exit to end)\n";
getline(cin, input);
while (getline(inputFile, line))
{
if (input == line)
{
isFound = true;
break;
}
else
{
isFound = false;
}
}
if (isFound )
{
cout << input << " is spelled correctly.\n";
}
else
{
if (input != "exit"){ // Don't print message if exiting
cout << input << " is not spelled correctly.\n";
}
}
}
if (input == "exit")
{
cout << "Ending program...\n";
}
inputFile.close();
}
else
{
cout << "Cannot open file\n";
}
return 0;
}

Why does this not ask user for another input?

This part of a larger project. Right now it's supposed to ask user for a string, calculate how many words are in it, print out the # of words, ask user if they want to do it again, then if they want to, ask for another string, and so on. But this only works fine the first time. After that, it takes the answer to the yes/no question as the test string. For example: I like coding. 3. Again? Yes/no. Yes. 1. Again? Yes/no... Can someone tell me how to fix this glitch?
#include <iostream>
#include <string>
using namespace std;
string original[10] = { "hello", "sir", "madam", "officer", "stranger", "where", "is", "the", "my", "your" };
string translated[10] = { "ahoy", "matey", "proud beauty", "foul blaggart", "scurvy dog", "whar", "be", "th'", "me", "yer" };
string input;
string ans;
bool playAgain()
{
cout << "Another? yes/no: ";
cin >> ans;
if (ans.compare("yes") == 0) { return true; }
if (ans.compare("no") == 0) { return false; }
}
int getNumOfWords(string input)
{
int numOfSpaces = 0;
string current;
for (int i = 0; i < input.length(); i++)
{
current = input.at(i);
if (current.compare(" ") == 0)
{
numOfSpaces++;
}
}
return numOfSpaces + 1;
}
void play(string input)
{
int numOfWords = getNumOfWords(input);
cout << numOfWords << endl;
}
void start()
{
getline(cin, input);
play(input);
}
int main()
{
bool playing;
do
{
start();
playing = playAgain();
} while (playing);
return 0;
}
When cin.getline() reads from the input, there is a newline character left in the input stream, so it doesn't read your c-string. Use cin.ignore() beore calling getline()
void start()
{ cin.ignore();
getline(cin, input);
play(input);
}
It's because of the difference between getline and cout. The former reads in the entire line up to and including the terminating \n, while cout will read only up to the \n or whitespace. The cin in your code reads in yes or no to ans (try printing it out immediately afterwards), but it doesn't account for the \n. Thus, when you call getline it finds the \n waiting in stdin, and so reads that into input instead of blocking until cin wasn't empty.

Most common/idiotproof way to catch invalid input

I am getting into c++ right now, and right now I want to know the most common/best way to catch invalid input. I would love answers to this wide open question, but my more specific question is as follows.
I want a char from the user. If the char is 'y' then it will repeat, if it is 'n' then the program will close. If I enter multiple chars then it will repeat as many times as chars e.g. I enter 'hello' it will show my output 5 times. I assume that it reads each char and goes through the whole loop then reads the next char in line. How can I get it to show up just one time?
bool valid = 0;
while(valid)
{
...
bool secValid = 0;
while(secValid == 0)
{
cout << "To enter another taxable income type 'y': \n\n";
char repeat = NULL;
cin >> repeat;
if(repeat == 'y')
{
valid = 0;
secValid = 0;
system("cls");
}else if(repeat == 'n')
{
return;
}else
{
secValid = 1;
}
}
}
You could structure it something like this:
while(true) {
cout << "Repeat (y/n)? ";
string line;
if(!getline(cin, line))
break; // stream closed or other read error
if(line == "y") {
continue;
} else if(line == "n") {
break;
} else {
cout << "Invalid input." << endl;
}
}
Example session:
Repeat (y/n)? y
Repeat (y/n)? foo
Invalid input.
Repeat (y/n)? n
Here we use std::getline to get a whole line of input, instead of getting one character at a time.
std::getline():
std::string line;
std::getline(std::cin, line);
if (line == "y") {
// handle yes
}
else if (line == "n") {
// handle no
}
else {
// handle invalid input
}
use std::getline from the <string> header to read a line of input into a std::string
Also when checking string for "y" or "n" is good practise to use upcased string instead. For example
std::string YES = "Y";
std::string NO = "N";
...
std::string line;
std::getline(std::cin, line);
std::transform(line.begin(), line.end(), line.begin(), std::toupper);
if (line == YES)
{
...
}
else if (line == NO)
{
..
.
}