Over looping (Cout) in C++ - c++

#include <iostream>
#include <string>
#include <cctype>
using namespace std;
char hold;
string name;
char num1;
char num2;
int main() {
cout << "Hello!\n";
cout << "Tell me your name?: ";
cin >> name;
cout << "Well well well, if it isn't "<< name << "!\n";
cout << "Enter a NUMBER " << name << ": ";
cin >> num1;
while(!isdigit(num1)) {
cout << "Enter a NUMBER " << name << ": ";
cin >> num1;
}
cin >> hold;
system("pause");
return 0;
}
The problem is, it is overlooping the cout. How do I fix it?
Thanks.

A better way is to use std::stringstream (note: include sstream)
int getNumber()
{
std::string line;
int i;
while (std::getline(std::cin, line))
{
std::stringstream ss(line);
if (ss >> i)
{
if (ss.eof())
{
break;
}
}
std::cout << "Please re-enter your input as a number" << std::endl;
}
return i;
}
This replaces your while loop, and you make the call after asking for a number as you already figured out how to do.

The following is a shortened version of the original attempt. However, as with the original, it only checks a single character.
If I changed num1 to be an int then i'd need to check whether the input was valid as #Dieter Lucking mentioned.
#include <iostream>
using namespace std;
int main() {
char num1;
do {
cout << "\nEnter a number: ";
cin >> num1
} while(!isdigit(num1));
}

A bit of a variation on staticx's solution, which will pass Dieter Lücking's echo "" | test line.
I use an istringstream and get input until no more standard input or I get valid input. I pushed it all into a templated Get function that can be used for any type; you just need to give it a prompt for the user:
Get() function
template<typename T>
void Get(T& toSet, std::string prompt) // read from cin
{
std::string nextIn;
cout << prompt;
getline(cin >> std::ws, nextIn);
istringstream inStream(nextIn);
while(cin && !(inStream >> toSet))
{
inStream.clear();
cout << "Invalid Input. Try again.\n" << prompt;
getline(cin >> std::ws, nextIn);
inStream.str(nextIn);
}
if (!cin)
{
cerr << "Failed to get proper input. Exiting";
exit(1);
}
}
And you'd use it like so:
int myNumber = 0;
Get(myNumber, "Please input a number:");
Full code:
Live Demo
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
template<typename T>
void Get(T& toSet, std::string prompt) // read from cin
{
std::string nextIn;
cout << prompt;
getline(cin >> std::ws, nextIn);
istringstream inStream(nextIn);
while(cin && !(inStream >> toSet))
{
inStream.clear();
cout << "Invalid Input. Try again.\n" << prompt;
getline(cin >> std::ws, nextIn);
inStream.str(nextIn);
}
if (!cin)
{
cerr << "\nFailed to get proper input. Exiting\n";
exit(1);
}
}
int main()
{
string name;
int num1 = -1;
cout << "\nHello!\n";
Get(name, "\nTell me your name?:");
cout << "\nWell well well, if it isn't "<< name << "!\n";
Get(num1, std::string("\nEnter a NUMBER, ") + name + ": ");
cout << "\nYou entered number: " << num1 << std::endl;
return 0;
}

Related

Phone number lookup within text file

