Welcome
Welcome to the forums of AntiRTFM's Absolute N00b Spoonfeed C++ Tutorials!

You are currently viewing our boards as a guest, which gives you limited access to view most discussions and access our other features. By joining our free community, you will have access to post topics, communicate privately with other members (PM), respond to polls, upload content, and access many other special features. Registration is fast, simple, and absolutely free, so please, <a href="/profile.php?mode=register">join our community today</a>!

Debug Project 6 (Medium)

Think you can spy out that little nasty bug? Try debugging some code in here

Debug Project 6 (Medium)

Postby Doctor Salt on Fri Aug 22, 2008 7:56 pm

(I hope i'm not breaking a rule posting here)

Okay, so I came across this problem while coding, and i though it might be useful showing it to everyone else.

So tell me what the problem is, and how to fix it.

HINT: The program compiles fine, so it couldn't tell you where the problem is :P)

EDIT:Before, i accidently solved my problem, but now its broken, like it should be. Before looking at c++'s solution, just take a look at the code first, and guess, then look.

Code: Select all
#include "stdafx.h"
#include <iostream>
#include <string>
using namespace std;

int main ()
{
   string name;
   int age;
   string address;

cout << "\nEnter your name\n";
   cin >> name;

cout << "\nNow enter your age\n";
   cin >> age;

cout << "\n Good, now enter your address, including street number\n";
cout << "(Example. 23 Maple Lane)\n";
   getline( cin, address);
   cout << "\nYou, " << name << ", are " << age << " years old, and you live on " << address << ".";

   char f;
   cin >> f;
}



If you really can't get it, try running the program
Last edited by Doctor Salt on Fri Aug 22, 2008 9:46 pm, edited 2 times in total.
I'm a 15 year old kid who has his heart set on Programming, almost as much as Marss++.......

Came here hoping to ask more questions so if you have any free time just say!
Doctor Salt
 
Posts: 147
Joined: Wed Jul 30, 2008 3:32 pm

Postby C++ on Fri Aug 22, 2008 8:35 pm

I came across the same problem while I was learning. The problem is the combined use of cin and getline. cin does not remove whitespaces or newlines from the input buffer when it encounters one. Getline however will stop at the first newline it encounters. Btw... I didn't encounter the problem in your example because you use getline twice. The first getline will simply read the newline only, while the second one will read the entire string up until the newline.

After inputting name a newline or a part of the name will be still in the input buffer. It's better to use getline for getting a name, since cin will stop when it encounters a space. The newline gets ignored and removed from the input buffer when cin scans the buffer for an entered int value. However requesting int type of input from cin is dangerous. If a user inputs a string, or the second part of the name is still in the buffer, the results will be unpredictable. Therefore you check in a loop if cin is going into error mode. You then simply clear the error state and clean the max length of the buffer of any chars cin won't swallow.

However after cin is done putting a valid int value in age, there's still a newline in the buffer that gets ignored. A simple cin.ignore() will remove a single unprocessed char from the input buffer. This will prevent the first getline from processing nothing but a newline. The first newline should therefore be replaced by a cin.ignore() since it's more efficient.

Code: Select all
#include <iostream>
#include <string>

using namespace std;

int main ()
{
     string name;
     int age;
     string address;

     cout << "\nEnter your name\n";
     getline(cin, name);
     
     cout << "\nNow enter your age\n";
     while (!(cin >> age))
          {
               cin.clear();
               cin.ignore(numeric_limits<streamsize>::max(),'\n');
          }

     cout << "\n Good, now enter your address, including street number\n";
     cout << "(Example. 23 Maple Lane)\n";
     cin.ignore();
     getline(cin, address);
     cout << "\nYou, " << name << ", are " << age << " years old, and you live on " << address << ".";
     
     char f;
     cin >> f;
}
C++
teh awesome
 
Posts: 217
Joined: Sun May 25, 2008 7:45 am

Postby Doctor Salt on Fri Aug 22, 2008 9:45 pm

ah.... i fail at life... lol. (I "fixed" my code) I added the second getline in afterwards, to make sure it still works with it added in.... But forgot to take it out, and accidently solved it for you....

Anyways, adding in two
getline(cin, name);
getline(cin, name);

seems like the easiest solution for me. However, c++'s method is fool proof, and means it won't crash jsut because of some damn runtime error.

My metaphorical explanation of why it works is that the first getline takes the metaphorical bullet for the next getline (bullet = newline). The second getline does its job correctly.


EDIT: Hmm, thats interesting, i tried copy pasting your code into my compiler, and it didn't work..... Hmmm
I'm a 15 year old kid who has his heart set on Programming, almost as much as Marss++.......

Came here hoping to ask more questions so if you have any free time just say!
Doctor Salt
 
Posts: 147
Joined: Wed Jul 30, 2008 3:32 pm

Postby C++ on Sat Aug 23, 2008 5:01 am

Doctor Salt wrote:ah.... i fail at life... lol. (I "fixed" my code) I added the second getline in afterwards, to make sure it still works with it added in.... But forgot to take it out, and accidently solved it for you....

Anyways, adding in two
getline(cin, name);
getline(cin, name);

seems like the easiest solution for me. However, c++'s method is fool proof, and means it won't crash jsut because of some damn runtime error.

My metaphorical explanation of why it works is that the first getline takes the metaphorical bullet for the next getline (bullet = newline). The second getline does its job correctly.


EDIT: Hmm, thats interesting, i tried copy pasting your code into my compiler, and it didn't work..... Hmmm


Well unfortunately you have to have a failsafe in user input when it comes to numbers. A program can crash if the unstable result is used for further stuff. It has to be idiot proof :P The cin.ignore() is more efficient to use than a second getline. A getline requires more operations than a simple char that gets cleared from the input buffer.

Why isn't it working? Do you get a compiler error? I noticed that you use Visual Studo C++ with precompiled header support. I removed the include because I'm using Linux with the GNU comiler. Be sure to replace it again or remove the precompiled header support.

Code: Select all
#include "stdafx.h"
C++
teh awesome
 
Posts: 217
Joined: Sun May 25, 2008 7:45 am

Postby Marss++ on Sat Aug 23, 2008 10:25 am

Yeah. The Cin.Ignore peace of code is a lifesaver. I came across this problem once, and it would just skip my getline() function. I swore it wasn't my fault and the computer was retarded, but then I found out about the whole ignore function a while back and it was great.
I'm a 15 year old kid who has his heart set on Programming.

Came here hoping to help so if you have any questions just ask!
Marss++
 
Posts: 149
Joined: Fri Jul 18, 2008 3:20 pm

Postby Doctor Salt on Sat Aug 23, 2008 11:35 am

Hmm, well so i tried compiling it, and it basically said..

error C2780: 'const _Ty &std::max(const _Ty &,const _Ty &)' : expects 2 arguments - 0 provided

see declaration of 'std::max'

error C2065: 'numeric_limits' : undeclared identifier
error C2275: 'std::streamsize' : illegal use of this type as an expression

see declaration of 'std::streamsize'
error C2780: 'const _Ty &std::max(const _Ty &,const _Ty &,_Pr)' : expects 3 arguments - 0 provided

Am I missing some type of heading or something? I'm using visual express, on vista....
I'm a 15 year old kid who has his heart set on Programming, almost as much as Marss++.......

Came here hoping to ask more questions so if you have any free time just say!
Doctor Salt
 
Posts: 147
Joined: Wed Jul 30, 2008 3:32 pm

Postby C++ on Sat Aug 23, 2008 11:54 am

Doctor Salt wrote:Hmm, well so i tried compiling it, and it basically said..

error C2780: 'const _Ty &std::max(const _Ty &,const _Ty &)' : expects 2 arguments - 0 provided

see declaration of 'std::max'

error C2065: 'numeric_limits' : undeclared identifier
error C2275: 'std::streamsize' : illegal use of this type as an expression

see declaration of 'std::streamsize'
error C2780: 'const _Ty &std::max(const _Ty &,const _Ty &,_Pr)' : expects 3 arguments - 0 provided

Am I missing some type of heading or something? I'm using visual express, on vista....


I think you need to include limits.

Code: Select all
#include <limits>
C++
teh awesome
 
Posts: 217
Joined: Sun May 25, 2008 7:45 am

Postby Doctor Salt on Sat Aug 23, 2008 12:44 pm

Ah, that did the trick. Just wondering, how would one use that code, the
Code: Select all
while (!(cin >> variable))
          {
               cin.clear();
               cin.ignore(numeric_limits<streamsize>::max(),'\n');
          }

and have it so when it encounters an error, it also gives you a simple message?

cout << "You did not enter a number! You die now infidel!\n";

Well, i guess i mean where would you put the cout statement.
I'm a 15 year old kid who has his heart set on Programming, almost as much as Marss++.......

Came here hoping to ask more questions so if you have any free time just say!
Doctor Salt
 
Posts: 147
Joined: Wed Jul 30, 2008 3:32 pm

Postby C++ on Sat Aug 23, 2008 1:49 pm

Doctor Salt wrote:Ah, that did the trick. Just wondering, how would one use that code, the
Code: Select all
while (!(cin >> variable))
          {
               cin.clear();
               cin.ignore(numeric_limits<streamsize>::max(),'\n');
          }

and have it so when it encounters an error, it also gives you a simple message?

cout << "You did not enter a number! You die now infidel!\n";

Well, i guess i mean where would you put the cout statement.


Code: Select all
while (!(cin >> variable))
          {
               cout << "You did not enter a number! You die now infidel!\n";
               cin.clear();
               cin.ignore(numeric_limits<streamsize>::max(),'\n');
          }


Now everytime you enter a non numerical value, you will get an error message. If cin encounters a char in the input stream it can't translate as a digit, then the cin state goes into error state.
C++
teh awesome
 
Posts: 217
Joined: Sun May 25, 2008 7:45 am

Postby Doctor Salt on Sat Aug 23, 2008 3:02 pm

Thanks, that should work :P
I'm a 15 year old kid who has his heart set on Programming, almost as much as Marss++.......

Came here hoping to ask more questions so if you have any free time just say!
Doctor Salt
 
Posts: 147
Joined: Wed Jul 30, 2008 3:32 pm


Return to Debug

Who is online

Users browsing this forum: No registered users and 0 guests