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;
}
Related
Basically I have a function, that writes into a .txt file.
The user has to input, what will be written in the file.
The problem is, every word has a new line, even tho it's written in the same line, while doing the input.
But I want it to be the way the user inputs it.
void Log_Write::WriteInLog(std::string LogFileName)
{
system("cls");
std::string input;
std::ofstream out;
out.open(LogFileName, std::fstream::app);
out << "\n\nNEW LOG ENTRY: " << getCurrentTime()<<"\n"; //
while (true)
{
system("cls");
std::cout << "Writing in Log\n\nType 'x' to leave editor!\n\nInsert new entry: ";
std::cin >> input;
if (input == "x")
break;
out << input << "\n"; // How do I change this so it doesn't create a new line for each word
}
out.close();
}
Sample Input:
1st Input:Test Input
2st Input:Next input
Sample Output in file.txt:
Test
Input
Next
Input
(Without the spaces in between!)
std::cin >> input; just reads to the first whitespace while std::getline(std::cin, input); would read the whole line.
One way of fixing it:
while(
system("cls"),
std::cout << "Writing in Log\n\nType 'x' to leave editor!\n\nInsert new entry: ",
std::getline(std::cin, input)
) {
if (input == "x")
break;
out << input << '\n';
}
I put the std::getline call last in the while condition to make the loop exit if std::getline fails.
Now, the above looks pretty nasty so I suggest putting clearing the screen and prompting the user in a separate function instead.
Example:
#include <iostream>
#include <string>
#include <string_view>
std::istream& prompt(std::string_view prompt_text, std::string& line,
std::istream& in = std::cin,
std::ostream& out = std::cout) {
std::system("cls");
out << prompt_text;
std::getline(in, line);
return in;
}
void Log_Write::WriteInLog(std::string LogFileName) {
// ...
auto prompt_text = "Writing in Log\n\n"
"Type 'x' to leave editor!\n\n"
"Insert new entry: ";
while (prompt(prompt_text, input)) {
if (input == "x") break;
out << input << '\n';
}
}
I am writing a database program with many features (Read, write, delete, search, login ect. ) and my writing feature just stopped working (It was working 3 days ago) and I have no idea what changed. My writing function (void savescore) is supposed to write my input (cin username and password) and then move to the next line so I can input some more info the next time I decide to go and write to the file. Right now it's just writing over what I last put in.
test2.txt -
Username, Password
Then I go to edit and enter "User, Pass" and this is what happens
test2.txt - User, Pass
I want it to enter that on the next line and I did "\n" Can someone give me some help? Thanks
CODE:
#include <iostream>
#include <stdlib.h>
#include <windows.h>
#include <fstream>
#include <conio.h>
#include <string>
#include <math.h>
using namespace std;
// Variables
string username;
string password;
//alphabet order functions
// Functions
void SaveScore()
{
ofstream Database;
Database.open("test2.txt");
Database << username << " " << password << "\n";
Database.seekp(0,std::ios::end); //to ensure the put pointer is at the end
Database.close();
}
int main()
{
int db;
char ans;
string save;
string file;
ifstream fin;
ofstream fout;
string searchpar;
char repeat;
bool loop = true;
while (loop == true)
{
cout << "WELCOME TO MY DATABASE\n\n";
cout << "To view the database, press 1\nTo edit the database, press 2\nTo search the database, press 3\nTo log in, press 4\n";
cin >> db;
system("CLS");
if (db == 1)
{
cout << "Here is the database: \n\n";
string line;
ifstream myfile("test2.txt");
if (myfile.is_open())
{
while (getline(myfile, line))
{
cout << line << '\n';
}
}
//open while bracket
cout << "\n\nWould you like to return to the menu(y/n)?";
cin >> repeat;
if (repeat == 'y')
{
loop = true;
}
else if (repeat == 'n')
{
loop = false;
}
system("CLS");
}
else if (db == 2)
{
cout << "Please enter your username : ";
cin >> username;
cout << "\nPlease enter your password: ";
cin >> password;
SaveScore();
cout << "\n\nWould you like to return to the menu(y/n)?";
cin >> repeat;
if (repeat == 'y')
{
loop = true;
}
else if (repeat == 'n')
{
loop = false;
}
system("CLS");
}
}
}
You say your program is
replacing the first line of the text file everytime I try to write something new into it
As it turns out, that's exactly what you have asked it to do. Consider:
Database << username << " " << password << "\n";
Database.seekp(0,std::ios::end); //to ensure the put pointer is at the end
You are opening the file (when the write pointer starts at the start of the file, writing some data, and then seeking to the end. Seeking to the end does not change the fact that you've already written the text. Swap the order of the above lines to get what you want.
Alternatively, you can open the file in "append" mode using:
Database.open("test2.txt", std::ios::app);
In this situation, you can omit the call to seekp entirely, since all data will automatically be written to the end of the file. See http://en.cppreference.com/w/cpp/io/basic_ofstream/basic_ofstream for full documentation on this.
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);
}
}
I would like to create a program where the user inputs a specific set of numbers of characters, then check an already created file if it has the EXACT same characters typed by the user in each line.
My code:
string line;
string employeeID;
bool found = false;
ifstream stream1("employees.txt", ios::app);
do{
cout << "Enter Employee Password:" << endl;
getline(cin, employeeID);
while (!stream1.eof())
{
getline(stream1, line);
if (employeeID == line){
found = true;
}
}
} while (found == false);
And my employees.txt file contains:
ADH4172
DGGH481
so in other words, I don't want it to proceed with the program if they do not input ADH4172 or DGHH481 as the employee ID. However, the method above does not seem to work. Thanks for your help.
CODE AFTER FIX:
string line;
string employeeID;
bool found = false;
cout << "This portion of the program asks for the employee password, and checks its existence from a text files.\nThe passwords are 5555 and 6666. Any other string will not work\n" << endl;
do{
ifstream input("employees.txt", ios::app);
cout << "Enter Employee Password:" << endl;
getline(cin, employeeID);
while (!input.eof())
{
getline(input, line);
if (employeeID == line){
found = true;
input.close();
}
}
if (found == false){
cout << "Incorrect, try again\n" << endl;
input.close();
}
} while (found == false);
while (found=false) sets found to false, making the condition false, so the loop terminates immediately. Change it to `found == false'.
#include <fstream>
#include <iostream>
#include <cstring>
using namespace std;
int main()
{
char filename[20] = "filename";
char userInput;
ofstream myFile;
cout << "Enter filename: ";
cin.getline(filename, sizeof(filename));
myFile.open(filename);
if(myFile.fail())
{
cout << "Error opening file: "
<< filename << "\n";
return 1;
}
cout << "Add text to the file: ";
cin.get(userInput);
while(cin.good() && userInput)
{
myFile.put(userInput);
cin.get(userInput);
}
myFile.close();
return 0;
}
Im having trouble terminating the input without force quiting it(It still writes to the file).
This is what I am supposed to do
Receives a line of input from the user, then outputs that
line to the given file. This will continue until the line input
by the user is “-1” which indicates, the end of input.
however I cannot work out the -1 part. Any help would be greatly appreciated everything else seems to work.
You're making things a bit more complicated than they need to be. Why C strings instead of std::string, for example? Using the right (standard-provided) classes generally leads to shorter, simpler and easier-to-understand code. Try something like this for starters:
int main()
{
std::string filename;
std::cout << "Enter filename" << std::endl;
std::cin >> filename;
std::ofstream file{filename};
std::string line;
while (std::cin >> line) {
if (line == "-1") {
break;
}
file << line;
}
}
First of all, the assignment asks to read a line from the user, character-wise input by get() shouldn't be the function to use. Use the member function getline() as you did to recieve the file name and use a comparison function to check against -1:
for (char line[20]; std::cin.getline(line, sizeof line) && std::cin.gcount(); )
{
if (strncmp(line, "-1", std::cin.gcount()) == 0)
break;
myFile.write(line, std::cin.gcount());
}