string to char

This is a discussion on string to char within the C++ Programming forums, part of the General Programming Boards category; Code: string verify; char yn; cin >> verify; string subverify = verify.substr(0,1); // yn = subverify --how? Once I accept ...

  1. #1
    SRS
    SRS is offline
    3rd Week In C++ SRS's Avatar
    Join Date
    Nov 2007
    Posts
    22

    string to char

    Code:
    string verify;
    char yn;
    cin >> verify;
    string subverify = verify.substr(0,1);
    // yn = subverify --how?
    Once I accept user input (string verify) what would be the best way to assign the substring to char yn?
    Basically this was a way to accept ANY user input, and then use (tolower(subverify)) on the char prior to the conditional...

    I found another (better) way to do what I wanted to but the question remains unanswered, how would I have done this typecasted assignment from subverify to yn?
    Maybe there is a way to initialize char yn with a the value in subverify? or other shorter method with a totally different setup than above?

  2. #2
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    If you want to copy the first character in the verify string into yn, use operator[] to get that character:
    Code:
    cin >> verify;
    yn = verify[0];
    You might want to add code to make sure verify is not empty. It might crash if it is empty and you don't check.

  3. #3
    and the hat of sweating
    Join Date
    Aug 2007
    Location
    Toronto, ON
    Posts
    3,545
    Quote Originally Posted by Daved View Post
    If you want to copy the first character in the verify string into yn, use operator[] to get that character:
    Code:
    cin >> verify;
    yn = verify[0];
    You might want to add code to make sure verify is not empty. It might crash if it is empty and you don't check.
    If you use verify.at(0) instead of verify[0], it will throw an out_of_range exception if verify is empty.

    But why not just input directly into the yn char?

  4. #4
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    Actually, inputting directly into yn makes sense. You cannot overrun a single char. You can only overrun a buffer it is a C style string.

    You can ignore extra characters with a call to cin.ignore(1000, '\n') or whatever.

  5. #5
    SRS
    SRS is offline
    3rd Week In C++ SRS's Avatar
    Join Date
    Nov 2007
    Posts
    22

    Well...

    Quote Originally Posted by Daved View Post
    Actually, inputting directly into yn makes sense. You cannot overrun a single char. You can only overrun a buffer it is a C style string.

    You can ignore extra characters with a call to cin.ignore(1000, '\n') or whatever.
    I tried that, or so I think

    Code:
    char yn;
    cin >> yn;
    and what happened if the user input more than one character, the remaining characters were entered to firstName and ran right down to input lastName...

    My answer was to accept longer than single char input, and omit anything after the first character. Is there a way to force only a single character input? What other ways would you suggest? Remember this is merely for learning, so any different way you know of to perform this task, for better or for worse, please feel free to post it and as many details as you feel the desire to go with it. Thanks again.

  6. #6
    Registered User
    Join Date
    May 2007
    Posts
    77
    SRS is right, I ran into that myself with my guessing game program. If you input any more characters that it takes for one part, it automatically sends those characters to the next input requirement. However, I figured this out:
    Code:
    char verify[20];
    char yn;
    cin >> verify;
    yn = verify[0];
    And on the surface, it works. You can probably set "20" to whatever number you need to make sure it takes all of what the user puts in. And to make sure it works, i just tested it by having the output be
    Code:
    cout << verify[0] << verify[1] << verify[2] << verify[3] << endl;
    And when I put in a 7 letter word, it printed the first four back to me, and didn't seem to have a problem with the extras.

    Edit: And now that I think about it, you could probably just do it this way, and get rid of verify altogether, like cpjust and Daved suggested:
    Code:
    char yn[20];
    cin >> yn;
    With that, the first letter is automatically set to the first part of the "yn" character array, and you can just call "yn[0]" to get the first letter wherever you need it.
    Last edited by Molokai; 11-04-2007 at 11:47 PM.

  7. #7
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    As I said, read into the char variable, then ignore the rest of the line. That's what cin.ignore(1000, '\n') does. That way it won't spill over into the first name the next time you get input.

  8. #8
    Registered User
    Join Date
    May 2007
    Posts
    77
    Quote Originally Posted by Daved View Post
    As I said, read into the char variable, then ignore the rest of the line. That's what cin.ignore(1000, '\n') does. That way it won't spill over into the first name the next time you get input.
    You mean doing it like this?
    Code:
    char yn;
    cin >> yn;
    cin.ignore(1000,'\n');
    That works great too. That's probably the way it's meant to be done, but I like the fact that mine found a back door, as it were, to accomplish the same thing.

  9. #9
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    Yes, that's what I meant.

    There are all kinds of ways a user can mess up input by typing in things you don't expect. For the most robust program you should handle all of them. This is just handling one possible problem because it is more likely than others.

    The reason you read into the char variable and not the string is because that's what you want, a character. It's better to do what you want directly than to find a neat but not as obvious solution.

  10. #10
    SRS
    SRS is offline
    3rd Week In C++ SRS's Avatar
    Join Date
    Nov 2007
    Posts
    22

    Thanks so much

    Quote Originally Posted by Daved View Post
    For the most robust program you should handle all of them.
    Yes, this is the goal. As idiot proof as I can think of ways to make it.
    Open for other suggestions on that too...

    TYVM again both of you!!

  11. #11
    Registered User
    Join Date
    Jan 2005
    Posts
    7,340
    For console input you could use this header which should handle any user input errors. It makes it simple by just returning false on error and keeping cin in a good (and clear) state. Any extra input is considered an error, so if you ask for 'y' or 'n' but the user types "yes" it returns false.
    Code:
    //
    // basic_input.h
    //
    // Contains the declaration/definition of console input helper functions
    // that make basic console input easier for new C++ programmers.
    //
    // basic_input:
    //    template<typename charT, typename traits, typename T>
    //      inline bool basic_input(std::basic_istream<charT,traits>& is, T& x, charT delim)
    //    template<typename charT, typename traits, typename Allocator>
    //      inline bool basic_input(std::basic_istream<charT,traits>& is, std::basic_string<charT,traits,Allocator>& x, charT delim)
    //    template<typename charT, typename traits>
    //      inline bool basic_input(std::basic_istream<charT,traits>& is, charT* x, std::streamsize count, charT delim)
    //    template<typename charT, typename traits, typename T>
    //      inline bool basic_input(std::basic_istream<charT,traits>& is, T& x)
    //
    //  Returns:
    //    bool - true if the input succeeded, false otherwise.
    //
    //  Effects:
    //    This function attempts to read from the input stream into the passed in
    //    variable up to the specified delimiter. If the data in the stream does
    //    not match the expected format of the variable type, or if the character
    //    following the data read in is not the delimiter, then the input fails.
    //
    //    On success, the variable x contains the inputted value. On failure, the
    //    variable x is cleared (i.e. default-initialized).
    //
    //    On success or failure, the input stream is left in a good state and all
    //    characters up to and including the delimiter are removed from the stream.
    //
    //    The delimiter defaults to '\n' if not specified.
    //
    //    If the variable type is char* (or some other character pointer), and the
    //    delimiter has not yet been reached prior to count characters being read
    //    in, then the input has failed and the array pointed to by the char* will
    //    be filled with count characters set to null.
    //
    //  Sample usage:
    //    int i;
    //    std::cout << "Enter an int: ";
    //    while (!bip::basic_input(std::cin, i))
    //        std::cout << "Invalid int! Try again: ";
    //
    //
    // ignore_line:
    //    template<typename charT, typename traits>
    //    inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is, charT delim)
    //    template<typename charT, typename traits>
    //    inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is)
    //
    //  Returns:
    //    std::basic_istream<charT,traits>& - the stream passed in.
    //
    //  Effects:
    //    This function reads and discards all characters in the passed in input
    //    stream up to and including the first instance of the delimiter. The
    //    delimiter defaults to '\n' if not specified.
    //
    //  Sample usage:
    //    std::cout << "Press Enter to Close.\n";
    //    bip::ignore_line(std::cin);
    //
    
    #ifndef BASIC_INPUT_H_
    #define BASIC_INPUT_H_
    
    #include <istream>
    #include <ios>
    #include <string>
    #include <limits>
    
    namespace bip
    {
        template<typename charT, typename traits>
        inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is, charT delim)
        {
            return is.ignore(std::numeric_limits<std::streamsize>::max(), delim);
        }
    
        template<typename charT, typename traits>
        inline std::basic_istream<charT,traits>& ignore_line(std::basic_istream<charT,traits>& is)
        {
            return ignore_line(is, is.widen('\n'));
        }
    
        template<typename charT, typename traits, typename T>
        inline bool basic_input(std::basic_istream<charT,traits>& is, T& x, charT delim)
        {
            std::ios::fmtflags old_flags = is.flags();
            if ((is >> std::noskipws >> x) && (is.eof() || is.get() == delim))
            {
                is.flags(old_flags);
                return true;
            }
            is.flags(old_flags);
    
            x = T();
            is.clear();
            ignore_line(is, delim);
            return false;
        }
    
        template<typename charT, typename traits, typename Allocator>
        inline bool basic_input(std::basic_istream<charT,traits>& is, std::basic_string<charT,traits,Allocator>& x, charT delim)
        {
            if (std::getline(is, x, delim))
                return true;
    
            x.clear();
            is.clear();
            return false;
        }
    
        template<typename charT, typename traits>
        inline bool basic_input(std::basic_istream<charT,traits>& is, charT* x, std::streamsize count, charT delim)
        {
            if (is.getline(x, count, delim))
                return true;
    
            if (is.gcount()+1 < count)
                memset(x, charT(), count);
    
            is.clear();
            ignore_line(is, delim);
            return false;
        }
    
        template<typename charT, typename traits, typename T>
        inline bool basic_input(std::basic_istream<charT,traits>& is, T& x)
        {
            return basic_input(is, x, is.widen('\n'));
        }
    }
    
    #endif // BASIC_INPUT_H_
    Here is sample usage:
    Code:
    #include <iostream>
    #include <string>
    #include "basic_input.h"
    
    using namespace std;
    using namespace bip;
    
    int main()
    {
        // Reading integers
        int i;
        cout << "Enter an int: ";
        if (basic_input(cin, i))
            cout << "The number read in was: " << i << '\n';
        else
            cout << "Sorry, invalid int!" << '\n';
    
        // Reading doubles
        double d;
        cout << "Enter a double: ";
        while (!basic_input(cin, d))
        {
            cout << "Invalid double! Try again: ";
        }
        cout << "The double read in was: " << d << '\n';
    
        // Reading strings (one whole line at a time like getline)
        string s;
        cout << "Enter a line of text: ";
        basic_input(cin, s);
        cout << "The line of text read in was: " << s << '\n';
    
        // Pause the program
        cout << "Press Enter to Close.\n";
        ignore_line(cin);
    }

  12. #12
    SRS
    SRS is offline
    3rd Week In C++ SRS's Avatar
    Join Date
    Nov 2007
    Posts
    22

    YES!

    Very well! I will try to digest how all of that works and get back to you, but at a glance it seems to be more along the lines of what I am attempting to learn how to do, thank you SO MUCH for your time and effort in helping me.

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: 8
    Last Post: 04-25-2008, 02:45 PM
  3. String issues
    By The_professor in forum C++ Programming
    Replies: 7
    Last Post: 06-12-2007, 09:11 AM
  4. Linked List Help
    By CJ7Mudrover in forum C Programming
    Replies: 9
    Last Post: 03-10-2004, 09:33 PM
  5. comparing fields in a text file
    By darfader in forum C Programming
    Replies: 9
    Last Post: 08-22-2003, 08:21 AM

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