Basically My Program Goal is that i have a file containing 4 telephone numbers
it would Look Like this
Harry Keeling (555)123-4567
Frank James (555)123-8901
Arthur Paul (555)987-4567
Todd Shurn (555)987-8901
What my program is doing right now is prompting the user for the name and last name and iterates through the file to see if their is a match if their is a match the phone number is saved in the variable phone number if their isnt a match the program outputs error right now my program is doing what is susposed to do but after each match is found the program is susposed to prompt do you want to continue looking up numbers y or n if it is a yes it is susposed to loop through the file again but basically my program isnt working and i have no idea why my code
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
void lookup_name(ifstream&, string&); // prototype
int main()
{
ifstream myfile;
string phonenumber;
string choice;
lookup_name(myfile, phonenumber);
if (phonenumber == " ") {
cout << "Error" << endl;
}
else {
cout << "The Telephone Number you Requested is" << phonenumber << endl;
cout << "Do you Want to look up another name in the directory?" << " " << "<Y/N" << endl;
cin >> choice;
if (choice == "Y")
lookup_name(myfile, phonenumber);
}
}
void lookup_name(ifstream& myfile, string& phonenumber)
{
string fname;
string lname;
string name1, name2, dummy, choice;
myfile.open("infile.txt");
cout << "What is your first name" << endl;
cin >> fname;
cout << "What is your last name" << endl;
cin >> lname;
for (int i = 0; i < 4; i++) {
myfile >> name1 >> name2;
if (fname + lname == name1 + name2) {
myfile >> phonenumber;
myfile.close();
if (choice == "Y")
{
continue;
}
else {
myfile >> dummy;
}
}
}
}
You need to add a loop inside of main() itself to prompt the user to continue, and you need to fix the mistakes in your lookup_name() function.
Try something more like this instead:
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <limits>
using namespace std;
bool lookup_name(istream&, const string&, string&); // prototype
int main()
{
ifstream myfile("infile.txt");
string name, phonenumber, choice;
do
{
cout << "What is the name? ";
getline(cin, name);
if (!lookup_name(myfile, name, phonenumber)) {
cout << "Error" << endl;
}
else {
cout << "The Telephone Number you Requested is '" << phonenumber << "'" << endl;
}
cout << "Do you want to look up another name in the directory (Y/N)? ";
cin >> choice;
cin.ignore(numeric_limits<streamsize_t>::max(), '\n');
if ((choice != "Y") && (choice != "y"))
break;
myfile.seekg(0);
}
while (true);
return 0;
}
bool lookup_name(istream& myfile, const string& name, string& phonenumber)
{
string line, fname, lname;
while (getline(myfile, line))
{
istringstream iss(line);
if (iss >> fname1 >> lname)
{
if (name == (fname + " " + lname))
return getline(iss, phonenumber);
}
}
return false;
}

Unreadable output file, is this a fault?

