Skip to main content
gamedev.net
🔒 Locked

Input problem

Started by Nitin Apr 25, 2007 at 8:26 AM 12 replies 1k views
Original Post
Nitin
Nitin
Hi. i've just about grasped the basics of c++, i know how to operate on pointers, work with objects, a little bit of inheritance and all the other basic manipulations. I've learnt all this through self-learn books which all seem to teach uptill here and then drop off. Now i'm unable to move on. i worked with turbo c++ 3.0 till now, and finally i've jumped to the GNU. what do i learn next, and (since most of you have cleared this stage of learning), could you point out any nice links for ebooks, tutorials, etc.? Thanks a lot in advance. oh, i also have this problem with the input with my code::blocks compiled program. here it is. can you please tell me why getline(std::cin, string h) does not work sometimes? thanks again. Edit: please use [source lang="cpp"] [source] tags to display large portions of source code (> 10 lines) - Emmanuel

#include <iostream>
#include <string>
#include <fstream>
#include <stdlib.h>


using namespace std;
void save();


class std_employee
{
    private:

    int number;
    string name;
    string ans;

    public:
    std_employee()
    { system("CLS"); }

    void disp_data()
    {
        cout<<"\nthe employee's name is: ";
        cout<<name<<endl;
        cout<<"\nthe employee's number is: ";
        cout<<number<<endl;
    }
    void take_data()
    {
        cout<<"\nenter the employee name: ";
        getline(cin,name);
        cout<<"\nenter the employee's number: ";
        cin>>number;
    }
    void store()
    {
        cout<<"\n\nsave file?"<<endl;
        getline(cin,ans);
        if(strcmp(ans,"yes") == 0)
        {
            save();
        }
        else
        {
            exit(0);
        }
        save();
    }


};

void save()
    {
        std_employee emp1;
        string file;
        cout<<"save as?: ";
        getline(cin,file);
        ofstream out("test.txt");
        out<<"it aint wurking";
        out.close();
        cout<<"\nsaved successfully.\n"<<endl;
    }

int main()
{
    std_employee emp1,*ptr;
    ptr = &emp1
    ptr->take_data();
    ptr->disp_data();
    cin.get();
    ptr->store();
    return 0;
}



cheers [Edited by - Nitin on April 25, 2007 9:23:39 AM]
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
Dave Hunt
Dave Hunt
You'll need to be a bit more specific than "can you please tell me why getline(std::cin, string h) does not work sometimes?"

What exactly is doing/not doing?
Nitin
Nitin
after the output of "save file?", it's quitting. (it says "press enter key to continue" and quits). Is this supposed to happen and if so, why?
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
Nitin
Nitin
ok. i googled the problem and found out it could be caused by:
a.) the buffer not being "flushed", as people call it.
b.) me not using cin.ignore();

but, i used both <
code:

void save();

void store()
{
cout<<"\n\nsave file?"< cin.ignore();
getline(cin,ans);
if(ans == "yes")
{
save();
}
else
{
exit(0);
}

}


};

void save()
{
std_employee emp1;
string file;
cout<<"save as?: "< cin.ignore();
getline(cin,file);
ofstream out("test.txt");
out<<"it wurking";
out.close();
cout<<"\nsaved successfully.\n"< }

-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
Haax
Haax
First, please use [ source] [ /source] tags when posting source.

Your code seems to work fine. The only problem is it doesn't check for any input other than "yes". If the input is not recognized, then your else section runs and you have exit(0) in there. "Press any key to continue..." means execution of the program has ended.

You should check for "no" and exit based on that. If anything other than "yes" or "no" is inserted, simply tell the user they have input invalid information and call the save() function again (yes, from within itself).

