cin, iostream problems

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Christopher

    cin, iostream problems

    I am trying to get a line from the user which could be anything, I am
    expecting either a string followed by a whitespace or just a string by
    itself. I have tryed using string::getline , stringstreams, and all
    sorts of cin variations and can't get it right. Currently my program
    stops, waiting for more input in the case the user just enters a
    command with no argument, in this block of code. How can I fix it up?

    void Menu()
    {
    string command;
    int argument;

    string::size_ty pe index = string::npos;

    while(command != "quit")
    {
    cout<<"\nThe Following are valid commands:\n";
    cout<<"read_all <number> -- display entire mail header and body.\n";
    cout<<"read <number> -- display body of message\n";
    cout<<"del <number> -- delete message\n";
    cout<<"undel -- undo all deletion\n";
    cout<<"reply <number> -- reply to message\n";
    cout<<"list <number> -- display the next 10 message
    summaries\n";
    cout<<"quit -- exit this program\n\n";

    cin>>command;

    if(!(cin>>argum ent))
    argument = 0;

    cin.clear();
    cin.ignore(std: :numeric_limits <std::streamsiz e>::max(), '\n');

    if(command == "read_all")
    cout<<"not implemented\n";

    else if(command == "read")
    cout<<"not implemented\n";

    else if(command == "del")
    cout<<"not implemented\n";

    else if(command == "undel")
    cout<<"not implemented\n";

    else if(command == "reply")
    cout<<"not implemented\n";

    else if(command == "list")
    cout<<"not implemented\n";
    }
    }

    Thanks,
    Christopher
  • Leor Zolman

    #2
    Re: cin, iostream problems

    On 29 Apr 2004 15:24:55 -0700, cp1119@swt.edu (Christopher) wrote:
    [color=blue]
    >I am trying to get a line from the user which could be anything, I am
    >expecting either a string followed by a whitespace or just a string by
    >itself. I have tryed using string::getline , stringstreams, and all
    >sorts of cin variations and can't get it right. Currently my program
    >stops, waiting for more input in the case the user just enters a
    >command with no argument, in this block of code. How can I fix it up?[/color]

    It is stopping and waiting for an argument after any initial command, even
    the ones that don't take an argument. This can be remedied easily enough by
    simply modifying your logic to treat commands with args differently from
    those without args. Here's a step in the right direction (but there are
    still flaws, which I'll mention afterwards):

    #include <iostream>
    #include <string>
    using namespace std;

    void Menu()
    {
    string command;
    int argument;

    // string::size_ty pe index = string::npos;

    while(command != "quit")
    {
    cout<<"\nThe Following are valid commands:\n";
    cout<<"read_all <number> -- display entire mail header and
    body.\n";
    cout<<"read <number> -- display body of message\n";
    cout<<"del <number> -- delete message\n";
    cout<<"undel -- undo all deletion\n";
    cout<<"reply <number> -- reply to message\n";
    cout<<"list <number> -- display the next 10 message
    summaries\n";
    cout<<"quit -- exit this program\n\n";

    cin>>command;

    if(command == "undel")
    cout<<"not implemented\n";
    else if(command == "quit")
    return;
    else
    {
    if(!(cin>>argum ent))
    argument = 0;

    cin.clear();
    cin.ignore(std: :numeric_limits <std::streamsiz e>::max(), '\n');

    if(command == "read_all")
    cout<<"not implemented\n";

    else if(command == "read")
    cout<<"not implemented\n";

    else if(command == "del")
    cout<<"not implemented\n";

    else if(command == "reply")
    cout<<"not implemented\n";

    else if(command == "list")
    cout<<"not implemented\n";

    else
    cout << "Invalid command!\n";

    }
    }
    }


    int main()
    {
    Menu();
    return 0;
    }


    The problem now is that if the user enters an invalid command, it'll still
    wait for that arg before diagnosing it. If it were me, I'd manually deal
    with the arg for each case that requires it. You'll have more lines of
    code, but at least it'll be straight-forward. Alternatively, you can
    process just the command name by calling a function that matches it to a
    valid string (perhaps returning an enum representing the command), and that
    also categorizes the command as taking or not taking an arg (perhaps via a
    bool reference argument the function sets). Then you'd just check that
    bool's value after the call to find out whether or not to attempt to
    consume an argument.
    -leor



    --
    Leor Zolman --- BD Software --- www.bdsoft.com
    On-Site Training in C/C++, Java, Perl and Unix
    C++ users: download BD Software's free STL Error Message Decryptor at:
    An STL Error Decryptor for C++ by Leor Zolman of BD Software - available to download here

    Comment

    • Christopher

      #3
      Re: cin, iostream problems


      "Leor Zolman" <leor@bdsoft.co m> wrote in message
      news:0b33901cko 6op6miceqoeab3k ulk8861rk@4ax.c om...[color=blue]
      > On 29 Apr 2004 15:24:55 -0700, cp1119@swt.edu (Christopher) wrote:
      >[color=green]
      > >I am trying to get a line from the user which could be anything, I am
      > >expecting either a string followed by a whitespace or just a string by
      > >itself. I have tryed using string::getline , stringstreams, and all
      > >sorts of cin variations and can't get it right. Currently my program
      > >stops, waiting for more input in the case the user just enters a
      > >command with no argument, in this block of code. How can I fix it up?[/color]
      >
      > It is stopping and waiting for an argument after any initial command, even
      > the ones that don't take an argument. This can be remedied easily enough[/color]
      by[color=blue]
      > simply modifying your logic to treat commands with args differently from
      > those without args. Here's a step in the right direction (but there are
      > still flaws, which I'll mention afterwards):
      >
      > #include <iostream>
      > #include <string>
      > using namespace std;
      >
      > void Menu()
      > {
      > string command;
      > int argument;
      >
      > // string::size_ty pe index = string::npos;
      >
      > while(command != "quit")
      > {
      > cout<<"\nThe Following are valid commands:\n";
      > cout<<"read_all <number> -- display entire mail header and
      > body.\n";
      > cout<<"read <number> -- display body of message\n";
      > cout<<"del <number> -- delete message\n";
      > cout<<"undel -- undo all deletion\n";
      > cout<<"reply <number> -- reply to message\n";
      > cout<<"list <number> -- display the next 10 message
      > summaries\n";
      > cout<<"quit -- exit this program\n\n";
      >
      > cin>>command;
      >
      > if(command == "undel")
      > cout<<"not implemented\n";
      > else if(command == "quit")
      > return;
      > else
      > {
      > if(!(cin>>argum ent))
      > argument = 0;
      >
      > cin.clear();
      > cin.ignore(std: :numeric_limits <std::streamsiz e>::max(), '\n');
      >
      > if(command == "read_all")
      > cout<<"not implemented\n";
      >
      > else if(command == "read")
      > cout<<"not implemented\n";
      >
      > else if(command == "del")
      > cout<<"not implemented\n";
      >
      > else if(command == "reply")
      > cout<<"not implemented\n";
      >
      > else if(command == "list")
      > cout<<"not implemented\n";
      >
      > else
      > cout << "Invalid command!\n";
      >
      > }
      > }
      > }
      >
      >
      > int main()
      > {
      > Menu();
      > return 0;
      > }
      >
      >
      > The problem now is that if the user enters an invalid command, it'll still
      > wait for that arg before diagnosing it.[/color]

      Yea I tryed that way and that's why I tossed it out
      ..[color=blue]
      > If it were me, I'd manually deal
      > with the arg for each case that requires it. You'll have more lines of
      > code, but at least it'll be straight-forward.[/color]

      I'd love to and that's the way I would normally do it, but the instructor
      won't accept that. He wants us to parse a line of input like it was 1970.
      I'd use a char array and do it the old fashion way but I hate c style
      strings and would much rather find out if there is a way to tell if
      something
      is sitting in the cin stream then stick it into the argument variable if it
      exists in a c++ fashion.
      [color=blue]
      >Alternativel y, you can
      > process just the command name by calling a function that matches it to a
      > valid string (perhaps returning an enum representing the command), and[/color]
      that[color=blue]
      > also categorizes the command as taking or not taking an arg (perhaps via a
      > bool reference argument the function sets). Then you'd just check that
      > bool's value after the call to find out whether or not to attempt to
      > consume an argument.
      > -leor[/color]

      It would still hang if the user was dumb and didn't enter an argument. I am
      aiming for getting the whole line
      and then seeing if an argument exists when it should and if it isn't or it
      isn't a number then giving an error message.

      Appreciate the input though,
      Chris


      Comment

      • Leor Zolman

        #4
        Re: cin, iostream problems

        On Fri, 30 Apr 2004 00:03:15 GMT, "Christophe r" <anon@nospam.ne t> wrote:

        [color=blue][color=green]
        >> If it were me, I'd manually deal
        >> with the arg for each case that requires it. You'll have more lines of
        >> code, but at least it'll be straight-forward.[/color]
        >
        >I'd love to and that's the way I would normally do it, but the instructor
        >won't accept that. He wants us to parse a line of input like it was 1970.
        >I'd use a char array and do it the old fashion way but I hate c style
        >strings and would much rather find out if there is a way to tell if
        >something
        >is sitting in the cin stream then stick it into the argument variable if it
        >exists in a c++ fashion.[/color]

        If you want to do it like "1970", (well, 1980 more likely, at least if
        you're not Dennis Ritchie...) then "think fgets and sscanf", but do it with
        iostreams! Just read the entire line into a std::string using getline, and
        start analyzing after it has been input. You can use <sstream> facilities
        to create an istringstream from the input string, then just extract from
        that and test the stream state after each extraction.
        Good luck,
        -leor


        --
        Leor Zolman --- BD Software --- www.bdsoft.com
        On-Site Training in C/C++, Java, Perl and Unix
        C++ users: download BD Software's free STL Error Message Decryptor at:
        An STL Error Decryptor for C++ by Leor Zolman of BD Software - available to download here

        Comment

        • Christopher

          #5
          Re: cin, iostream problems


          "Leor Zolman" <leor@bdsoft.co m> wrote in message
          news:ko63901apd dhmcnq3ilmm8ft4 qielnnh13@4ax.c om...[color=blue]
          > On Fri, 30 Apr 2004 00:03:15 GMT, "Christophe r" <anon@nospam.ne t> wrote:
          >
          >[color=green][color=darkred]
          > >> If it were me, I'd manually deal
          > >> with the arg for each case that requires it. You'll have more lines of
          > >> code, but at least it'll be straight-forward.[/color]
          > >
          > >I'd love to and that's the way I would normally do it, but the instructor
          > >won't accept that. He wants us to parse a line of input like it was 1970.
          > >I'd use a char array and do it the old fashion way but I hate c style
          > >strings and would much rather find out if there is a way to tell if
          > >something
          > >is sitting in the cin stream then stick it into the argument variable if[/color][/color]
          it[color=blue][color=green]
          > >exists in a c++ fashion.[/color]
          >
          > If you want to do it like "1970", (well, 1980 more likely, at least if
          > you're not Dennis Ritchie...) then "think fgets and sscanf", but do it[/color]
          with[color=blue]
          > iostreams! Just read the entire line into a std::string using getline, and
          > start analyzing after it has been input. You can use <sstream> facilities
          > to create an istringstream from the input string, then just extract from
          > that and test the stream state after each extraction.
          > Good luck,
          > -leor
          >
          >
          > --
          > Leor Zolman --- BD Software --- www.bdsoft.com
          > On-Site Training in C/C++, Java, Perl and Unix
          > C++ users: download BD Software's free STL Error Message Decryptor at:
          > www.bdsoft.com/tools/stlfilt.html[/color]

          Well here is my attempt. I don't understand why if I put cin.clear();
          cin.ignore(std: :numeric_limits ::max(),'\n'); after the input that i have to
          hit enter twice.
          I thought I had to put that after using the instream to make sure there
          wasn't any garbage left for the next function who wants to use it. So I took
          it out.
          Here is my code, please make any suggestions that would make it better and
          more standard like:
          void Menu()
          {
          string command;
          int argument;
          while(true)
          {
          cout<<"\nThe Following are valid commands:\n";
          cout<<"read_all <number> -- display entire mail header and body.\n";
          cout<<"read <number> -- display body of message\n";
          cout<<"del <number> -- delete message\n";
          cout<<"undel -- undo all deletion\n";
          cout<<"reply <number> -- reply to message\n";
          cout<<"list <number> -- display the next 10 message summaries\n";
          cout<<"quit -- exit this program\n\n";
          getline(cin, command, '\n');
          // Extract command and argument
          stringstream temp(command);
          temp>>command;
          if(!(temp>>argu ment))
          argument = 0;
          // Check for valid commands and perform them
          if(command == "read_all" && argument)
          cout<<"not implemented\n";
          else if(command == "read" && argument)
          cout<<"not implemented\n";
          else if(command == "del" && argument)
          cout<<"not implemented\n";
          else if(command == "undel")
          cout<<"not implemented\n";
          else if(command == "reply" && argument)
          cout<<"not implemented\n";
          else if(command == "list" && argument)
          cout<<"not implemented\n";
          else if(command == "quit")
          break;
          else
          cout<<"\nInvali d command or argument\n";
          }
          }

          sorry my email client hates tabs for some reason, but I think it's still
          readable.
          Thanks,.
          Chris


          Comment

          • Leor Zolman

            #6
            Re: cin, iostream problems

            On Fri, 30 Apr 2004 01:16:59 GMT, "Christophe r" <anon@nospam.ne t> wrote:
            [color=blue]
            >Well here is my attempt. I don't understand why if I put cin.clear();
            >cin.ignore(std ::numeric_limit s::max(),'\n'); after the input that i have to
            >hit enter twice.
            >I thought I had to put that after using the instream to make sure there
            >wasn't any garbage left for the next function who wants to use it. So I took
            >it out.[/color]

            Why bother clearing the input? You've read in an entire line, you're
            processing it, and the next time 'round you're getting an entirely new
            line...so it doesn't really matter if there are items remaining on the
            previous line or not. If you weren't reading an entire line at a time, but
            extracting directly from cin instead of from the stringstream , then you'd
            need to worry about extraneous characters. In that case, I've seen various
            posts showing elaborate ways of doing it, but so far I've done OK just
            reading characters until I encounter a newline. YMMV.

            (And by the way, istringstream seems as if might be a better fit to your
            context than stringstream, since you're just using it for input.)

            Other than that, what you have looks OK to me. When you post in the future,
            though, please consider posting a complete program, with headers and a
            driver, as I did in my post. It's just a way of being considerate to folks
            who're inclined to fire up your code; in fact, it would be likely to make
            them more inclined.

            And newsreaders are weird about tabs. When I copied and pasted your code,
            it came up in my editor with all the tabs intact and looking mighty purdy.
            What I do personally when posting code, though, is use an Epsilon keystroke
            macro I wrote to "untabify" code, put the result into the clipboard, and
            then re-tabify it in my editor's buffer. Then I just paste the untabified
            code into the body of my post. Now all I have to do is to remember to hit
            that magic key instead of doing the usual mark-and-copy dance. I've been
            doing well, since the keystroke macro is easier than the dance ;-)
            -leor
            [color=blue]
            >Here is my code, please make any suggestions that would make it better and
            >more standard like:
            >void Menu()
            >{
            >string command;
            >int argument;
            >while(true)
            >{
            >cout<<"\nThe Following are valid commands:\n";
            >cout<<"read_al l <number> -- display entire mail header and body.\n";
            >cout<<"read <number> -- display body of message\n";
            >cout<<"del <number> -- delete message\n";
            >cout<<"undel -- undo all deletion\n";
            >cout<<"reply <number> -- reply to message\n";
            >cout<<"list <number> -- display the next 10 message summaries\n";
            >cout<<"quit -- exit this program\n\n";
            >getline(cin, command, '\n');
            >// Extract command and argument
            >stringstream temp(command);
            >temp>>comman d;
            >if(!(temp>>arg ument))
            >argument = 0;
            >// Check for valid commands and perform them
            >if(command == "read_all" && argument)
            >cout<<"not implemented\n";
            >else if(command == "read" && argument)
            >cout<<"not implemented\n";
            >else if(command == "del" && argument)
            >cout<<"not implemented\n";
            >else if(command == "undel")
            >cout<<"not implemented\n";
            >else if(command == "reply" && argument)
            >cout<<"not implemented\n";
            >else if(command == "list" && argument)
            >cout<<"not implemented\n";
            >else if(command == "quit")
            >break;
            >else
            >cout<<"\nInval id command or argument\n";
            >}
            >}
            >
            >sorry my email client hates tabs for some reason, but I think it's still
            >readable.
            >Thanks,.
            >Chris
            >[/color]

            --
            Leor Zolman --- BD Software --- www.bdsoft.com
            On-Site Training in C/C++, Java, Perl and Unix
            C++ users: download BD Software's free STL Error Message Decryptor at:
            An STL Error Decryptor for C++ by Leor Zolman of BD Software - available to download here

            Comment

            • Leor Zolman

              #7
              Re: cin, iostream problems

              [color=blue]
              >And newsreaders are weird about tabs. When I copied and pasted your code,
              >it came up in my editor with all the tabs intact and looking mighty purdy.[/color]

              Well, I just figured out why /that/ happened. As I mentioned, I use
              Epsilon; it auto-formatted the code for me because it knew I was editing a
              C++ document. I just didn't realize it did that upon text pasted in from
              the clipboard... I do like Epsilon a lot ;-)
              -leor

              --
              Leor Zolman --- BD Software --- www.bdsoft.com
              On-Site Training in C/C++, Java, Perl and Unix
              C++ users: download BD Software's free STL Error Message Decryptor at:
              An STL Error Decryptor for C++ by Leor Zolman of BD Software - available to download here

              Comment

              • John Harrison

                #8
                Re: cin, iostream problems

                >[color=blue]
                > Well here is my attempt. I don't understand why if I put cin.clear();
                > cin.ignore(std: :numeric_limits ::max(),'\n'); after the input that i have[/color]
                to[color=blue]
                > hit enter twice.[/color]

                Because cin.ignore(std: :numeric_limits ::max(),'\n'); means ignore input upto
                the next newline. If there is no newline pending then you are going to have
                to input another.

                john


                Comment

                • Siemel Naran

                  #9
                  Re: cin, iostream problems

                  "Christophe r" <cp1119@swt.edu > wrote in message
                  [color=blue]
                  > cout<<"\nThe Following are valid commands:\n";
                  > cout<<"read_all <number> -- display entire mail header and body.\n";
                  > cout<<"read <number> -- display body of message\n";
                  > cout<<"del <number> -- delete message\n";
                  > cout<<"undel -- undo all deletion\n";
                  > cout<<"reply <number> -- reply to message\n";
                  > cout<<"list <number> -- display the next 10 message
                  > summaries\n";
                  > cout<<"quit -- exit this program\n\n";
                  >
                  > cin>>command;
                  > if(!(cin>>argum ent))[/color]

                  One solution is to use cin.getline to read into a string one line terminated
                  by a newline character. Then use istringstream to parse the command and
                  command line arguments.

                  std::string linestring;
                  getline(std::ci n, linestring);
                  std::istringstr eam line(linestring );
                  line >> command >> argument;


                  Comment

                  • Dave Moore

                    #10
                    Re: cin, iostream problems

                    "Siemel Naran" <SiemelNaran@RE MOVE.att.net> wrote in message news:<38mkc.635 6$Xj6.103462@bg tnsc04-news.ops.worldn et.att.net>...[color=blue]
                    > "Christophe r" <cp1119@swt.edu > wrote in message
                    >[color=green]
                    > > cout<<"\nThe Following are valid commands:\n";
                    > > cout<<"read_all <number> -- display entire mail header and body.\n";
                    > > cout<<"read <number> -- display body of message\n";
                    > > cout<<"del <number> -- delete message\n";
                    > > cout<<"undel -- undo all deletion\n";
                    > > cout<<"reply <number> -- reply to message\n";
                    > > cout<<"list <number> -- display the next 10 message
                    > > summaries\n";
                    > > cout<<"quit -- exit this program\n\n";
                    > >
                    > > cin>>command;
                    > > if(!(cin>>argum ent))[/color]
                    >
                    > One solution is to use cin.getline to read into a string one line terminated
                    > by a newline character. Then use istringstream to parse the command and
                    > command line arguments.
                    >
                    > std::string linestring;
                    > getline(std::ci n, linestring);
                    > std::istringstr eam line(linestring );
                    > line >> command >> argument;[/color]

                    Even better, the OP can easily get the behavior he wants (i.e. reading
                    variable arguments) by checking the state of the istringstream between
                    the operator>> calls. However, I posted such a solution the last time
                    he asked this question,



                    so I guess that is not what he wants.

                    Dave Moore

                    Comment

                    • Christopher

                      #11
                      Re: cin, iostream problems


                      "Dave Moore" <dtmoore@rijnh. nl> wrote in message
                      news:306d400f.0 404300247.1ba26 821@posting.goo gle.com...[color=blue]
                      > "Siemel Naran" <SiemelNaran@RE MOVE.att.net> wrote in message[/color]
                      news:<38mkc.635 6$Xj6.103462@bg tnsc04-news.ops.worldn et.att.net>...[color=blue][color=green]
                      > > "Christophe r" <cp1119@swt.edu > wrote in message
                      > >[color=darkred]
                      > > > cout<<"\nThe Following are valid commands:\n";
                      > > > cout<<"read_all <number> -- display entire mail header and body.\n";
                      > > > cout<<"read <number> -- display body of message\n";
                      > > > cout<<"del <number> -- delete message\n";
                      > > > cout<<"undel -- undo all deletion\n";
                      > > > cout<<"reply <number> -- reply to message\n";
                      > > > cout<<"list <number> -- display the next 10 message
                      > > > summaries\n";
                      > > > cout<<"quit -- exit this program\n\n";
                      > > >
                      > > > cin>>command;
                      > > > if(!(cin>>argum ent))[/color]
                      > >
                      > > One solution is to use cin.getline to read into a string one line[/color][/color]
                      terminated[color=blue][color=green]
                      > > by a newline character. Then use istringstream to parse the command and
                      > > command line arguments.
                      > >
                      > > std::string linestring;
                      > > getline(std::ci n, linestring);
                      > > std::istringstr eam line(linestring );
                      > > line >> command >> argument;[/color]
                      >
                      > Even better, the OP can easily get the behavior he wants (i.e. reading
                      > variable arguments) by checking the state of the istringstream between
                      > the operator>> calls. However, I posted such a solution the last time
                      > he asked this question,
                      >
                      >[/color]
                      http://groups.google.com/groups?hl=e...ing.google.com[color=blue]
                      >
                      > so I guess that is not what he wants.
                      >
                      > Dave Moore[/color]

                      It really was and that's what I ended up doing. Problem was when I tryed it
                      the first time, evidently there was a problem with the way I was testing the
                      output and it made it appear as if it wasn't working. It wasn't until I
                      tryed it every other way possible that I came back around and did it again
                      to find that it did indeed work the way I wanted. Lesson learned: don't
                      concentrate so much on the problem so much that you forget how your testing
                      the solution.
                      Thanks,
                      Chris


                      Comment

                      Working...