Here is my code:
#include <stdio.h>
#include <iostream>
#include <conio.h>
char filename[100];
FILE *stream, *stream2;
char s[20];
struct date
{
int day, month, year;
};
struct employee
{
int ID;
char name[100];
date birthdate;
char address[20];
char rank[20];
int money;
};
void main()
{
errno_t err;
// Open for read (will fail if file "crt_fopen_s.c" does not exist)
// Open for write
err = fopen_s(&stream2, "C:/Users/Van/Desktop/LAALAL/fool.txt", "w+");
if (err == 0)
{
employee nv;
std::cout << "\nInput information of an employee:\n";
std::cout << "\tInput ID : ";
std::cin >> nv.ID;
std::cin.sync();
std::cout << "\tInput name : ";
std::cin.clear();
gets_s(s);
gets_s(nv.name);
std::cout << "\tInput birthdate (Day Month Year ) : ";
std::cin >> nv.birthdate.day >> nv.birthdate.month >> nv.birthdate.year;
std::cout << "\tInput address: ";
std::cin.clear();
gets_s(s);
gets_s(nv.address);
std::cout << "\tInput rank : ";
std::cin.clear();
gets_s(s);
gets_s(nv.rank);
std::cout << "\tMoney : ";
std::cin >> nv.money;
std::cin.sync();
std::fwrite(&nv, sizeof(nv), 1, stream2);
std::fclose(stream2);
}
}
Well I don't have any problem with the code, but when I input my information, I cant read the output in the file. Here is the picture of my output:
What is my problem?
Thanks in advance for your time!
You are using fwrite() function, which writes data to files as binary, not as text (ASCII). You should be using std::ofstream class from <fstream> (instead of FILE), together with << operator.
More info here:
http://www.cplusplus.com/doc/tutorial/files/
Example code:
#include <iostream>
#include <fstream>
using namespace std;
struct some_struct{
int some_int;
char some_char;
};
int main () {
struct some_struct x;
x.some_int = 123123;
x.some_char = 'x';
//This is how you open the file.
ofstream myfile;
myfile.open ("example.txt");
//This is is how you write to it.
myfile << "Integer: " << x.some_int << " Char: " << x.some_char;
//This is how you close it.
myfile.close();
return 0;
}
Output inside the file example.txt:
Integer: 123123 Char: x
You can use fstream library to programming by operators like << or >>
#include <iostream>
#include <fstream>
using namespace std;
struct date
{
int day, month, year;
};
struct employee
{
int ID;
char name[100];
date birthdate;
char address[20];
char rank[20];
int money;
};
int main()
{
char ch;
ofstream file("fool.txt");
if (!file)
{
cout << ""Cannot open file, press any key to continue ...";
cin.get();
exit(0);
}
employee nv;
cout << "\nInput information of an employee:\n";
cout << "\tInput ID : ";
cin >> nv.ID;
cin.ignore();
cout << "\tInput name : ";
gets_s(nv.name);
cout << "\tInput birthdate (Day Month Year) : ";
cin >> nv.birthdate.day >> nv.birthdate.month >> nv.birthdate.year;
cin.ignore();
cout << "\tInput address: ";
gets_s(nv.address);
cout << "\tInput rank: ";
gets_s(nv.rank);
cout << "\tMoney: ";
cin >> nv.money;
cin.ignore();
file << nv.ID << ' ' << nv.name << ' ' << nv.birthdate.day
<< ' ' << nv.birthdate.month << ' ' << nv.birthdate.year
<< ' ' << nv.address << ' ' << nv.rank << ' ' << nv.money << ' ';
file.close();
cout << "\nOutput From File : \n";
ifstream file2("fool.txt");
file2.get(ch);
while (!file2.eof())
{
cout.put(ch);
file2.get(ch);
}
file2.close();
cout << "\nOutput Completed";
cin.get();
}
and pay attention to these hints :
Declare the usage of std namespace in your code first, so you can remove the std:: clauses.
using namespace std;
cin.clear() and cin.sync() are not necessary, just use cin.ignore() after input a integer type and before input a char type
cin >> nv.ID;
cin.ignore();
gets_s(nv.name);
see this post to understand it better
you are collecting char s[20]; from input in some lines. Why?? remove it
in this example and using operators for file programming ( << ) you should add a space character after writing each data to file for separate data
file << nv.ID << ' ' << nv.name
standard functions for input or print char type are gets() and puts(), but you use gets_s() that I think it's because of secure warning, you can disable this error, In this case, if you want your code to use another compiler it will not be a problem. You can only comment one line instead of change many lines
#pragma warning(disable: 4996)

extract cin data to a variable that fits

In case of an invalid input, I want extract the invalid input from cin and store it in a variable that fits. How can I do that?
#include<iostream>
using namespace std;
int main(){
int number;
cout << "Enter a number: " << endl;
cin >> number;
if(cin.fail()){
cout << "Error!" << endl;
//HOW CAN I STORE THE INVALID INPUT WHICH IS STORED IN cin INTO A STRING?
}
return 0;
}
When you detect that failbit is set, reset it, and use std::getline to read entire line of invalid input into std::string from std::cin:
#include <iostream>
#include <string>
int main()
{
int number;
while(true)
{
std::cout << "Enter a number (0 to exit): " << std::endl;
std::cin >> number;
if(std::cin.fail())
{
std::string error_data;
std::cin.clear(std::cin.rdstate() & ~std::ios::failbit);
std::getline(std::cin, error_data);
std::cout << "You didn't enter a number - you've entered: " << error_data << std::endl;
}
else
{
std::cout << "Number is: " << number << std::endl;
if(number == 0)
{
break;
}
}
}
return 0;
}

Shopping cart assignment, concepts on getline()

