I want to input a string (with spaces in between) and i am using cin.getline(). But i am getting a run time error (loop executes infinitely).
class account
{
int acno;
int password;
char name[50];
char address[100];
char sex;
string phonenumber;
public:
void create_account(); //function to get data from user
void show_account() const; //function to show data on screen
void modify(); //function to add new data
void withdraw(int,int); //function to accept amount and subtract from balance amount
void donate(int,int); //function to accept amount and add to balance amount
void report() const; //function to show data in tabular format
int retacno() const; //function to return account number
int retpassword() const; //function to return password
}; // class definition
this is my function for inputting the data for a class record.
void account::create_account()
{
cout<<"\nEnter The account No. :";
cin>>acno;
cout<<"\n\nEnter The Name of The account Holder : ";
cin.getline(name,49);
cin.ignore();
cout<<"\n\nEnter your Password (Max 8 characters) : ";
cin>>password;
cin.ignore();
cout<<"\n\nEnter your Address : ";
cin.getline(address,99);
cin.ignore();
cout<<"\nEnter your Contact Number: ";
cin>>phonenumber;
cin.ignore();
cout<<"\nSex (Enter M for male and F for female): ";
cin>>sex;
cout<<"\n\n\nAccount Created..\n\n";
}
When I execute this I get a run time error if I introduce spaces in between string entries
and it skips the string input if I don't use cin.ignore() function.
Use the free-standing std::getline function, not the member function. The former operates on a std::string, so you don't have to mess around with a raw pointer.
Related
I have a class wallet which has info like name,pin,amount etc. I use function create() to create new users and write it to a file wallet.txt. This all process is fine. Problem arises when I transfer amount from one to other. Using function pay(). Here s,s1,s2 are objects of class wallet. File is opened in read mode and sender's info and receiver info is searched and stored in s1 and s2. Then fin is closed and fout is opened in write mode and things are written into file.
void pay()
{
char f1='n',f2='n';
int pos1,pos2;
int ycode;
float amount;
cout<<"\nenter your pin: ";
cin>>pin;
cout<<"\nenter the code of the receiver: ";
cin>>ycode;
ifstream fin("wallet.txt",ios::in);
while(fin.read((char*)&s,sizeof(s)))
{
if(ycode==s.getcode())
{
pos1=fin.tellg();
f1='f';
}
if(pin==s.getpin())
{
pos2=fin.tellg();
f2='f';
}
};
if(f1=='f' && f2=='f')
{ cout<<"Enter the amount to be transferred: ";
cin>>amount;
fin.seekg(pos1-sizeof(s));
fin.read((char*)&s1,sizeof(s));
s1.add(amount); //function of class wallet::add(float amount){balance+=amount}
fin.seekg(pos2-sizeof(s));
fin.read((char*)&s2,sizeof(s));
s2.sub(amount); //function of class wallet similar to add()
fin.close();
ofstream fout("wallet.txt",ios::ate);
fout.seekp(pos1-sizeof(s));
fout.write((char*)&s1,sizeof(s1));
s1.display();
fout.seekp(pos2-sizeof(s));
fout.write((char*)&s2,sizeof(s2));
s2.display();
fout.close();
}
else
cout<<"\nInvalid E-code or E-pin";
}
My file content content for receiver become
Name: [empty]
balance: [amount]
pin: 0
code: 0
and receiver
Name: [empty]
balance: -[amount]
pin: 0
so basically amount became 0 and then transfer occurs. WHY?
code: 0
class wallet{
int ecode;
int epin;
float balance;
char name[23];
public:
void create(); //function to open new E wallet
void add(float); //function to add money in wallet
void sub(float);//function to withdraw money from wallet
int getpin(); //function to return pin
int getcode(); //function to return code
void show(); //function to show details
void display(); //function to display current balance
}s,s1,s2 ; //class ends here
void wallet::display()
{
cout<<"\n The current balance of "<<name<<" is: "<<balance;
}
Also I tried debugging by calling the below function in every line of pay(), and found that problem occurred after first display().
void viewall()
{
ifstream fin("wallet.txt",ios::in);
while(fin.read((char*)&s,sizeof(s)))
{
s.show();
cout<<endl;
};
fin.close();
}
This question already has answers here:
getline() does not work if used after some inputs [duplicate]
(3 answers)
Closed 1 year ago.
In the following code, I have made two classes, the second class is inherited from the first one. However when I call the getdata function. it skips input, I have tried using cin.ingnore() and also cin>>ws, but I am still getting the same errors. It runs properly till " Enter the Last name" but after that, it just prints all the other things without taking the input.
#include <iostream>
#include <stdlib.h>
#include <time.h>
using namespace std;
class RegistrationModule{
protected:
string Firstname;
string Lastname;
double cnic;
double contact;
string address;
static double challanno;
public:
RegistrationModule(){
Firstname = "";
Lastname = "";
cnic=0;
address = "";
contact=0;
challanno++;
}
};
double RegistrationModule::challanno=105487;
class monthlyentry : public RegistrationModule{
public:
void getdata(){
cout<<"Enter First Name"<<endl;
getline(cin,Firstname);
cin.ignore();
cout<<"Enter Last Name"<<endl;
getline(cin,Lastname);
cin.ignore();
cout<<"Enter your CNIC: "<<endl;
cin>>cnic;
cin.ignore();
cout<<"Enter your Address: "<<endl;
getline(cin,address);
cout<<"Enter your contact number: "<<endl;
cin>>contact;
cout<<"Your Challan Number is: "<<challanno<<endl;
}
};
int main(){
int size;
monthlyentry a;
a.getdata();
}
You cannot just slap ignore() randomly and expect things to work. By default, ignore() will remove 1 character. If there is no character there, it will set eof() bit and your stream cannot read anything more until you clear() eof flag from it.
Only use ignore() when there is a leftover end of line (like after formatted extraction).
void getdata(){
cout<<"Enter First Name"<<endl;
getline(cin,Firstname);
cout<<"Enter Last Name"<<endl;
getline(cin,Lastname);
cout<<"Enter your CNIC: "<<endl;
cin>>cnic;
cin.ignore();
cout<<"Enter your Address: "<<endl;
getline(cin,address);
cout<<"Enter your contact number: "<<endl;
cin>>contact;
cin.ignore(); // might want to clear up before next extractions
cout<<"Your Challan Number is: "<<challanno<<endl;
}
To use std::ws, you would need to use directly in getline calls
std::getline(std::cin >> std::ws, Firstname);
This question already has an answer here:
How to make cin work after using getline?
(1 answer)
Closed 3 years ago.
This program is a small hospital management program.
It works with C++ and uses binary files and classes.
it is a simple prog that taken the input of patients details and saves in a binary file, and displays the patients details by searching regno.
The code does not run beyond : cin>>A1.PI.age; and starts printing endless loop of something.
PLEASE REPLY ME ON WHERE HAVE I GONE WRONG
here is the code:
#include<iostream.h>
#include<conio.h>
#include<fstream.h>
#include<string.h>
#include<stdlib.h>
class all
{ private:
struct address
{ int house;
char street[30];
char city[30];};
struct patient_info
{ char name[40];
address AD1;
int age;
int maritalstatus;
int regno;
char bldgrp[3];
char sex;
}PI;
int task;
protected:
void firstpinfo();
void showpinfo();
void enterpinfo();
public:
void tasks();
char ch;
int serial;
}A1;
class date :public all
{ private :
int day;
int month;
int year;
public:
void enterdate()
{cout<<"enter day of date";
cin>>day;
cout<<"enter month";
cin>>month;
cout<<"enter year";
cin>>year;
}
void showdate()
{ cout<<day<<"/"<<month<<"/"<<year;}
}D1;
//global variables
int count,attempt;
void main()
{ count=0;
cout<<" HOSPITAL MANAGEMENT SOFTWARE
";
D1.enterdate();
A1.tasks();
getch();
while(count==0)
{ A1.tasks();
cout<<"press 0 to continue and 1 to exit";
cin>> count;
}
getch();
}
void all::tasks()
{ attempt=0;
D1.showdate();
cout<<"select task"<<endl
<<"1.show patient details"<<endl
<<"2.enter details of a patient"<<endl
<<"3.exit prog"<<endl;
cin>>task;
switch(task)
{
case 1: {cout<<"enter regno to display"<<endl;
int search;
cin>>search;
fstream fon;
fon.open("hospital.dat",ios::in|ios::binary);
if(!fon)
{cout<<"error in opening"<<endl;
getch();
exit(0);
}
else
{fon.read((char*)&A1,sizeof(A1));
if(A1.PI.regno==search)
{cout<<"showing details";
A1.showpinfo();}
else
{cout<<"regno not found";}
fon.close();
}
break;}
case 2: {cout<<"adding a new patient";
A1.enterpinfo();
fstream fan;
fan.open("hospital.dat",ios::in|ios::binary);
if(fan)
{fan.write((char*)&A1,sizeof(A1));}
fan.close();
break;}
case 3: { cout<<"exiting...press any key";
getch();
exit(0);
break;
}
default: {cout<<"error... press anykey to try again";
getch();
A1.tasks();
};
}}//END OF TASKS
void all::showpinfo()
{cout<<"patient regno\n"<<A1.PI.regno<<endl;
cout<<"patient name\n"<<A1.PI.name<<endl;
cout<<"address of patient\n"<<A1.PI.AD1.house<<" "<< PI.AD1.street<<" "<<PI.AD1.city<<endl;
cout<<"blood group"<<A1.PI.bldgrp<<endl;
cout<<"sex"<<A1.PI.sex<<endl;
cout<<"data extracted";
}
void all:: enterpinfo()
{
cout<<"enter unique registration number";
cin>>PI.regno;
cout<<"enter patient name"<<endl;
cin.getline(A1.PI.name,50);
cout<<"enter address( house, street, city)"<<endl;
cin>>A1.PI.AD1.house;
cin.getline(A1.PI.AD1.street,30);
cin.getline(A1.PI.AD1.city,30);
cout<<"enter age in years"<<endl;
cin>>A1.PI.age;
cout<<"enter 1 for married and 0 for otherwise"<<endl;
cin>>A1.PI.maritalstatus;
cout<<"enter blood group"<<endl;
cin>>A1.PI.bldgrp;
cout<<"enter M for male and F for female";
cin>>A1.PI.sex;
}
why this happens :
This happens because you have mixed cin and cin.getline.
when you enter a value using cin, cin not only captures the value, it also captures the newline. So when we enter 2, cin actually gets the string ā2\nā. It then extracts the 2 to variable, leaving the newline stuck in the input stream. Then, when getline() goes to read the input, it sees ā\nā is already in the stream, and figures we must have entered an empty string! Definitely not what was intended.
old solution :
A good rule of thumb is that after reading a value with cin, remove the newline from the stream. This can be done using the following :
std::cin.ignore(32767, '\n'); // ignore up to 32767 characters until a \n is removed
A better solution :
use this whenever you use std::getline() to read strings
std::getline(std::cin >> std::ws, input); // ignore any leading whitespace characters
std::ws is a input manipulator which tell std::getline() to ignore any leading whitespace characters
source : learncpp website
goto section (Use std::getline() to input text)
hope this is helpful
#include<iostream>
#include<fstream>
#include<string>
#include<cstdlib>
don't use .h extension
we don't think we need #include<conio.h> anymore
and isn't simpler
getline(cin, A1.PI.name) than cin.getline(A1.PI.name,50)
then resize its max size
A1.PI.name.resize(50);
I'm having odd behavior when creating and using a class.
I create multiple instances of that class, sequentially - and then I create a few temp variables to prompt the user to enter some data, then i use basic mututaor functions and pass the data to the parts of the object. I do this for the first item, then the second, etc.
What happens when the declarations of those personalData elements are sequential then for some reason the cin/getline statements skip over some and i can't enter all the data correctly. When i spread them out between statements have one object created then the input from the user then updates, then the next object it works better but still not in 100% of the cases. Lastly i found that creating different variables for inputting data - my temp variables also resolves the problem but that seems strange to have to create a dozen variables when i should be able to input data/update existing ones?
class personalData
{
private:
string name;
string address;
int phone;
int age;
public:
void setname(string);
void setadress(string);
void setphone(int);
void setage(int);
string getname()const;
string getadress()const;
int getage()const;
int getphone()const;
};
void personalData::setname(string n)
{ name=n; }
void personalData::setadress(string a)
{ address=a; }
void personalData::setphone(int p)
{ phone=p;}
void personalData::setage(int ag)
{age=ag;}
string personalData::getname()const
{return name;}
string personalData::getadress()const
{return address;}
int personalData::getage()const
{return age;}
int personalData ::getphone()const
{return phone;}
int main()
{
personalData my;
personalData friendd;
personalData family;
string n;
string a;
int p;
int g;
cout<<"enter your name";
getline(cin,n);
cout<<"enter your address:";
getline(cin,a);
cout<<"enter your phone:";
cin>>p;
cout<<"enter your age";
cin>>g;
my.setname(n);
my.setadress(a);
my.setphone(p);
my.setage(g);
cout<<"enter your friend's name";
getline(cin,n);
cout<<"enter your friend's address:";
getline(cin,a);
cout<<"enter your friend's phone:";
cin>>p;
cout<<"enter your friend's age";
cin>>g;
friendd.setname(n);
friendd.setadress(a);
friendd.setphone(p);
friendd.setage(g);
cout<<"enter your family member's name";
getline(cin,n);
cout<<"enter your family member's address:";
getline(cin,a);
cout<<"enter your family member's phone:";
cin>>p;
cout<<"enter your family member's age";
cin>>g;
family.setname(n);
family.setadress(a);
family.setphone(p);
family.setage(g);
cout<<"my name"<<my.getname()<<endl;
cout<<"my address"<<my.getadress()<<endl;
cout<<"my phone"<<my.getphone()<<endl;
cout<<"my age"<<my.getage()<<endl;
// more cout statements with objects.getData ...
return 0;
}
Sorry for the long piece of code, I'm stuck and can't figure out what the issues are.
Thanks.
I wrote this code to obtain name. telephone and address of a person and then i input these into class object variables:
#include<iostream>
#include<cstdlib>
#include<fstream>
#include<string>
using namespace std;
class contact{
public:
string name;//ALL CLASS VARIABLES ARE PUBLIC
unsigned int phonenumber;
string address;
contact(){//Constructor
name= "Noname";
phonenumber= 0;
address= "Noaddress";
}
/*void input_contact_name(string s){//function to take contact name
name=s;
}
void input_contact_number(int x){//function to take contact number
phonenumber=x;
}
void input_contact_address(string add){//function to take contact address
address=add;
}*/
};
int main(){
contact *d;
d= new contact[200];
string name,add;
int choice;//Variable for switch statement
unsigned int phno;
static int i=0;//i is declared as a static int variable
bool flag=false;
cout<<"\tWelcome to the phone Directory\n";//Welcome Message
cout<<"Select :\n1.Add New Contact\n2.Update Existing Contact\n3.Delete an Existing Entry\n4.Display All Contacts\n5.Search for a contact\n6.Exit PhoneBook\n\n\n";//Display all options
cin>>choice;//Input Choice from user
while(!flag){//While Loop Starts
switch(choice){//Switch Loop Starts
case 1:
cout<<"\nEnter The Name\n";
cin>>name;
d[i].name=name;
cout<<"\nEnter the Phone Number\n";
cin>>phno;
d[i].phonenumber=phno;
cout<<"\nEnter the address\n";
cin>>add;
d[i].address=add;
i++;
flag=true;
}
}
return 0;
}
However If I enter the name separated with its surname, the code bypasses the next cins and exits. Can some one help me out why this happens?
Same happens when I enter 10 digit cell no.
Thanks in advance
Use std::getline() instead of operator>> to extract a std::string containing whitespace.