How to break from a while loop with bool? [duplicate] - c++

This question already has answers here:
Read file line by line using ifstream in C++
(8 answers)
Closed 1 year ago.
I am trying to get the user to key in data and store them inside a vector so when -1 is being entered it will break the entire loop and start displaying the vector. However it is currently not working even if -1 has been entered the loop will still continue to go on.
void cargo::addCargo(vector<cargo> &userCargo)
{
fstream file;
file.open("cargo.txt", ios::out | ios::app);
int i = 0;
bool checker = true;
cargo newCargo;
while (checker == true)
{
cout << "Enter id" << endl;
if (cin.peek() == '-1')
{
checker = false;
cout << "Hello";
}
else
{
cin >> idCon;
newCargo.setId(idCon);
}
cout << "Enter Destination Country" << endl;
if (cin.peek() == '-1')
{
checker = false;
}
else
{
cin >> destCountryCon;
newCargo.setDestCountry(destCountryCon);
}
cout << "Enter Time" << endl;
if (cin.peek() == '-1')
{
checker = false;
}
else
{
cin >> timeCon;
newCargo.setTime(timeCon);
newCargo.setIndex(i + 1);
userCargo.push_back(newCargo);
}
cout << endl;
i++;
}
//loop to display the entire vector
displayCargo(userCargo);
}

You are code is not self-contained so I can't fix it for you. The pragmatic answer is break or continue with a flag like checker. peek() looks at the next character and when the user enters "-1" it will return '-' and not the multi-character constant '-1'. Alternative, user can press ctrl-d to trigger eof. If you want to use "-1" (who came up with that terrible ux?), read that as a string or int.

Related

I am getting the error that variable "count" is not being initialized. But it should be initializing after reading and verifying data from file. C++

I am working on Login/Registration system. So far I am getting the error that the variable "count" is used without being initialized.
bool count;
string userId, password, id, pass;
system("cls");
cout << "\t\t\n Please enter the username and password\n\n";
cout << "Username:";
cin >> userId;
cout << "Password:";
cin >> password;
//reads info from the file
ifstream readL("record.txt");
while (readL >> id >> pass) {
if (id == userId && pass == password) {
count = true;
}
else {
count = false;
}
}
readL.close();
if (count == true) {
cout << userId << " your LOGIN is successfull.\n\n";
main();
}
else {
cout << "\nLOGING error\n\nPlease check your username and password\n\n\n";
main();
}
I have second part of the code and same system works here. `
case 1: {
bool count;
string suserId, sId, spass;
cout << "\n\nEnter the username that you remember:";
cin >> suserId;
//reads the file
ifstream f2("records.txt");
while (f2 >> sId >> spass) {
if (sId == suserId) {
count = true;
}
else {
count = false;
}
}
f2.close();
if (count == true) {
cout << "\n\n\tYour account is found!\n\nYour password is " << spass << endl << endl;
main();
}
else {
cout << "\n\n\tSorry your account is not found." << endl << endl;
main();
}
break;
}
`
The only difference that in the first case it reads two variables during the while if statement, in second only Username.
But even if I am going to read only Username in the first case error is still appearing.
Your C++ compiler is smart enough to figure out that if the file could not be opened or is empty, the while loop never executes even once, and count remains uninitialized until its value is checked after the loop. That's what your C++ compiler is telling you.
Just because the input file exist or is not empty, and its contents are valid (because garbage in it will also result in the initial attempt to read it fail) is immaterial. It is logically possible for count to be uninitialized when its value gets used, hence your compiler's diagnostic.
P.S. the while loop's logic is also fatally flawed, for a different reason. But that's unrelated to the compiler diagnostic you asked about.
Maybe you should just initialize it with
bool count = false;

Detect blank input on integer type variable?

