CPP infinit while-loop error when reading in struct data? - c++

I would like to use an infinite loop to read in Person struct (name, age, salary). I would like to break the loop when the user enters name as 'x'.
#include <iostream>
#include <vector>
using namespace std;
struct Person
{
char name[50];
int age;
float salary;
};
int main(int argc, const char * argv[]) {
Person p1;
vector <Person> p1_vec;
while (true) {
cout << "Enter Full name or simply 'x' to exit: ";
cin.get(p1.name, 50);
bool next_entry = strcmp(p1.name,"x");
if (!next_entry) {
break;
}
cout << "Enter age: ";
cin >> p1.age;
cout << "Enter salary: ";
cin >> p1.salary;
p1_vec.push_back(p1);
}
}

You need to ignore the new line character that you get after reading a salary input:
cin >> p1.salary;
doing:
cin >> p1.salary;
cin.ignore(1, '\n');
will make the code to stop here:
cin.get(p1.name, 50);
and wait for another user input!

cin state needs to be cleared after reading, try something like:
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
For example (depending on the amount of error tolerance you want)
while (true)
{
cout << "Enter Full name or simply 'x' to exit: ";
cin.get(p1.name, 50);
cin.clear();
auto equal = strcmp(p1.name, "x")==0;
if (equal)
{
break;
}
cout << "Enter age: ";
cin >> p1.age;
cin.clear();
cout << "Enter salary: ";
cin >> p1.salary;
p1_vec.push_back(p1);
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(), '\n');
}

cin.get(p1.name, 50) does not consume the \n, that remains in the input buffer after having entered a salary; so it skips the input and leaves the values blank.
Write cin >> p1.name and it should work properly.

After getting data from input buffer, you should clear it.
int main(int argc, const char * argv[]) {
Person p1;
vector <Person> p1_vec;
while (true) {
cout << "Enter Full name or simply 'x' to exit: ";
cin.get(p1.name, 50);
bool next_entry = strcmp(p1.name,"x");
if (!next_entry) {
break;
}
cout << "Enter age: ";
cin >> p1.age;
cout << "Enter salary: ";
cin >> p1.salary;
p1_vec.push_back(p1);
cin.clear();
cin.ignore();
}
}

Related

Undefined reference error along with exit status error when trying to call function in database management system

So I am trying to call a function which creates an assessment class object within the newStudent function. Ideallly the aim is for the newStudent function to run and after it reaches level selection it would call the respective makeAssess functions. Each of the makeAssess functions would then recursively call themselves until the total weighting of each level is 100 and then move onto the next makeAssess function. All the makeAssess functions were already defined at the start of the program.
Edit: Iam using CodeBlocks with a GNU GCC compiler. The two errors are "|undefined reference to `makeassessH()'|" and "|error: ld returned 1 exit status|"
MPE:
//Relevant libraries
#include <iostream>
#include <fstream>
using namespace std;
int option;
void newStudent();
void makeassessH();
void makeassessI();
void makeassessC();
class Student {
public:
int stuNum;
std::string stuName;
int startDate;
int endDate;
string progofStudy;
char level;
};
class Assessment{
public:
std::string title;
int weight;
double grade;
string deadline;
};
int main()
{
//The option page
while (option != 5) {
cout << "\nPlease choose an option\n"
"1. Add new students\n"
"2. Student Login\n"
"3. Staff Login\n"
"4. Admin View\n"
"5. Exit\n"
"Enter option: ";
cin >> option;
if (option == 1) {
newStudent();
} else if (option == 5)
return 0;
}
}
void newStudent() {
Student stu;
string studentName = stu.stuName;
cout << "Please enter in your student number: ";
cin >> stu.stuNum;
cout << "Please enter in your name: ";
cin.ignore();
getline (cin, studentName);
cout << "Please enter in your start date: ";
cin >> stu.startDate;
cout << "Please enter in your end date: ";
cin >> stu.endDate;
cout << "Please enter in your programme of study: ";
cin.ignore();
getline(cin, stu.progofStudy);
cout << "Please enter your level of study: ";
cin >> stu.level;
if(stu.level == toupper('h')){
makeassessH();
makeassessI();
makeassessC();
}else if (stu.level == toupper('i')){
makeassessI();
makeassessC();
}else if(stu.level == toupper('c')) {
makeassessC();
}
}
void makeassesH(){
Assessment assessmentH;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentH.title);
cout << "Assessment weighting: ";
cin >> assessmentH.weight;
cout << "Assessment grade: ";
cin >> assessmentH.grade;
cout << "Assessment deadline: ";
cin >> assessmentH.deadline;
}
void makeassessI(){
Assessment assessmentI;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentI.title);
cout << "Assessment weighting: ";
cin >> assessmentI.weight;
cout << "Assessment grade: ";
cin >> assessmentI.grade;
cout << "Assessment deadline: ";
cin >> assessmentI.deadline;
}
void makeassessC(){
Assessment assessmentC;
cout << "Assessment title: ";
cin.ignore();
getline (cin, assessmentC.title);
cout << "Assessment weighting: ";
cin >> assessmentC.weight;
cout << "Assessment grade: ";
cin >> assessmentC.grade;
cout << "Assessment deadline: ";
cin >> assessmentC.deadline;
int totalWeight = totalWeight + assessmentC.grade;
}
The error message is telling you (and us all now) that you have declared a function named
void makeassessH()
but you never defined it. You do have a function named
void makeassesH()
but that's not the same spelling.

