I am here including a simple program that written in C++ where I am trying to use a parametrized constructor. My idea is to instantiate the class dynamically and capture the required task.
But whenever I run the program and enter the task 1 it simply prints the two lines (i.e. Enter Name.Enter Tel.No.). It is actually supposed to print "Enter Name." then input the name, And then again print "Enter Tel.No.".
How can I fix the issue? I have to use parametrized constructor dynamically while creating an object.
#include <iostream>
#include <conio.h>
#include <fstream>
#include <string>
using namespace std;
class myClass
{
string fullname,telephone;
public:
myClass(int taskType = 2)
{
if(taskType==1)
{
add_record();
}
else if(taskType==2)
{
//view_records();
}
else if(taskType==3)
{
//delete_record();
}else{
// custom_error();
}
}
void add_record()
{
cout << "Enter Name.\n";
getline(cin, fullname);
cout << "Enter Tel. No.\n";
getline(cin, telephone);
}
};
main (){
int myTask;
cout << "Enter a Task-Type. \n"
<< "1 = Add Record,"
<< "2 = View Records,"
<< "3 = Delete a Record\n\n";
cin >> myTask;
myClass myObject(myTask);
getch();
}
You are using cin >> myTask to read the first input. As you press enter to give the 1, selecting "Add Record", that 1 will be read from the buffer, but your newline will still be in the input buffer. Thus, the first getline will only read this off the buffer, producing an empty input for the line getline(cin, fullname);
The reason is that the first newline after the task type is not consumed by
cin >> myTask
so the fullname reading will only read an empty line and the "enter Tel.No" thing will be printed directly.
Insert a getline call after the cin >> myTask to fix this problem.
Also see this question.
This probably has nothing to do with your constructor, but rather with the mixing of cin >> and getline. Add a getline to a garbage variable after cin >> myTask and it should work.
Related
I'm new to C++ programming, and I've come upon a roadblock. Here's my code:
#include <iostream>
using namespace std;
int main(){
int sum = 0, a;
cout << "enter first set of numbers:";
while(cin >> a) sum += a;
cout << "first sum = " << sum;
cin.clear();
cin.ignore( numeric_limits<streamsize>::max(), '\n');
sum = 0;
cout << "enter second set of numbers:";
while(cin >> a) sum += a;
cout << "second sum = " << sum;
}
I'm trying to sum two sets of numbers that I input at the command line. The problem is that when I hit ctrl-d to terminate my first set of numbers, it skips the second set of cin's. Most of the pages I find elsewhere on the internet tell me to use cin.clear and cin.ignore. I've tried that and it still doesn't work. This page question concerning cin.clear() even seems to have the same problems. However, the fixes they suggest don't work for me.
Does this code above work for anyone else?
When you use Ctrl-D you terminate the input stream: there is no further character coming from std::cin. Even clearing the stream doesn't help: you have told the stream it is at its end. You can't reopen it. However, clear()ing the stream and using ignore() is the solution to your problem!
You need a different indicator that one set of values is done. The easiest is to use a non-digit character or string: trying to read something which isn't an int will cause the stream to go into failure mode [without closing the stream]. That is, you read until the conversion fails, clear() the stream, and ignore() everything up to the end of the line.
Your code should already do that: instead of using Ctrl-D just enter, e.g., x.
//Use stringstream ^^ for multiple user input
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
int main (void)
{
string mystr;
float price = 0;
int quantity = 0;
cout << "Enter price: ";
getline (cin, mystr);
stringstream(mystr) >> price;
cout << "Enter quantity:";
getline (cin, mystr);
stringstream(mystr) >> quantity;
cout << "Total price: " << price*quantity << endl;
return 0;
}
You can use Ctrl-D, you just need to have your loop in another thread. So Ctrl-D, kills the thread, then returns to your main function, then you can start another thread.
It'd not the best solution, but it can work, http://codebase.eu/tutorial/posix-threads-c/
Please, is there a way I can wait for a single ENTER key press in all of the below cases? It works fine except when the std::getline() is used, which consumes the \n, and the ENTER needs to be pressed twice.
The code below works fine:
#include <iostream>
#include <limits>
using std::cout;
using std::cin;
using std::string;
void waitForENTERKeyPress();
int main ()
{
char c;
string s;
cout << "Enter c:"; cin >> c;
waitForENTERKeyPress();
cout << "Enter c:"; c = cin.get();
waitForENTERKeyPress();
cout << "Enter s:"; cin >> s;
waitForENTERKeyPress();
cout << "Enter s:"; std::getline(cin, s);
waitForENTERKeyPress();
return 0;
}
void waitForENTERKeyPress()
{
// Does not work with std::getline(...)
cin.ignore( std::numeric_limits<std::streamsize>::max(), '\n');
cout << "Press an ENTER to continue...\n";
cin.get();
}
====[UPDATE]============================================
Let me rephrase what I am looking for: The way how to make the waitForENTERKeyPress() function working in both cases – with \n in the buffer, when cin operator >> or cin.get() is used and also in cases the std::getline() is used.
From what I understand it is not possible as there is not a way how to detect if the \n is still in the buffer or not.
I have tried to use cin.rdbuf()->in_avail(), but it always returns 0.
When I am trying to store more than one word in a string variable, it only outputs one word when I tell the program to print it. This is an example:
#include <iostream>
using namespace std;
string i;
int main() {
cout << "Input more than one word." << endl;
//in this case the user will input whats up//
cin >> i;
cout << i << endl;
//the program outputs 'whats'//
}
Instead of using cin >> i, use getline(cin, i).
The difference is that, with getline() you get all the words in a line, whereas with operator>> you get only one word at a time.
Replace that:
cin >> i;
for:
getline(cin, i);
and it will work :)
This question already has answers here:
Why does std::getline() skip input after a formatted extraction?
(5 answers)
Closed 3 years ago.
Is there a reason why if in my program I am asking the user for input, and I do:
int number;
string str;
int accountNumber;
cout << "Enter number:";
cin >> number;
cout << "Enter name:";
getline(cin, str);
cout << "Enter account number:";
cin >> accountNumber;
Why after inputting the first number, it outputs "Enter Name", followed immediately by "Enter Account Number" before I even get to input my "str" for the getline(cin, str) line? Thanks!
The getline(cin, str); reads the newline that comes after the number read previously, and immediately returns with this "line". To avoid this you can skip whitespace with std::ws before reading the name:
cout << "Enter number:";
cin >> number;
cout << "Enter name:";
ws(cin);
getline(cin, str);
...
Note that this also skips leading whitespace after the newline, so str will not start with spaces, even if the user did input them. But in this case that's probably a feature, not a bug...
Try
cout << "Enter name:";
cin.ignore();
getline(cin, str);
cin >> number
only grabs the numbers from the buffer, it leaves the "enter" in the buffer, which is then immediately grabbed up by the getline and interpreted as an empty string (or string with just the new line, i forget).
It looks like you want line based reading. For this you probably want to use getline consistently and then parse each line if you need to parse a number from then read line. It makes the input reading more consistent.
This way you don't have to manually scan for the end of each line to guarantee that the next read operation starts on a fresh line.
It also makes adding error handling for repeating input requests simpler.
e.g.
#include <string>
#include <iostream>
#include <istream>
#include <ostream>
#include <sstream>
int parse_integer(const std::string& input)
{
std::istringstream iss(input);
int result;
if (!(iss >> result))
{
// error - throw something?
}
return result;
}
int main()
{
int number;
std::string str;
int accountNumber;
std::string inputline;
std::cout << "Enter number: ";
if (!std::getline(std::cin, inputline))
{
// error - throw something?
}
number = parse_integer(inputline);
std::cout << "Enter name:";
if (!std::getline(std::cin, inputline))
{
// error - throw something?
}
str = inputline;
std::cout << "Enter account number:";
if (!std::getline(std::cin, inputline))
{
// error - throw something?
}
accountNumber = parse_integer(inputline);
return 0;
}
cin >> number // eat the numeric characters
getline(cin, str) // eat the remaining newline
I think the problem is that cin >> passes on the newline character (\n). The getline() assumes the newline character is whitespace and passes it on. Someone posted a solution you can use.
You can use a dummy getline(cin, dummy); or the real thing cin.ignore(100,'\n');
Don't use getline(): it's a bad thing for memory allocation. Use fgets(). See fgets reference.
I'm trying to read multiple Strings and ints from the user. I want to take pairs of Name and Age and keep doing it until the user types in "done". But my do-while crashes early on, and i can't figure out why?
int number;
string name;
do
{
cout << "Your name: " ;
getline(cin, name);
cout <<name<< " age: " ;
cin >> number;
}
while (name!="done");
Edit: Also after entering "done", i have to enter "done" also on age, why is that?
I tried to run your program in VS 2010, and even when I entered a valid number, the program would, to my surprise skip reading the next name.
It seems to me that cin >> number doesn't swallow the '\n' I naturally entered after the number.
I attempted adding a call to getchar() after each cin >> number and the program suprisingly started working as expected.
So the conclusion is, that you should clean()/ignore() after cin >> number even after the number entered was OK, or resort to using getline() (and then parsing) for reading numbers.
If you want not to input "done"'s age then you have to break out of the loop immediately after it's entered. My final code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
int number;
string name;
while(true)
{
cout << "Your name: " ;
getline(cin, name);
if(name == "done")
break;
cout <<name<< " age: " ;
cin >> number;
cin.clear();
cin.ignore(std::numeric_limits<streamsize>::max(),'\n');
}
}
If someone enters an invalid age, i.e. something that isn't a number, you need to clear the flags of your cin, and also flush any remaining characters.
if( !(cin >> number )
{
cin.clear();
}
cin.ignore( std::numeric_limits<streamsize>::max() );
If it does read a number then you also need to ignore the newline after it.
Use the std namespace
This way
int number;
string name;
do
{
std::cout<<"Your name: " ;
std::cin>>name;
std::cout<<name<<" age: " ;
std::cin>>number;
}
while (name!="done");
Or this
using namspace std;
int number;
string name;
do
{
std::cout<<"Your name: " ;
std::cin>>name;
std::cout<<name<<" age: " ;
std::cin>>number;
}
while (name!="done");
#include <iostream>
#include <string>
int main ()
{
std::string name;
int age;
while (true)
{
std::cout << "Please enter your name: ";
std::cin >> name;
if ( "done" == name )
break;
std::cout << name << ", please enter your age: ";
std::cin >> age;
std::cout << name << ", you are " << age << " years old\n";
}
std::cout << "Bye.\n";
return 0;
}
Mixing use of getline() and >> can be problematic. Best to just avoid it if you can. You could also use getline() for both, and convert the int using a stringstream, or possibly atoi(), but I don't like that much.
Because you give it a string while it expect an int as age.
At the end of the first iterate, as you typed the Enter key to input the age, an extra newline was taken into the cin. So in the second iterate, the newline showed up as an empty line, causing the name to be set as an empty string. Then the program wanted an int as age. If you are not careful enough, you would input a string and cause the program crash.
One suggestion:
To replace:
getline(cin, name);
with:
do {
getline(cin, name);
} while (name.empty());