c++ string input

This is a discussion on c++ string input within the C++ Programming forums, part of the General Programming Boards category; I'm trying to learn how to receive input that includes whitespaces from the keyboard into a c++ string. I wrote ...

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    595

    c++ string input

    I'm trying to learn how to receive input that includes whitespaces from the keyboard into a c++ string. I wrote this simple Person class and Tperson driver program to play with. Most of it works as expected, except for two lines indicated by comments where it prints the prompt "Enter first name > " & then immediately prints the next prompt without waiting for input.

    What am I doing wrong?

    (I'm pretty sure it has nothing to do with the difference between the parameters of the methods setFirstname(string s) and setLastname(string &s); I did that as an experiment to learn what difference the reference would make, but I haven't gotten to that issue yet.)

    Code:
    // Tperson.cpp:
    
    // trial version: trying to enable 2-word names (not successful yet)
    
    #include <iostream>
    #include <string>
    
    #include "person.h"
    using namespace std;
    
    int main()
    {
    	string s1,s2;
    	int z;
    	char c;
    	double rate;
    	Person p1;
    	Person *p2;
    
    	cout.setf(ios::fixed);
    	cout.precision(2);
    	cout << "Testing default constructor:\n";
    	p1.print();
    	cout << "\nTesting mutator functions:\n";
    	cout << "Enter first name > ";
    	getline(cin,s1);
    	p1.setFirstname(s1);
    
    	cout << "Enter last name > ";
    	getline(cin,s1);
    	p1.setLastname(s1);
    
    	cout << "Enter age > ";
    	cin >> z;
    	p1.setAge(z);
    	cout << "Enter salary > ";
    	cin >> rate;
    	p1.setSalary(rate);
    	cout << "Enter sex > ";
    	cin >> c;
    	p1.setSex(c);
    	p1.print();
    
    
    	cout << "\nNow testing dynamic allocation with name constructor:\n";
    
    	cout << "Enter first name > ";
    	getline(cin,s1);			// can't figure out why this line *********************
    								// is being skipped; printing to screen
    								// Enter first name > Enter last name >
    								// and then waiting for input
    
    	cout << "Enter last name > ";
    	getline(cin,s2);
    	p2 = new Person(s1,s2);
    	p2 -> print();
    	cout << "\nNow testing mutator functions on dynamically allocated object:\n";
    	cout << "Enter last name > ";
    	getline(cin,s1);
    	p2 -> setLastname(s1);
    	cout << "Enter age > ";
    	cin >> z;
    	p2 -> setAge(z);
    	cout << "Enter salary > ";
    	cin >> rate;
    	p2 -> setSalary(rate);
    	cout << "Enter sex > ";
    	cin >> c;
    	p2 -> setSex(c);
    	p2 -> print();
    	delete p2;
    
    	cout << "\nNow testing multiple inputs:\n";
    	for (int i=0; i<5; i++)
    	{	
    		p2 = new Person();
    		cout << "Enter first name > ";
    		getline(cin,s1);		// here too, this line ********************************
    								// is being skipped; printing to screen
    								// Enter first name > Enter last name >
    								// and then waiting for input	
    
    		p2 -> setFirstname(s1);	
    		cout << "Enter last name > ";
    		getline(cin,s1);
    		p2 -> setLastname(s1);
    		cout << "Enter age > ";
    		cin >> z;
    		p2 -> setAge(z);
    		cout << "Enter salary > ";
    		cin >> rate;
    		p2 -> setSalary(rate);
    		cout << "Enter sex > ";
    		cin >> c;
    		p2 -> setSex(c);
    		p2 -> print();
    		delete p2;
    	}
    
    	return 0;
    }
    
    
    ////////////////////////////////////////////////////////////////////
    // person.h
    #ifndef _person_h
    #define _person_h
    
    #include <string>
    #include <iostream>
    using namespace std;
    
    
    class Person{
    public:
    	Person()  {_firstname=_lastname="unknown"; _salary=_age=_sex=0;}
    	Person(string s1, string s2) { setFirstname(s1); setLastname(s2); _salary=_age=_sex=0;}
    	void setFirstname(string &s) {_firstname = s;}
    	void setLastname(string &s)  {_lastname = s;}
    	void setAge(int z) {_age = z;}
    	void setSalary(double r) {_salary = r;}
    	void setSex(int x)  {_sex=x;}
    	void print(void) { cout << _lastname << " "
    			<< _firstname << endl;
    			cout <<  "   age: " << _age << "   salary: " << _salary << "   sex: " << (char)_sex << endl;}
    
    
    private:
    	string _firstname;
    	string _lastname;
    	int _age;
    	double _salary;
    	int _sex;
    	
    };
    
    
    #endif

  2. #2
    Registered User
    Join Date
    Sep 2002
    Posts
    254
    getline is buggy so try adding on msvc++ 6.0

    add cin.ignore() in there

  3. #3
    RoD
    RoD is offline
    Redundantly Redundant RoD's Avatar
    Join Date
    Sep 2002
    Location
    Missouri
    Posts
    6,331
    Fix to <string>
    The header <string> contains a definition for template function getline. It has a lookahead problem -- typing a delimiter to end the input doesn't return control until you type yet another character. Change the code as indicated by the comment:

    else if (_Tr::eq(_C, _D))
    {_Chg = true;
    _I.rdbuf()->snextc(); // replace snextc with sbumpc
    break; }
    see if that helps.

  4. #4
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    That's great. Thanks, Z! I put cin.ignore() before those two getlines & it works fine.

    BTW, this problem was not just in MSVC. The same thing happened using Borland bcc32 and with a Unix CC compiler, and cin.ignore() fixes it for those compilers too.

  5. #5
    Registered User
    Join Date
    Feb 2003
    Posts
    595
    RoD:

    I guessed that your comment applies specifically to MSVC 6.0, correct? (Since I wouldn't be able to mess around with the Sun or Borland files in any case.)

    Anyway, it turns out that ZerOrDie's suggestion was all I needed for those two compilers.

    MSVC needed both. I had to change that code segment in the <string> header file AND add cin.ignore() before getline in both places where it appears after a cin >>, and now it works correctly.

    Incidentally, the <string> segment is slightly different from yours (there's an (_E) before the _C):

    Code:
    else if (_Tr::eq((_E)_C, _D))
                    {_Chg = true;
                    _I.rdbuf()->sbumpc();//**************changing snextc(); to sbumpc();

    Thanks for your help.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. char Handling, probably typical newbie stuff
    By Neolyth in forum C Programming
    Replies: 16
    Last Post: 06-21-2009, 04:05 AM
  2. Replies: 14
    Last Post: 01-18-2008, 03:14 PM
  3. Replies: 4
    Last Post: 03-03-2006, 01:11 AM
  4. can anyone see anything wrong with this code
    By occ0708 in forum C++ Programming
    Replies: 6
    Last Post: 12-07-2004, 11:47 AM
  5. lvp string...
    By Magma in forum C++ Programming
    Replies: 4
    Last Post: 02-26-2003, 11:03 PM

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21