cin.get() issue with empty line - c++

When I run the following code and insert a new line (press enter) when prompted for
the golf structure, the second call to the function doesn't request input and finishes as if I've pressed enter again.
I've read up on : cin.get() , cin.clear() , cin.ignore(...) but nothing seems to help.
I'm pretty sure that it has nothing to do with multiple .cpp files and the header but I'm putting the code as is.
I'm using Visual Studio C++ 2010 - Express.
Thanks in advance for your help!
header file : golf.h
#ifndef GOLF_H
#define GOLF_H
const int Len = 40;
struct golf{
char fullname[Len];
int handicap;
};
int setgolf(golf & g );
void showgolf(const golf & g );
#endif
golf.cpp
#include "stdafx.h"
#include "golf.h"
#include <iostream>
#include <string>
using namespace std;
int setgolf(golf & g ){
cout << "Enter a name for the golf structure:" << endl;
if (cin.get(g.fullname,Len)) {
cin.get(); // deals with the '\n' incase the user inputs a valid string
return 1;
}
else{
return 0;
}
}
void showgolf(const golf & g ){
cout << "this golf structure contains the following information:" << endl;
cout << "name: " << g.fullname << endl ;
cout << "handicap: " << g.handicap << endl ;
}
main ()
#include "stdafx.h"
#include "golf.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
golf myGolf;
// check of int setgolf(golf & g );
int answ = setgolf(myGolf); //try to input empty string
showgolf(myGolf);
cout << "the number returned :" << answ << endl ;
answ = setgolf(myGolf); // normal string
showgolf(myGolf);
cout << "the number returned :" << answ << endl ;
return 0;
}

This problem happens when you just press enter in the first prompt. The input stream is marked as eof, an error condition flag (that's why it returns 0). The input stream then stops working.
It seems that you're using a kind of old C++, pre ISO 1998, while I don't think you need that. However, if you want to stick with your approach, then do the following: after cin.getline() (no need to return anything) write: cin.clear(); cin.sync();, as follows:
void setGolf(Golf &g)
{
cout << "Enter a name for the golf structure:" << endl;
getline( cin, g.fullname ) );
cin.clear();
cin.sync();
}
Now, about modernizing your code. First of all, you can use the standard library's class string, which is able to store a string literal, even growing if needed, without giving a maximum value of chars. This is somewhat confusing, since you are including the header string, which will include that class, but you're not using it. The use of string also comes with other advantages, such as automatically correcting the potential buffer overflow which could happen in your Golf structure. So I would change your structure to be:
struct Golf{
string fullname;
int handicap;
};
Now you can use getline(), in utility, which reads a whole line and stores it in string, doing all the magic for you. So you could change your golf.cpp file, to:
#include <utility>
//...
void setGolf(Golf &g)
{
cout << "Enter a name for the golf structure:" << endl;
getline( cin, g.fullname ) );
}
You can now also change the return type to void. It is not probable to experience an error of any kind while using getline(). Anyway, take into account that you could return bool (boolean type), which is a built-in type, with literals true and false.
I am certain that you could change your main() now, to a simpler style:
int main()
{
Golf myGolf;
setGolf(myGolf);
showGolf(myGolf);
setGolf(myGolf);
showGolf(myGolf);
return 0;
}
Finally, you could consider encapsulating your information in a class, instead of a struct, but that is a whole different issue.
Hope this helps.