void store()    {        cout<<"\n\nsave file?"<<endl;        getline(cin,ans);        if(strcmp(ans.c_str(),"yes") == 0)        {            save();        }        else if(strcmp(ans.c_str(), "no") == 0)        {          // Exit here, if they typed no.          exit(0);        }        else        {          //exit(0); // Don't exit here, just try again.          cout << "Invalid answer." << endl;          store();        }        //save(); // No need to call this again.    }


Also you don't need to use strcmp for std::string. You can simply do these checks:

if(ans == "yes")else if(ans == "no")
Nitin
Nitin
i tried it, but it still doesn't work!
when i type in yes,
it says - "invalid answer" and does the same when i type in no.
what's wrong? is it something to do with code::blocks?

 void store()    {        cout<<"\n\nsave file?"<<endl;        cin.ignore();        getline(cin,ans);        if(ans == "yes")        {            save();        }        else if(ans == "no")        {            exit(0);        }        else        {            cout<<"invalid answer";            cin.get();            store();        }    }};void save()    {        std_employee emp1;        string file;        cout<<"save as?: "<<endl;        cin.ignore();        getline(cin,file);        ofstream out("test.txt");        out<<"it wurking";        out.close();        cout<<"\nsaved successfully.\n"<<endl;        cin.get();    }
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
Haax
Haax
First, make sure you understand cin.ignore and cin.getline.

cin.getline(string) // retrieves a line from the input buffer (std::cin)
cin.getline(string, 100) // retrieves up to 100 chars from the lines start
cin.getline(string, 100, ';') // retrieves a line until the ';' character

cin.ignore() // A single char is discarded from the input buffer.
cin.ignore(2) // Two chars are discarded from the input buffer.

If you don't provide a delimiter character as the 3rd argument to getline, it defaults to newline '\n'. While cin.getline will extract the delimiter as part of the line, cin.get, and "cin >>" will not. Consider this example:

/*1*/ std::string strFirst;/*2*/ std::string strSecond;/*3*/ std::cin >> strFirst;/*4*/ std::cin.getline(strSecond);


First, cin will read input until the newline '\n' or whitespace ' ' is encountered, and stop. Unline getline, get will not read this character in and will leave it in the buffer. Then the program will then use getline to read the input buffer up until '\n'. However the problem is that the '\n' character was not removed in the line above, so getline encounters it immediately and figures it's done reading the next line. The solution would be a cin.ignore() after line 3 to remove the newline from the input buffer before calling getline.

Long story short, you don't need cin.ignore() in your program because you're only using cin.getline, which is extracting the newline for you. When you use cin.ignore in your store() function, you're discarding one character from the input buffer. If you type "yes" getline is only going to read "es". In your code above "yyes" or "3yes" or "*yes" will proceed to save(). Comment out those ignores and you'll be fine.
Nitin
Nitin
Thanks Haax. you diagnosed the problem most precisely and put it by succintly.
Thanks a lot.
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
jouley
jouley
Quote:
Original post by Haax
You should check for "no" and exit based on that. If anything other than "yes" or "no" is inserted, simply tell the user they have input invalid information and call the save() function again (yes, from within itself).

I'm not sure this is the place for recursion. While stack overflows aren't a real problem here (though possible!), the standard way to ignore invalid data is to loop until the data is valid:
while (input != "yes" && input != "no")  input = AskForInput( );if (input == "yes")  // ...else  // ...
Nitin
Nitin
how does it matter if recursion is used or not?
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
jouley
jouley
The main use of recursion is to solve one big problem by solving little bits of it at a time. There are exceptions, but that's the main goal. Your big problem, that of getting valid input, can't really be split up into little problems. So, while recursion here works, it makes me shiver -- all those extra pushes and pops off of the stack aren't necessary at all. A simple looping construct achieves the exact same thing, without the added overhead.

Also, say you wanted to add something else to your save method, such as a portion of code that would open a file for writing. If you called save( ) from inside of itself, it would open the file again and again. While it's true that you probably wouldn't open the file until the "yes" signal is given, there are other, less trivial things that could crop up that I can't think of at the moment. Basically, save( ) could include more than just asking yes or no. Since asking yes or no is the only thing you want to repeat, you shouldn't re-call the whole function for it when a loop will do just as well, if not better.
EnigmaticCoder
EnigmaticCoder
Quote:
Original post by Nitin
how does it matter if recursion is used or not?


Recursion can take up a lot of memory if used incorrectly. Generally, when you want to use recursion, you have to make sure that the function will not call itself more than a few times. The reason it uses so much memory is because the variables from the first function call stay in scope until all subsequent function calls are returned.
--------------------Enigmatic Coding
Nitin
Nitin
Understood. so what you say is that the entire function getting repeated causes a lot of memory usage. Had never thought of it before. But what's a stack?
-------------------------------Expect the felon to post more queries (which may appear mundane to theprofessional's eye, but humour me, for the learner and the infernalnewbie that i am. I'm sure i'll cross this stage soon.).
jouley
jouley
More than you want to know ;). Basically, the stack is a section of memory that stores everything about what is currently going on in your program. Every variable declared as either a parameter to a function or as a local variable withing the function is stored on the stack. Once the function exits, this memory is released and reused for the next function call. Recursion, though, keeps these variables around until the stack unwinds, going back through every previous call to the function.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.