I am currently working on a text based adventure game as a project for class. I have mostly everything started and working fine. The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room." For the life of me I cannot figure it out. Any help is much appreciated.
Code:
#include <iostream>
#include <cstdlib>
#include <ctime>
using namespace std;
int main() {
bool game_play = true;
bool game_start = true;
int room_change;
int room_current = 0;
while (game_play == true) {
if (game_start == true) {
srand((unsigned int)time(NULL));
room_change = rand() % 2 + 1;
game_start = false;
}
else {
for (bool check = false; check == false;) { // Check if input is invalid
cin >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
}
else if (room_change == room_current) {
cout << "You're already in that room.";
}
else {
check = true;
}
}
}
switch (room_change) {
case 1:
cout << "You are in room 1.";
room_current = 1;
break;
case 2:
cout << "You are in room 2.";
room_current = 2;
break;
case 3:
game_play = false;
break;
default:
cout << "That room doesn't exist.";
}
}
return 0;
}
I just ran your code and when you hit enter, it will keep waiting until you enter a number or something invalid such as a character or a string. I did find that if you change your code from
cin >> room_change;
to
cin >> noskipws >> room_change;
when the user inputs a blank, it will cause the cin.fail() to return true and then proceed to print "Choose an existing room."
In your situation, the while loop will keep getting called until we have valid input. The "Choose an existing room" does get repeated because room_change is an integer, so when we hit enter, the '\n' will be left in the buffer. The while loop on the next iteration then reads that '\n' and executes the cin.fail() before letting you input something else. One solution I found is to use more cin.ignore() statements.
for (bool check = false; check == false;) { // Check if input is invalid
cin >> noskipws >> room_change;
if (cin.fail()) {
cout << "Choose an existing room.";
cin.clear();
cin.ignore();
} else if (room_change == room_current) {
cout << "You're already in that room.";
cin.ignore();
} else {
check = true;
cin.ignore();
}
}
The reason is because we want to get rid of that '\n' so that the cin.fail() does not execute. However, I did find that when you input a character, it will print "Choose an existing room" twice. It will print the first time because a character is not an integer, and a second time because of that '\n'.
The only problem is when I ask the user which room they want to change to, if they enter a blank input, then a message should output saying "You must choose a room."
Using std::getline and then extracting the number from the line using a std::istringstream is a better strategy for that.
std::string line;
std::cout << "Choose an existing room. ";
while ( std::getline(std::cin, line) )
{
// Try to get the room_change using istringstream.
std::istringstream str(line);
if ( str >> room_change )
{
// Successfully read the room.
break;
}
// Problem reading room_change.
// Try again.
std::cout << "Choose an existing room. ";
}
#include <iostream>
using namespace std;
int main(){
int room_change=200;
cout<<"Enter Blank";
cin>>room_change;
if(room_change==NULL){
cout<<"There is NO-THING"<<endl;
}
if(room_change!=NULL){
cout<<"There is something and that is :"<<room_change<<endl;
}
return 0;
}
But a much simpler approach to this would be to use Strings. If this is a Homework of sort and you are limited to Integer variable only. Its much more complicated if you want to detect if an Buffer is empty or not. Regardless of homework limitation, the OS layer input is String based. How can I use cin.get() to detect an empty user input?

How do I stop spaces from displaying as carriage returns when read in from a file?

void displayFile()
{
char userInput[20];//Used to store the typed input commands from the user.
ifstream ip("D:\\H Drive ITT\\Level 8 Degree\\Software Dev (Andrew)\\MiniProject\\about.txt");//Input from file
string line ;//Store each line in the string
int exit = 0;//Used to hold the value which indicates whether or not the function should end determined by the user.
if (ip)//ip is true if the file exists.
{}
else
{
cout << "-Error_File_Not_Found" << endl;
}
while (!ip.eof())//Scan till end of file
{
ip >> line;
cout << line << endl;
}
cout << "Type exit to return" << endl << endl << ">>>" ;
do {
cin >> userInput;
if (strcmp(userInput, "exit") == 0 || strcmp(userInput, "EXIT") == 0 || strcmp(userInput, "eXIT") == 0 || strcmp(userInput, "Exit") == 0)
{
exit = 1;
}
else
{
exit = 0;
}
} while (exit !=1);
ip.close();
}
//The
//output
//displays
//like
//this.
When the code runs it takes in the paragraph and displays each word on a line of its own. I have seen solutions that involve classes but I need a different solution as I have not done classes yet.
There are two problems here.
The >> operator does not read lines, it stops on whitespace. Use std::getline as Ramana suggested in the comments.
You are using eof() incorrectly. It returns true after you have already read past the end of the file, not before you would read past the end. So your loop will iterate one time too many. The best method is to use the return value of std::getline as the loop condition.

Both If and Else condition execute C++ [duplicate]

