Thread: First letter is missing

  1. #1
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193

    Question First letter is missing

    Continuing the golf odyssey, the program is not printing the first letter.

    Code:
     
    #include <iostream> 
    #include <string>
    #include <cstring>
    #include "../Headers/golf.h"
    
    int main() 
    { 
       using std::cout; 
       using std::cin; 
       using std::strlen;
       using std::string; 
       using sport::showgolf;
       using sport::setgolf;
       using sport::golf; 
       
       string fullname;
       int players, handicap; 
       
       cout << "How many players are playing? "; 
       while(!(cin >> players))
       { 
         cin.clear();
         while(cin.get() != '\n') 
           continue; 
         cout << "Please enter how many players are playing: ";     
       }        
       cin.get();
       golf *golfers = new golf[players];
       for(int i = 0; i < players; i++) 
       { 
          cout << "Enter your full name: "; 
          if(cin.get() == '\n') 
           break; 
          getline(cin, fullname);
          cout << "Enter the handicap: "; 
          (cin >> handicap).get();
          setgolf(golfers[i], fullname, handicap);
       } 
       
       for(int i = 0; i < players; i++) 
       { 
         showgolf(golfers[i]);  
       }        
    }
    Code:
     
    #include <iostream> 
    #include <string>
    #include <cstring>
    #include "../Headers/golf.h"
    
    namespace sport { 
        
      void setgolf(golf &g, const std::string name, int hc)
      { 
         g.fullname = name;
         g.handicap = hc;      
      }
      
      int setgolf(golf &g)
      { 
        using std::string;
        using std::cout;
        using std::cin; 
        using std::strlen;
        
        cout << "Please enter full name: "; 
        cin >> g.fullname;
        if(cin.get() == '\n') 
          return 0; 
        cout << "Please enter handicap: ";
        cin >> g.handicap;  
         
        return 1;    
      }
      
      void handicap(golf &g, int hc) 
      { 
        g.handicap = hc;  
      }     
      
      void showgolf(const golf &g)
      { 
         using std::cout; 
         using std::endl; 
         
         cout << "Your name: " <<  g.fullname << endl;   
         cout << "Handicap: " << g.handicap << endl; 
      }                           
    }
    Code:
    #ifndef GOLF_H_
    #define GOLF_H_
    
    #include <string>
    
    namespace sport { 
    
      struct golf { 
        
        std::string fullname; 
        int handicap;    
      };     
    
        // non-interactive version: 
        // function sets golf structure to provided name, handicap
        // using values passed as arguments to the function
        void setgolf(golf & g, const std::string name, int hc);
        // interactive version:
        // function solicits name and handicap from user
        // and sets the members of g to the values entered
        // returns 1 if name is entered, 0 if name is empty string
        int setgolf(golf & g);
        // function resets handicap to new value
        void handicap(golf & g, int hc);
        // function displays contents of golf structure
        void showgolf(const golf & g);
    }    
    
    #endif
    Code:
    How many players are playing? 2
    Enter your full name: thames
    Enter the handicap: 6
    Enter your full name: quack
    Enter the handicap: 8
    Your name: hames
    Handicap: 6
    Your name: uack
    Handicap: 8
    Last edited by thames; 12-20-2012 at 09:57 AM.

  2. #2
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    I am in the mac the uni gave me. I got
    Code:
    Macintosh-c8bcc88e5669-9:~ usi$ g++ -Wall px.cpp golf.cpp -o px
    px.cpp:4:17: error: array: No such file or directory
    One more reason for not using std::array.

    As Elysia said in previous post, use vectors ( and I say, if you want to have something "ready", otherwise use an array as normal (not an std one) ).

    EDIT : Removes #include<array> and it worked ( well with the same error as yours ;p )
    Last edited by std10093; 12-20-2012 at 09:52 AM.
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  3. #3
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    One more reason for not using std::array.
    I'm not using it. I forgot to delete the #include <array> directive.

    but the problem remains

  4. #4
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Yeah I edit the same time as you posted about the error.. Hmm..
    I do not know you are getting this.

    However I am sure that are making your life hard with no real reason! cin.get, getline etc... why? Use only cin, cout and endl and everything will work
    Code:
    #include <iostream>
    #include <string>
    #include <cstring>
    #include "golf.h"
    
    int main()
    {
       using std::cout;
       using std::cin;
            using std::endl;
       using std::strlen;
       using std::string;
       using sport::showgolf;
       using sport::setgolf;
       using sport::golf;
    
       string fullname;
       int players, handicap;
    
       cout << "How many players are playing? "<<endl;
            cin >>players;
            for( int i = 0 ; i < players ; i++ ) {
                    cout << "Name please. "<< endl;
                    cin >> fullname;
                    cout << "Name is " << fullname << endl;
            }
            return 0;
    }
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  5. #5
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    Use only cin, cout and endl and everything will work
    Not really... Stephen Prata says in his book you will have buffer problems if you only use general input with cin. Particularly for string input after number input, the problem below appears:

    Code:
     
    How many players are playing? q
    Please enter how many players are playing: 2
    Enter your full name: thames
    Enter the handicap: 8
    Enter your full name: Your name: hames
    Handicap: 8
    that's why I used getline() and get() for input. But this letter bug is really bugging me ... I wonder if there's something to do with that cin.get() I put after the while loop...

  6. #6
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by thames
    Stephen Prata says in his book you will have buffer problems if you only use general input with cin. Particularly for string input after number input, the problem below appears:
    Actually, if you had only used formatted input with the overloaded operator>>, then you would not be getting that problem (but you would have difficulty reading strings that contain whitespace). Likewise, if you only use string input with getline, then you would not be getting that problem (but you would have to parse the string for say, numeric input, e.g., with the help of a stringstream). However, it is precisely by mixing formatted input with the overloaded operator>> and getline that you get the buffer problems that Stephen Prata presumably alluded to. These can be avoided with care, but it is easy to get it wrong, and apparently you did get it wrong.

    EDIT:
    Here is where your problem can be pinpointed:
    Code:
    if(cin.get() == '\n')
    This reads the first character and compares it. Regardless of the comparison, the character read is discarded. Thus, the getline proceeds with the second character onwards.

    Unless you choose to use getline exclusively (and then parse strings), you will be stuck with mixing getline and operator>>. However, you don't appear to need to use get here, so don't. Rather, if you want to deliberately discard input, use cin.ignore.
    Last edited by laserlight; 12-20-2012 at 11:46 AM.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  7. #7
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    Sorry. I meant: Stephen Prata says in his book you will have buffer problems if you only use general input with cin when it comes to having a number input followed by string input.

    However, it is precisely by mixing formatted input with the overloaded operator>> and getline that you get the buffer problems that Stephen Prata presumably alluded to. These can be avoided with care, but it is easy to get it wrong, and apparently you did get it wrong.
    so, how should I do?

  8. #8
    SAMARAS std10093's Avatar
    Join Date
    Jan 2011
    Location
    Nice, France
    Posts
    2,694
    Well, I used to have inputs like the one you describe, but with a little care and cautious, everything worked nicely with typical cin, cout, endl and overloaded operators

    Why don't you take a look in post number four. Reconstruct your main by scratch. It is a small one Post back if problems
    Code - functions and small libraries I use


    It’s 2014 and I still use printf() for debugging.


    "Programs must be written for people to read, and only incidentally for machines to execute. " —Harold Abelson

  9. #9
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by thames
    Stephen Prata says in his book you will have buffer problems if you only use general input with cin when it comes to having a number input followed by string input.
    Either Stephen Prata does not know what he is talking about, or the book contains a typographical error, or you misread. For example, compile and run this program with similiar input as in your post #5:
    Code:
    #include <iostream>
    #include <string>
    #include <vector>
    #include <algorithm>
    #include <iterator>
    
    class Player
    {
    public:
        Player(const std::string& first_name_, int handicap_) :
            first_name(first_name_), handicap(handicap_) {}
    
        friend std::ostream& operator<<(std::ostream& out, const Player& player)
        {
            return out << player.first_name << " (" << player.handicap << ')';
        }
    private:
        std::string first_name;
        int handicap;
    };
    
    int main()
    {
        using namespace std;
    
        cout << "Please enter how many players are playing: ";
        unsigned int num_players;
        cin >> num_players;
    
        vector<Player> players;
        for (unsigned int i = 0; i < num_players; ++i)
        {
            cout << "Enter your first name: ";
            string first_name;
            cin >> first_name;
    
            cout << "Enter the handicap: ";
            int handicap;
            cin >> handicap;
    
            players.push_back(Player(first_name, handicap));
        }
    
        cout << "The players are:\n";
        copy(players.begin(), players.end(), ostream_iterator<Player>(cout, "\n"));
    }
    Now, change this line:
    Code:
    cin >> first_name;
    to:
    Code:
    getline(cin, first_name);
    Compile and run the program with similiar input as in your post #5.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  10. #10
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    Quote Originally Posted by laserlight View Post
    Compile and run the program with similiar input as in your post #5.
    I see. But what about full names? when Stephen Prata showed a code like this one:

    Code:
    #include <iostream>
    
    int main()
    { 
      using namespace std;
      int number; 
      string fullname;
      string hobby;  
      
      cout << "Please enter a number: "; 
      (cin >> number).get(); 
      cout << "Please enter your full name: ";
      getline(cin, fullname);
      cout << "Enter hobby: "; 
      getline(cin, hobby);
      return 0;     
    }
    he was teaching it to fix the '\n' buffer issue (he didn't show overload operators yet):

    Code:
     
    #include <iostream>
    
    int main()
    { 
      using namespace std;
      int number; 
      string fullname;
      string hobby;  
      
      cout << "Please enter a number: "; 
      cin >> number;
      cout << "Please enter your full name: ";
      cin >> fullname; 
      cout << "Enter hobby: "; 
      cin >> hobby;
      return 0;     
    }
    Code:
    thames@semaht ~/C++/Sandbox $ g++ -g -Wall strtest1.cpp -o strtest1 -std=c++11
    thames@semaht ~/C++/Sandbox $ valgrind ./strtest1
    ==2707== Memcheck, a memory error detector
    ==2707== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
    ==2707== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
    ==2707== Command: ./strtest1
    ==2707== 
    Please enter a number: 8
    Please enter your full name: thames thames
    Enter hobby: ==2707== 
    ==2707== HEAP SUMMARY:
    ==2707==     in use at exit: 0 bytes in 0 blocks
    ==2707==   total heap usage: 8 allocs, 8 frees, 230 bytes allocated
    ==2707== 
    ==2707== All heap blocks were freed -- no leaks are possible
    ==2707== 
    ==2707== For counts of detected and suppressed errors, rerun with: -v
    ==2707== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2)

  11. #11
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by thames
    But what about full names?
    Then getline becomes appropriate, upon which you have to deal with the fact that formatted input with operator>> usually stops at whitespace, which may then be read by a subsequent getline call.

    That is the whole idea behind using get() to read and discard a character: you are reading and discarding the newline character that was left on the input buffer by operator>>. However, as I mentioned in my post #6, it would be more descriptive to use ignore:
    Code:
    cin >> number;
    cin.ignore(1000, '\n'); // 1000 is arbitrary; numeric limits could be used instead
    Frankly, I think the (cin >> number).get() syntax is just being fancy: chaining does not really improve readability here, in my opinion.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  12. #12
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    Frankly, I think the (cin >> number).get() syntax is just being fancy: chaining does not really improve readability here, in my opinion.
    I don't get it. It prevents this:

    Code:
     
    Please enter a number: 8
    Please enter your full name: Enter hobby:
    when you only code a cin >> number;

    anyways, I think it's a good idea to keep the program like this and wait until the overloaded operators chapter comes to write a decent program.
    Last edited by thames; 12-20-2012 at 12:49 PM.

  13. #13
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by thames
    I don't get it. It prevents this: (...) when you only code a cin >> number;
    No, the cin >> number; thing is not the problem in itself. The problem lies when you have a cin >> number followed by a getline. For example:
    Code:
    cin >> number;
    getline(cin, fullname);
    There is no magic here: it is just the case that when you enter a number, the newline character from the enter is left in the input buffer by the cin >> number; then when getline comes along, it reads this newline, instead of reading the next line. To stop this, you can read and discard the newline character:
    Code:
    cin >> number;
    cin.get();
    getline(cin, fullname);
    Now, here's where the fanciness comes in: cin >> number is actually a function call, and this function returns an output stream, i.e., cin. Hence, we can call the get member function of that output stream:
    Code:
    (cin >> number).get();
    getline(cin, fullname);
    Of course, this assumes that the user only entered the number. The user could have entered a number followed by say, a space, upon which the get() would read and discard the space, leaving the newline in the buffer, and you still have the same problem. I saw that in your code you used a loop to solve this. Well and good, but by using ignore instead of get, you make your code both more readable, and you can specify the maximum number of characters to ignore.

    Then, we get back to your claim that "you will have buffer problems if you only use general input with cin when it comes to having a number input followed by string input". As you can see, the problem precisely lies with the placement of the getline call after the formatted input, because if you did this instead:
    Code:
    cin >> number;
    cin >> fullname;
    then cin >> fullname would skip the newline character, thus correctly reading the name (except that the name should not contain spaces).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #14
    Tears of the stars thames's Avatar
    Join Date
    Oct 2012
    Location
    Rio, Brazil
    Posts
    193
    I wil try to use cin.ignore(fullname.length(), '\n');

  15. #15
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by thames
    I wil try to use cin.ignore(fullname.length(), '\n');
    That may or may not work, but it reveals a misunderstanding: you want to ignore the remaining input until the newline character (and you don't know how many characters that will be). This is independent of the length of fullname. You could also have written:
    Code:
    cin.ignore(sizeof("Tears of the stars"), '\n');
    and it would have made just as much sense (or be just as puzzling).
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 12
    Last Post: 11-24-2012, 04:10 AM
  2. How To Make Capital Letter To Small Capital Letter??
    By jason07 in forum C++ Programming
    Replies: 3
    Last Post: 10-10-2005, 04:37 PM
  3. Big Letter became small letter
    By cogeek in forum C Programming
    Replies: 27
    Last Post: 12-13-2004, 02:04 PM
  4. I got a letter from the IRS.
    By Cheeze-It in forum A Brief History of Cprogramming.com
    Replies: 10
    Last Post: 09-26-2002, 03:53 PM
  5. Letter
    By drdroid in forum C++ Programming
    Replies: 1
    Last Post: 02-27-2002, 09:12 PM

Tags for this Thread