I've been working on a shopping cart assignment lately and couldn't understand why would this code below not work.
I have to write a code that will output name, cost and quantity of items, for three items without using arrays.
At the end of the maximum of three items I have to display out the total cost of the items. Currently I'm stuck because after I add in a second item, it appears that the program does not ask for the first input (Item name). Here's the code:
#include <iostream>
int main() {
int total;
std::cout << "Item name:";
std::string itemName;
std::getline(std::cin,itemName);
std::cout << "Cost(in cents):";
int cost;
std::cin >> cost;
std::cout << "Quantity:";
int quantity;
std::cin >> quantity;
std::cout << "Do you want to add more items? (Y/N)";
char option;
std::cin >> option;
if (option == 'y') {
std::cout << "Item name:";
std::string itemName2;
std::getline(std::cin,itemName2);
std::cout << "Cost(in cents):";
int cost2;
std::cin >> cost2;
std::cout << "Quantity:";
int quantity2;
std::cin >> quantity2;
std::cout << "Do you want to add more items? (Y/N)";
char option2;
std::cin >> option2;
if (option2 == 'y') {
std::cout << "Item name:";
std::string itemName3;
std::getline(std::cin,itemName3);
std::cout << "Cost(in cents):";
int cost3;
std::cin >> cost3;
std::cout << "Quantity:";
int quantity3;
std::cin >> quantity3;
total = cost*quantity + cost2*quantity2 + cost3*quantity3;
std::cout << "Total value:" << total;
}
else {
total = cost*quantity + cost2*quantity2;
std::cout << "Total value:" << total;
}
}
else {
total = cost*quantity;
std::cout << "Total value:" << total;
}
return 0;
}
After I input 'y' after every item input, the code would somehow skip my input for itemName and output the 'Cost(in cents):' together with 'Item name:' in the same line.
I do think that it's got something to do with the getline() function, but I do not know exactly what. Any help is greatly appreciated.
Frsitly, you are using getline and haven't included <string> header file.
2ndly, you may be facing issue because of cin buffer. you should use cin.ignore() after taking input for option for extracting the characters and discarding or other option may be clearing cin buffer.
cin.ignore() will work for ignoring 1 character in stream.
you can try std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
This will extract as many characters till ``\n''
I tried following code on VS2012, and it worked properly.
#include <iostream>
#include <string>
int main() {
int total;
std::cout << "Item name:";
std::string itemName;
std::getline(std::cin,itemName);
std::cout << "Cost(in cents):";
int cost;
std::cin >> cost;
std::cout << "Quantity:";
int quantity;
std::cin >> quantity;
std::cout << "Do you want to add more items? (Y/N)";
char option;
std::cin >> option;
std::cin.ignore();
if (option == 'y') {
std::cout << "Item name:";
std::string itemName2;
std::getline(std::cin,itemName2);
std::cout << "Cost(in cents):";
int cost2;
std::cin >> cost2;
std::cout << "Quantity:";
int quantity2;
std::cin >> quantity2;
std::cout << "Do you want to add more items? (Y/N)";
char option2;
std::cin >> option2;
std::cin.ignore();
if (option2 == 'y') {
std::cout << "Item name:";
std::string itemName3;
std::getline(std::cin,itemName3);
std::cout << "Cost(in cents):";
int cost3;
std::cin >> cost3;
std::cout << "Quantity:";
int quantity3;
std::cin >> quantity3;
total = cost*quantity + cost2*quantity2 + cost3*quantity3;
std::cout << "Total value:" << total;
}
else {
total = cost*quantity + cost2*quantity2;
std::cout << "Total value:" << total;
}
}
else {
total = cost*quantity;
std::cout << "Total value:" << total;
}
system("pause");
return 0;
}
For details on cin.ignore() see this link.
You should use
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
For remove \n, remained after inputting option.
you can do:
std:cin>>itemName
instead of doing:
std::getline(std::cin,itemName)
This would be the easiest approach for the strings without spaces!

Fstreams C++ has extra spaces on writing