This question already has answers here:
eof problem c++
(3 answers)
Closed 8 years ago.
I have a function for deleting data from a text file.
I'm having problems when valid input is entered:
if I enter bad input, it only executes the else part, as expected
if I enter valid input, it executes both the if and the else part.
Here is my code:
void Member::processTransaction()
{
fstream f;
f.open("Member.txt",ios::in|ios::out);
int x = 0, y = 0, z = 0;
while (!f.eof())
{
f >> idList[x] >> nameList[y];
if (id == idList[x])
{
cout << idList[x] << "\t" << nameList[x] << endl;
cout << "Do you want to delete the entry (Y/N) : " << endl;
char deleteEntry = getche();
if(deleteEntry=='Y'||deleteEntry=='y')
deleteInformation();
f.close();
}
else
{
cout << "No Matches Found!";
}
}
}
in the output. If I enter True, it executes and displays "No Matches Found".
If I enter false, it only displays "No Matches Found" and its fine.
while(!f.eof()){ is almost always a mistake. This case is no exception.
eof means you tried to read something previously, and it failed due to end of file. It's false if you have read the whole file exactly, and it's false if you close the file before trying to read past the end as you do in this example. And it's false if the stream is in an error state for another reason.
Instead , change to while (f >> idList[x] >> nameList[y]), and use break; if you want to exit the loop for some other reason than this read failing.
void Member::processTransaction() {
fstream f;
f.open("Member.txt", ios::in | ios::out);
int x = 0, y = 0, z = 0;
bool found = false; // found or not?
// search the file now.
while(!f.eof() && !found) {
f >> idList[x] >> nameList[y];
if(id != idList[x]) {
continue;
}
cout << idList[x] << "\t" << nameList[x] << endl;
cout << "Do you want to delete the entry (Y/N) : " << endl;
char deleteEntry = getche();
if(deleteEntry == 'Y' || deleteEntry == 'y') {
deleteInformation();
}
found = true;
}
f.close(); // close here
// not found only after you're done searching.
if(!found) {
cout << "No Matches Found!";
}
}
Your code is bad. My code is just less bad. Your entire way of doing this is flawed. But this is the right wrong way to do it.

Skipping lines and not leaving them blank w/ ofstream

I have a pretty basic ofstream() question. I have an app that matches data that was inputted by a user in a text document. Can i skip lines with ofstream and not modify text already there? If possible, how? Please forgive me my English isn't too great.
#include <fstream>
#include <iostream>
#include <string>
using namespace std;
int main()
{
int count = 0;
int num;
int numcopy;
string clientNames[3000];
string caseNumbers[3000];
int userInp = 1;
string confirm = "2";
cout << "Do you have a file already started (y/n)?"<<endl;
cin >> confirm;
if(confirm == "y")
{
goto input;
}
if(confirm == "n")
{
goto postinput;
}
input:
cout << "What is the number of the query last entered?";
cin >> userInp;
num = userInp;
numcopy = userInp;
postinput:
for(int i = 1; i <3000; i++)
{
userInp ++;
repeat:
cout <<"Enter Client's Name:";
cin >> clientNames[userInp];
cout << " " <<endl;
cout <<"Enter Case Number:";
cin>> caseNumbers[userInp];
cout <<"Client Name "<< i << " "<<clientNames[userInp]<<endl;
cout << "Case Number" << i << " "<<caseNumbers[userInp]<<endl;
cout <<"Is This Correct?"<<endl;
confirm == " ";
cin >> confirm;
if(confirm == "y")
{
cout <<"Confirmed"<<endl;
}
if(confirm == "n")
{
goto repeat;
}
if(confirm == "/end")
{
break;
}
}
ofstream file;
file.open("caseData.txt");
for(int w = 0; w <3000;w++)
{
num++;
file <<
}
}
"skip lines with ofstream and not modify text already there" is not possible.
But you can store all lines of the file in your program first. And while you are processing the file, output the stored line when you want to leave that line unchanged.
This effectively does what you want.
Also, you really should get rid of the gotos in your code. They should be used only in rare cases. And for beginners, I always feel they should not use it until they are very familiar with programming.
I am going to take a guess that you want to do something about the circumstance when the user has inputted the same clientName or same caseNumber multiple times. It is actually not entirely clear from your question that this is what you want to do, but you asked:
I have an app that matches data that was inputted by a user in a text document. Can i skip lines with ofstream and not modify text already there? If possible, how?
However, I did not see any matching logic in your program. You are simply recording up to 2999 entries (since you don't use the 0 entry of your arrays), or wait until the user enters /end as a confirmation message.
If you had actual matching logic, you could detect on input whether the user has typed in the same clientName or same caseNumber, and you can prompt the user for what to do about it (for example, keep the old existing entry, keep newly entered entry). If you had such logic, you would know that you would only be outputting unique lines of data, and so your output loop would be fairly simple.
There were some comments made on your use of goto. Instead of the repeat: label, you could start another loop:
//repeat:
do {
// ...read in input, echo it back, wait for confirmation...
cin >> confirm;
if (confirm == "y") {
cout << "Confirmed" << endl;
break;
}
} while (confirm != "/end");
if (confirm == "/end") {
break;
}
In this code, anything other than a y or /end is treated the same as n.