While loop not breaking, using cin.ignore and cin.clear() to verify input

I'm trying to use a loop to verify that the input grade is an integer, but when I intentionally input a char, the program does nothing. It only starts a newline upon pressing enter.
void fillvector(vector<student>& parameter)
{
string newname;
int newgrade;
int number;
cout << "How many students are in your class: ";
cin >> number;
for (int i = 0; i < number; i++)
{
cout << endl << "Enter student name: ";
while (1)
{
cin >> newname;
cout << "Enter student grade: ";
cin >> newgrade;
if (cin.fail())
{
cout << endl << "Grade must be an integer value, try again.";
cin.clear();
cin.ignore(INT_MAX);
i--;
break;
}
else
{
student student(newname, newgrade);
parameter.push_back(student);
break;
}
}
}
cout << endl;
}
cin.ignore(INT_MAX);
This will make cin ignore any further characters you enter up to MAX_INT..
What you wanted is to ignore up-to the next newline:
cin.ignore(INT_MAX, '\n');
Besides, there is no point in making a while(1) loop that will break in all paths in the first iteration. You can remove that inner loop.

Checking for input type fails, C++

I have this code which is supposed to fool-proof the program from users entering something else but an integer. I wrote this code based on several sources online but for some reason it doesn't work.
int cost;
cin >> cost;
if (!(cin>>cost)) {
cout << "Enter a number: ";
cin >> cost;
cin.ignore(10000, '\n');
}
The prompt which is supposed to show up when you enter an incorrect type doesn't appear and the program terminates. I've tried moving around and adding cin.ignore() to other places, I've also tried if(cin.fail()) with no success.
do the following:
int cost;
cout << "Enter a number: ";
if(!(cin >> cost) {
cin.clear();
cin.ignore(10000, '\n');
}
Reason : You have a redundant cin statement.
you might do like #MatsPetersson and #40two mentioned above, but I would do that this way:
const int MAX_TRIES = 3;
int cost;
cout << "Enter a number: ";
for( int tries = 0; !(cin >> cost) && (tries < MAX_TRIES); ++tries ) {
cin.clear();
cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
cout << "This is not a number, try again: ";
}
Should work like this,
int cost;
while (!(cin >> cost)
{
cout << "Enter a number:";
cin.ignore(10000, '\n');
}

C++ FSTREAM & classes

Okay so when I started using classes to make functions, it gives me an error file is invalid, normally doesn't if I don't use classes. If you run it, enter in some info, and then run it again, normally it should read in the data correctly, it still reads it in, but it says there's an error. I don't really know what I'm doing wrong, any tips? Thanks!
#include <iostream>
#include <fstream>
#include <cstring>
#include <cctype>
using namespace std;
const int TEMP_SIZE = 10;
const int NAME_SIZE = 100;
const int BREED_SIZE = 100;
const int DESC_SIZE = 250;
const int REASON_SIZE = 250;
const int ID_SIZE = 50;
//creating the struct
struct animal
{
char name[NAME_SIZE];
char ID[ID_SIZE];
char breed[BREED_SIZE];
float age;
float weight;
char desc[DESC_SIZE];
char reason[REASON_SIZE];
int day;
int month;
int year;
float length;
};
struct adopted
{
char hostName[100];
char hostAddress[100];
int numPets;
};
class petAdoption
{
public:
petAdoption();
//~petAdoption();
void enroll(animal newAnimal[]);
void read(animal newAnimal[]);
private:
int count;
int numPets;
int * pets;
};
petAdoption::petAdoption()
{
count = 0;
pets = NULL;
numPets = 0;
}
void petAdoption::enroll(animal newAnimal[])
{
cout << "Please enter your pet's name: ";
cin.get(newAnimal[count].name, NAME_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter a unique ID for your pet (combinations of numbers EG: 432FD3): ";
cin.get(newAnimal[count].ID, ID_SIZE, '\n');
cin.ignore(100, '\n');
cout << "What type of breed is your pet?: ";
cin.get(newAnimal[count].breed, BREED_SIZE, '\n');
cin.ignore(100, '\n');
cout << "How old is your pet?: ";
cin >> newAnimal[count].age;
cin.ignore(100, '\n');
cout << "How much does your pet weigh? (in LBS): ";
cin >> newAnimal[count].weight;
cin.ignore(100, '\n');
cout << "Please describe your pet's personality!: ";
cin.get(newAnimal[count].desc, DESC_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please explain why the pet is being put up for adoption: ";
cin.get(newAnimal[count].reason, REASON_SIZE, '\n');
cin.ignore(100, '\n');
cout << "Please enter your pet's day of birth (1-31): ";
cin >> newAnimal[count].day;
cin.ignore(100, '\n');
cout << "Please enter your pet's month of birth (1-12): ";
cin >> newAnimal[count].month;
cin.ignore(100, '\n');
cout << "Please enter your pet's year of birth (1900-2012) : ";
cin >> newAnimal[count].year;
cin.ignore(100, '\n');
cout << "Please enter the length of time your pet has spent in a shelter (in months): ";
cin >> newAnimal[count].length;
cin.ignore(100, '\n');
/*** WRITES the pet ID into the list of pets***/
ofstream write;
write.open("pets.txt", ios::app);
write << newAnimal[count].name << '\n';
write.close();
/*** WRITES EACH PET INFO ****/
//this opens the file / creates a file if it's not made yet
//and it writes the pet's information
write.open(newAnimal[count].name, ios::app);
write << newAnimal[count].name << '\n'
<< newAnimal[count].ID << '\n'
<< newAnimal[count].breed << '\n'
<< newAnimal[count].age << '\n'
<< newAnimal[count].weight << '\n'
<< newAnimal[count].desc << '\n'
<< newAnimal[count].reason << '\n'
<< newAnimal[count].day << '\n'
<< newAnimal[count].month << '\n'
<< newAnimal[count].year << '\n'
<< newAnimal[count].length << '\n';
//this closes the file
write.close();
}
void petAdoption::read(animal newAnimal[])
{
ifstream read;
//open the file apps.txt
read.open("pets.txt");
//if apps.txt doesn't exist, then print out this error
if(!read)
{
cout << "pets.txt doesn't exist! This is your first time!" <<endl;
}
//else if it does exist, read in the names and store them back
//into the struct member name(s)
else
{
//while the document isn't empty
//read in each line
while(!read.eof())
{
read.getline(newAnimal[count].name, NAME_SIZE, '\n');
++count;
}
count = count-1;
}
//close the file
read.close();
for (int i = 0; i < count; ++i)
{
//open the file of the name of the app
read.open(newAnimal[count].name);
//if the file doesn't exist
//then we probably deleted it
//without removing it from the apps.txt
//but it prints out an error
if( !read)
{
cout << "invalid file!" <<endl;
}
//however if the file does exist,
//read in each line and store them back
//into the struct members
while(!read.eof())
{
read.getline(newAnimal[count].name, NAME_SIZE, '\n');
read.ignore(100, '\n');
read.getline(newAnimal[count].ID, ID_SIZE, '\n');
read.ignore(100, '\n');
read.getline(newAnimal[count].breed, BREED_SIZE, '\n');
read.ignore(100, '\n');
read >> newAnimal[count].age;
read.ignore(100, '\n');
read >> newAnimal[count].weight;
read.ignore(100, '\n');
read.getline(newAnimal[count].desc, DESC_SIZE, '\n');
read.ignore(100, '\n');
read.getline(newAnimal[count].reason, REASON_SIZE, '\n');
read.ignore(100, '\n');
read >> newAnimal[count].day;
read >> newAnimal[count].month;
read >> newAnimal[count].year;
read >> newAnimal[count].length;
read.ignore(100, '\n');
}
//close the file
read.close();
}
}
int main()
{
animal newAnimal[10];
petAdoption adopt;
adopt.read(newAnimal);
adopt.enroll(newAnimal);
}
I think I know what's going on. when you say read.open("pets.txt"); it should say read.open("pets.txt"),ios::app because then it so snot delete the data it already stores. Also go in to your file explorer and search pets.txt and read it to see what's going on. I hope I helped you.

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.