I figured some stuff out, but I suck at fstreams, and this is just killing me, for BREED + DESC, they have a space between them and name, but when I remove them completely then I get no spaces and it works again. Could someone tell me what I'm doing wrong?
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
const int NAME_SIZE = 100;
const int BREED_SIZE = 100;
const int DESC_SIZE = 250;
const int REASON_SIZE = 250;
//creating the struct
struct animal
{
//members
char name[NAME_SIZE];
char breed[BREED_SIZE];
char desc[DESC_SIZE];
char reason[REASON_SIZE];
float age;
float weight;
int day;
int month;
int year;
float length;
};
class petAdoption
{
public:
petAdoption();
void enroll(animal newAnimal[], int & count);
void read(animal newAnimal[], int & count);
//void display(animal & newAnimal);
//void adopt(animal & newAnimal);
private:
};
petAdoption::petAdoption()
{
}
int main()
{
int count = 0;
animal * newAnimal = new animal[count];
petAdoption adopt;
adopt.read(newAnimal, count);
adopt.enroll(newAnimal, count);
delete[] newAnimal;
}
void petAdoption::read(animal newAnimal[], int & count)
{
int pets = 0;
ifstream read;
read.open("pets.txt");
if(!read)
{
cout << "Checking... File doesn't exist!" <<endl;
}
else
{
while(!read.eof())
{
read.getline(newAnimal[pets].name, NAME_SIZE, '\n');
read.ignore(100, '\n');
++pets;
}
count = pets + 1;
}
read.close();
for (int i = 0; i < pets; ++i){
read.open(newAnimal[i].name);
if( !read)
{
cout << "Checking... File doesn't exist!" <<endl;
}
else{
while(!read.eof())
{
read.getline(newAnimal[i].name, NAME_SIZE, '\n');
read.getline(newAnimal[i].breed, BREED_SIZE, '\n');
read.getline(newAnimal[i].desc, DESC_SIZE, '\n');
read.getline(newAnimal[i].reason, REASON_SIZE, '\n');
read.ignore(100, '\n');
read >> newAnimal[i].age;
read >> newAnimal[i].weight;
read >> newAnimal[i].day;
read >> newAnimal[i].month;
read >> newAnimal[i].year;
read >> newAnimal[i].length;
read.ignore(100, '\n');
}
}
read.close();
}
}
/*
ENROLL FUNCTION
*/
void petAdoption::enroll(animal newAnimal[], int & count)
{
//making a write variable
ofstream write;
//stores the name into the struct member
cout << "Please enter a name: ";
cin.get(newAnimal[count].name, NAME_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter a breed: ";
cin.get(newAnimal[count].breed, BREED_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter a desc: ";
cin.get(newAnimal[count].desc, DESC_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter a reason (EG: eats people): ";
cin.get(newAnimal[count].reason, REASON_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter an age (EG: 5): ";
cin >> newAnimal[count].age;
cin.ignore(100, '\n');
cout << "Please enter a weight (in LBS): ";
cin >> newAnimal[count].weight;
cin.ignore(100, '\n');
cout << "Please enter a day (EG: 2): ";
cin >> newAnimal[count].day;
cout << "Please enter a month (EG: 11): ";
cin >> newAnimal[count].month;
cout << "Please enter a year (EG: 2002): ";
cin >> newAnimal[count].year;
cout << "How long has the pet been in a shelter? (in months): ";
cin >> newAnimal[count].length;
//error
if(!write)
{
cout << "Invalid File" << endl;
}
else{
write.open(newAnimal[count].name, ios::app);
write << newAnimal[count].name << '\n'
<< newAnimal[count].breed << '\n'
<< newAnimal[count].desc << '\n'
<< newAnimal[count].reason << '\n'
<< newAnimal[count].age << '\n'
<< newAnimal[count].weight << '\n'
<< newAnimal[count].day << '\n'
<< newAnimal[count].month << '\n'
<< newAnimal[count].year << '\n'
<< newAnimal[count].length << '\n';
write.close();
}
if(!write)
{
cout << "Invalid File";
}
else {
write.open("pets.txt", ios::app);
write << newAnimal[count].name << '\n';
write.close();
}
}
As people mention (in response to an earlier version of this question already) you shall not use eof() to control your loop . Furthermore you shall test that you successfully received your input after you [attempted] to read it.
The problem with extra newlines at the end if a line is due to your use of get() rather than getline(): the former retains the stop character while the latter does not. You should als consider using std::string together with std::getline(): it reads arbitrary length strings.