You can also leave char[] instead of replacing it with string(I am still learning, so if I'm wrong please correct me). I think that when
std::cin.get(char *,Size) is not able to load characters, it's turning 2 bits on 0, fail and error, this is my solution:
std::cin.get(g.fullname, Len);
if(!std::cin)
{
std::cin.clear();
std::cin.get();
std::cout << "You inserted empty line." << std::endl;
return 0;
}

Related

How do i get a user to pick a number in c++

i am trying to make the user pick a number thats leads to a another code in c++ how do i do that?
cout << "Choose a text: "
getline(????)
1:
code number one
2.
text number 2
Pick a number?
I would assume you are talking about inputing a integer.
getline mostly is used for a string and spaces between each words, or a word.
For example if the input is like "Happy thanks giving"
the code would be like:
#include <iostream>
#include <string> //to use getline(cin, variable_name)
using namespace std;
int main()
{
string sentenceWithSpace;
cout << "get input" << endl;
getline(cin,sentenceWithSpace);
cout << sentenceWithSpace << endl;
system("pause"); // include this line if you use VS
return 0;
}
if the user is just inputing a value like 1,2,3,4,5,6
#include <iostream>
using namespace std;
int main()
{
int thisIsJustAInteger;
cout << "get input" << endl;
cin >> thisIsJustAInteger;
cout << thisIsJustAInteger << endl;
system("pause"); // include this line if you use VS
return 0;
}

Code doesn't work as intended in visual c++ (examples from bjarne stroustrup programming and principles book 2n version)

Okey as I've recently started to read about C++ and try to go with the book I'm having Programming Principles and practice Using C++ 2nd version.
I'm a total newbie so this is probably why, but here goes.
Okey so in the book they have you implement a header .h file instead of the (iostream) etc. So it just have all those for the start as the book doesn't want us to focus on those libraries in the start of the learning.
So i implemented it and used it (not sure if this is related to the problem). Anyway at page 77, I'm getting stuck.
Basically it's a wrong value that's getting entered and it's supposed to just show -1(or 0) as the int gets a false value, etc Carlos(letters, not an integer) so the int doesn't get a correct value so the code that is supposed to work (and show 0 or -1 as it's an incorrect value that's entered) is this according to the book:
#include "std_lib_facilities.h"
using namespace std;
int main()
{
cout << "Please enter your first name and age\n";
string first_name = "???"; // string variable // ("???” means “don’t know the name”)
int age = –1; // integer variable (–1 means “don’t know the age”)
cin >> first_name >> age; // read a string followed by an integer
cout << "Hello, " << first_name << " (age " << age << ")\n";
}
and this is what i wrote:
#include "std_lib_facilities.h"
using namespace std;
int main()
{
cout << "Please enter your first name and age" << endl;
string First_Name = "???";
int Age = -1;
cin >> First_Name >> Age;
cout << "Hello, " << First_Name << "(age" << Age << ")" << endl;
keep_window_open();
return 0;
}
However, the result with visual c++ for me is a crash when i for example write 22 Carlos.
According to the book it's supposed to output Hello, 22 (age -1)
But for me it just crashes after i enter the word Carlos as value for age...
I don't get a a error or anything when i run and compile it, but it crashes after when i give the false value for age.
What am i doing wrong?
add: I know i can use a string to get it to work, however I'm just interested in why it doesn't work as I'm following this book i wish to follow it without having these kind of problems as it's intended to work.
Here is a gif when im doing it:
http://imgur.com/a/ERjhz
Solution: To use system("pause"); instead of keep_window_open();
however it's still annoying to read the book with the knowledge that the code in the book doesn't work always :(
Well it is isn't a problem but too fast to be noticed by our eyes.
i am adding the function definition of keep_window_open()
inline void keep_window_open()
{
cin.clear();
cout << "Please enter a character to exit\n";
char ch;
cin >> ch;
return;
}
As you can see it simply takes the character input from the us
Forward you will learn about input stream and its buffer
So when you input a character in place of integer there is error flagged in the stream(background) and the only one of the characters input is used(in your case 'C' is used for flagging).
I am using input as Carlos 22
So now the input stream is still having characters 'a','r','l','o','s',22
so now the 'a' is used as a input for keep_window_open function
and the program ends without waiting for a input from you
So there is no error or crash but since the character is already there for input for keep_window_open function so its kind of really fast
The problem is in keep_window_open. It's a tricky function that is very hard to get absolutely right. You can replace it with this code that sidesteps the problem but only works on Windows:
inline void keep_window_open()
{
system("pause");
}
or with this slightly more complicated code that tries to take more cases into account:
inline void keep_window_open()
{
cout << "Please enter a character to exit\n";
if (!cin)
{
cin.clear();
cin.ignore(120, '\n');
}
char ch;
cin >> skipws >> ch;
}
(This assumes you don't enter lines longer than 120 characters. Replace 120 with numeric_limits<streamsize>::max() if you want it to be free from arbitrary limits. Other functions from std_lib_facilities.h do use 120 in this situation. You many or may not have to add #include <limits> directive to your program).
I have tested in a couple of cases and it appears to work with both correct and incorrect input to the program, but use it at your own risk. It still may or may not work correctly if your program requires more complicated input.
A good rule is to always except that the end users is idiots, so you need to write the program in a way that can handles all kinds of inputs without crashing. Therefore always read input numbers as std::string and then try convert it to int, short, double, unsigned int or what ever datatype you are using.
Your code should look like:
#include <cstdlib>
#include <exception>
#include <iostream>
#include <stdexcept>
#include <string>
int main(int argc, char **argv)
{
int age;
std::string first_name;
std::string input_age;
std::cout << "Please enter your first name and age: " << std::endl;
std::cin >> first_name >> input_age; // Read the age as 'std::string'
try
{
age = std::stoi(input_age); // Try to convert age from 'std::string' to 'int'
std::cout << "Hello, " << first_name << " (" << age << ")" << std::endl;
}
catch(std::invalid_argument& ex) // 'std::stoi()' will throw 'std::invalid_argument' if it's not able to convert 'std::string' to 'int'
{
std::cerr << "Unable to convert input value ('" << input_age << "') to 'int'" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
}
catch(std::out_of_range& ex) // 'std::stoi()' will throw 'std::out_of_range' if 'std::string' is too small or too big to store in a 'int'
{
std::cerr << "The input value (" << input_age << ") is out of range, please input a value inside the range" << std::endl;
std::cerr << "Debug info: " << ex.what() << std::endl;
}
return EXIT_SUCCESS;
}
So it's nothing to do with code, it's something to do with input.
when i for example write 22 Carlos.
The problem is that the code is asking for First_Name then Age, Not Age then First_Name. So when you put 22 for First_Name, the .exe got confused.
for example lets say I did this
int y = 0;
cout << "Give me INT: ";
cin >> y;
cout >> "You put: " >> y;
And when I run the program and put this for input
Give me INT: ghaisewofasd
*crashed*
This is a problem because the user is giving a string for when the code is asking for a int.
So for your case, instead of writing 22 Carlos, just write Carlos 22.
Also keep in mind, this book maybe not so correct, because it shouldn't print out Hello, (22). Now a days stuff like that crash if that happens, maybe it was a older version of C++.

Can anyone help identify why this wont execute properly? IF promblems with cast

#include <iostream>
#include <fstream>
using namespace std;
int run_t = 0;
char q_mos;
char i_pstring;
int main () {
cout << "Would you like to write to the temporary datapcku database?\nSelect Y/N\n";
cin >> q_mos;
if(q_mos = char(Y)){ //for some reason I am having time resolving the value of Y
while(run_t=0){
cout << "Running Input Operations.\n";
cout << "Please provide me with a Question so it can be achrived in the Active DB(Directory)\n";
cin >> i_pstring;
cout << "Please tell me the answer...\n";
cout << i_pstring;
}
run_t=1;
} else {
run_t=1;
cout << "Booting into main operations...\n";
}
cout << "At diagnostic Boot menu, prepare for diagnostic on system config orginaztional routines.\n";
ofstream binlib;
binlib.open ("datapcku.bin", ios::app | ios::binary );
binlib << "Writing this to a file.\n";
binlib.close();
while(1){}
return 0;
}
As is is apparent I wanted to use my run_t variable to control complete program maneuverability but I am having a time executing q_mos to cin input and I can not understand why the logic appears to be failing, as in the simple while loop following the q_mos comparison wont execute even one I get inside the block.
Do i need to convert q_mos to a string? And what could be affect my run_t variable while loop.
A couple of things are wrong.
In your if(q_mos = char(Y)) statement,
a) you are assigning, not comparing (use == instead of =). This also applies to your while loop.
b) replace char(Y) with 'Y', as you are passing it at the moment, Y is perceived to be a variable.

Why do I get an out_of_range exception here?

Currently doing a project at uni where at first I need to de-hyphenate a string, seemed pretty simple however when i run the program it has an error WeirdPuncProgram.exe: Microsoft C++ exception: std::out_of_range at memory location 0x004EF898
It also is not returning the string value properly, inside the function answer() is changed and hyphens are removed but once it comes out its just the original input again.
#include <iostream>
#include <string>
using namespace std;
string answer;
string hyphonRemover(string answer)
{
string spacer = " ";
int h;
for (int i = 0; i < answer.length(); i++)
{
h = answer.find_first_of("-");
answer.replace(h, 1, spacer);
}
return answer;
}
int main()
{
cout << "Type a sentence which contains punctuation and ill remove it for you! " << endl << endl;
getline(cin, answer);
hyphonRemover(answer);
cout << answer << endl;
system("pause");
return 0;
}
every use of answer in hyphonRemover() will be local variable, not global answer you defined above.
thus the function will modify only its local variable.

Testing for an integer in c++

I'm trying to write a c++ program that tests each input integer, and stops if the input is invalid.
Here is my code, without the testing part:
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int i;
do
{
cout << "\nPlease enter an integer: ";
cin >> i;
cout << endl << i << endl;
} while(i != 0);
system("Pause");
return 0;
}
How can I test the input for validity?
The easiest is to use std::getline to read a whole line of input into a std::string, and then test whether that string is a valid integer specification.
It's also possible to do this by testing the failure state of cin, and clearing it, but that way lies an assortment of complications that you don't want.
In order to test the string you can use a high level std::istringstream (just read from it and test its failure state after) or, more efficient but a little more complicated, strtol from the C library (the latter is what a C++ stream uses internally).
You need to test whether a string is an integer without crashing.
You can do this with strtol(). It converts the string to an integer, and reports on the first character that is not a legal char for a number. No invalid characters means the entire string was an integer.
There is a good description and example of how to use it here:
http://www.tutorialspoint.com/c_standard_library/c_function_strtol.htm
#include <iostream>
#include <stdlib.h>
using namespace std;
int main()
{
int i;
do
{
cout << "\nPlease enter an integer: ";
while(!(cin >> i))
{
cin.clear();
cin.ignore();
cout << "\nInput was invalid, please re-enter: ";
}
cout << endl << "The integer is: " << i << endl;
} while(i != 0);
system("Pause");
return 0;
}