Thread: The "cin"... proper way of using cin, tips, tricks...

  1. #1
    Registered User
    Join Date
    Jul 2008
    Posts
    44

    Post The "cin"... proper way of using cin, tips, tricks...

    So far, I know that cin >> lets me input to a variable of any type... is that correct?

    I'm not really sure what's the "proper" way of using cin... So, even though I'm programming C++, I tend to use some of "C's way" of inputting data...

    For example,

    - If I want to input to a string variable / character string array, I'd use:
    Code:
    fgets([varname], sizeof([varname]), stdin);
    - If I want to input to a character variable, I'd use:
    Code:
    [character variable] = getchar();
    - If I want to input to an integer variable, I'd use:
    Code:
    scanf("%i", &[variablename]);
    - If I want to input to a float / double variable, I'd use:
    Code:
    scanf("%f", &[variablename]);  // %lf for double
    - If I want to input [EDIT: "output" NOT input... lol] to a float / double variable WITH precision, I'd use:
    [EDIT: NEW CODE... -_+]
    Code:
    printf("The output: %.2f", [variablename]);  // %.2lf for double
    ...obviously that's not the C++ way, so I would like to ask you people how am I going to those stuffs above using the C++ way... are there any cin equivalent for that? Thanks in advance and God bless...
    Last edited by ShadeS_07; 04-17-2011 at 07:26 PM.

  2. #2
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    In general it's:
    Code:
    std::cin >> foo;
    no matter what foo is. The FAQ will teach you how to do strings and numbers. The rest I think you can figure out?

  3. #3
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by ShadeS_07 View Post
    So far, I know that cin >> lets me input to a variable of any type... is that correct?
    No, it is not.

    "cin >> whatever" can be used to input to a variable of a type for which an operator>> is defined.

    The standard library does define operator>>() for all basic types (int, double, char, etc) and for a number of types (eg std::string) in the standard library. If the programmer wants a user defined type (a struct/class or, more rarely, an enum type) to have such support, then the programmer needs to define it.
    Quote Originally Posted by ShadeS_07 View Post
    I'm not really sure what's the "proper" way of using cin... So, even though I'm programming C++, I tend to use some of "C's way" of inputting data...
    That means you are really using C++ as "C with extensions". There is nothing inherently wrong with that, but what you are doing is probably only touching the surface of what you can do in C++. You are probably writing code that would be considered quite bad style - or possibly even inferior - by most C++ programmers. Note that these notions of "bad style" or "inferior" are subjective. Common practice - which is really what your question is about - in C++ is different from common practice in C.

    Anyway, just as there is no "proper" way of doing C I/O, there is no "proper" way of doing C++ I/O. Technically, it is possible to use C I/O in C++, but it is also actively discouraged as it is a good way to make mistakes, particularly if C I/O and C++ I/O are both used in the one program.

    What I'll do is give some possible ways of doing the things you ask. They are not the only ways, or even necessarily the best ways. C and C++ libraries both provide toolboxes, and we mortal programmers select tools out of toolboxes for any given task. Different programmers will prefer different tools.

    Note also that I never employ "using namespace std;" in production code. So I always refer to cin by its full and unambiguous name of std::cin.
    Quote Originally Posted by ShadeS_07 View Post
    - If I want to input to a string variable / character string array, I'd use:
    Code:
    fgets([varname], sizeof([varname]), stdin);
    Assuming you want to work with C-style strings (by convention an array of char terminated by a nul character) you might do this
    Code:
        std::cin.getline(varname), sizeof(varname));
    Note that, as in C, there is a distinction between a pointer and an array, so the above will not work if given an arbitrary char pointer.

    In C++, there is a better way, if you move away from the C notion of a string. If you use
    Code:
        std::string  varname;
    
        getline(std::cin, varname);
    an entire line of input (up to the carriage return) is input, and the string is resized as needed to hold it. No possibility of getting the size wrong, as the programmer does not specify the size.

    I would encourage this approach, although it does cause some headaches for C programmers, as there are some minor anomalies in how std::string interacts with C-style strings and string literals.
    Quote Originally Posted by ShadeS_07 View Post
    - If I want to input to a character variable, I'd use:
    Code:
    [character variable] = getchar();
    Strictly speaking, I wouldn't use the above in C either, as getchar() returns an int, not a char. Converting it directly to a char prevents error checking (for example, detecting EOF). In C, I'd actually do
    Code:
    [int variable] = getchar();
    if ([int variable] != EOF)
        [char variable] = [int variable];
    else
        complain_bitterly();
    The literal C++ equivalent of this is
    Code:
    [int variable] = std::cin.get();
    if ([int variable] != EOF)
        [char variable] = [int variable];
    else
        complain_bitterly();
    And an alternative is
    Code:
    std::cin.get([char variable]);
    if (!std::cin)           // Test state of the stream
        complain_bitterly();
    Quote Originally Posted by ShadeS_07 View Post
    - If I want to input to an integer variable, I'd use:
    Code:
    scanf("%i", &[variablename]);
    - If I want to input to a float / double variable, I'd use:
    Code:
    scanf("%f", &[variablename]);  // %lf for double
    In both of the above
    Code:
        cin >> [variablename];
    This works as the compiler knows what type variablename is, and calls the appropriate operator>>(). This obviously only works for types for which an operator>>() is defined.
    Quote Originally Posted by ShadeS_07 View Post
    - If I want to input to a float / double variable WITH precision, I'd use:
    Code:
    scanf("%.2f", &[variablename]);  // %.2lf for double
    Personally, I would never do that in C (better to make output a fixed precision, but input using a permissive format, as that allows the user more flexibility). However, the literal equivalent is;
    Code:
        std::cin >> set::setprecision(2) >> [variablename];
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  4. #4
    Registered User
    Join Date
    Jul 2008
    Posts
    44

    Lightbulb Thank you!

    Wow, thank you very much for the detailed response...

    And yeah, I'm talking about styles.... ~Proper styles.... -_+

    However, I still have questions regarding your post:

    That red parenthesis shouldn't be there, right?
    Code:
    std::cin.getline(varname), sizeof(varname));
    Is this the proper syntax?
    Code:
    std::cin.getline(varname, sizeof(varname));





    Quote Originally Posted by grumpy
    Personally, I would never do that in C (better to make output a fixed precision, but input using a permissive format, as that allows the user more flexibility). However, the literal equivalent is;
    Oh yeah, sorry about that, what I meant was output precision... in C++

    So how is it done in C++...? btw, the code above in my first post has already been edited/updated.

    C:
    Code:
    printf("The output: %.2f", variablename); //%.2lf for double
    C++
    Code:
    ?? :)
    Thanks again and God bless...

  5. #5
    Registered User
    Join Date
    Jun 2005
    Posts
    6,815
    Quote Originally Posted by ShadeS_07 View Post
    That red parenthesis shouldn't be there, right?
    That is a typo in my post; any code I provide in posts is written to illustrate a concept - I don't guarantee the absence of unintended errors.

    Quote Originally Posted by ShadeS_07 View Post
    Code:
    printf("The output: %.2f", variablename); //%.2lf for double
    C++
    Code:
    ?? :)
    One way is;
    Code:
       std::cout << "The output: " << std::setprecision(2) << variablename;
    This works whether variablename's type is float or double.
    Last edited by grumpy; 04-17-2011 at 09:47 PM.
    Right 98% of the time, and don't care about the other 3%.

    If I seem grumpy or unhelpful in reply to you, or tell you you need to demonstrate more effort before you can expect help, it is likely you deserve it. Suck it up, Buttercup, and read this, this, and this before posting again.

  6. #6
    Lurking whiteflags's Avatar
    Join Date
    Apr 2006
    Location
    United States
    Posts
    9,612
    Formatting input/output can be a chore. Here's a small demonstration of what it's like:
    Code:
    C:\Documents and Settings\Owner>test
    messing with a_float:
    1.
    1.3e+000
    1.3333
    1.33
    messing with a_int:
    0x2a
    052
    00052
    default a_float: 1.33333
    default a_int: 42
    
    C:\Documents and Settings\Owner>more test.cpp
    #include <iostream>
    #include <iomanip>
    
    int main ( )
    {
      std::ios_base::fmtflags oldflags = std::cout.flags();
      std::streamsize oldprec = std::cout.precision();
    
      float a_float = 4.0f / 3.0f;
      std::cout << "messing with a_float:" << std::endl;
      std::cout << std::showpoint << std::setprecision( 1 ) << a_float << std::endl;
      std::cout << std::scientific << a_float << std::endl;
      std::cout << std::fixed << std::setprecision( 4 ) << a_float << std::endl;
      std::cout << std::setprecision( 2 ) << a_float << std::endl;
    
      int a_int = 42;
      std::cout << "messing with a_int:" << std::endl;
      std::cout << std::showbase;
      std::cout << std::hex << a_int << std::endl;
      std::cout << std::oct << a_int << std::endl;
      std::cout << std::setfill('0') << std::setw(5) << a_int << std::endl;
    
      // Always reset things when you're done.
      std::cout.flags( oldflags );
      std::cout.precision( oldprec );
      std::cout << "default a_float: " << a_float <<  std::endl;
      std::cout << "default a_int: " << a_int << std::endl;
    
      return 0;
    }
    Of course, the demonstration should be equally applicable to other types of numbers. And I didn't demonstrate anything with strings although personally I never do more than dump them pretty much unformatted anyway.

    The objects inserted into streams to manipulate things are given the inventive name of manipulators. A pretty complete listing of standard ones is here: manipulators - C++ Reference

    If you actually go through that reference, you'll start looking into other things like ios_base, the class that standard streams are based on. You'll find a lot of member functions there that duplicate functionality. In my example though, I show you something with them that without them would be annoying, TBH. And you have to fix the stream when you're done if you ever want a 'normal' stream again, because some changes, like precision or base, are persistent, and others, like width, are applied once to a particular object.

    Welcome to a rather dark corner of C++ programming. Bjarne apologizes.
    Last edited by whiteflags; 04-17-2011 at 10:29 PM.

  7. #7
    Registered User
    Join Date
    Jul 2008
    Posts
    44
    Thanks everyone...

    Btw, do I have to include iomanip if I'm going to use std::setprecision()?


    And...,

    Can I also do something like this...? :

    Code:
    std::setprecision(8.2)
    Just like the way I do it in C:

    Code:
    printf("OUTPUT: %8.2f", varname);
    Cheers!

  8. #8
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by ShadeS_07
    Can I also do something like this...?
    Use Boost.Format, which can help alleviate the "formatting input/output can be a chore" thing.
    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

  9. #9
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Boost's Format documentation is poor at best, though, so it doesn't really help.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 9
    Last Post: 03-31-2009, 04:23 PM
  2. "itoa"-"_itoa" , "inp"-"_inp", Why some functions have "
    By L.O.K. in forum Windows Programming
    Replies: 5
    Last Post: 12-08-2002, 08:25 AM
  3. "CWnd"-"HWnd","CBitmap"-"HBitmap"...., What is mean by "
    By L.O.K. in forum Windows Programming
    Replies: 2
    Last Post: 12-04-2002, 07:59 AM