1

For my homework, I am using std::istringstream in order to create error messages when applicable.

My program works fine, except for two certain cases, it does not work properly.

The first test case is when the second number is zero and the first number is a number greater than zero.

The second test case is when the second number, n, is greater than the first number, m.

It should return the error message when n > m, but it goes straight to the result.

My question is, how exactly does std:::istringstream work? How does it compare the value in argv at this line? How can I fix my code so it checks the correct thing?

More specifically, what does this line do?

(!(iss >> m))

My teacher gave us this std::istringstream code in an earlier lab, however I believe that it is checking for only positive numbers, which is why it fails in the first test case I included. How can I fix this?

int main(int argc, char* argv[])
{
    unsigned int m;
    unsigned int n;
    //error checks
    istringstream iss;
    if(argc != 3) {
        cerr<< "Usage: " << argv[0] << " <integer m> <integer n>" << endl;
        return 1;
    }
    iss.str(argv[1]);
    if (!(iss >> m) ){
        cerr << "Error: The first argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    iss.clear();
    iss.str(argv[2]);
    if (!(iss >> n) ){
        cerr << "Error: The second argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    if (n > m){
        cerr << "Error: The second argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    //correct output
    cout << m << " x " << n << " = " << russian_peasant_multiplication(m, n) << endl;
    return 0;
}
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
Phil Cho
  • 131
  • 3
  • 14
  • 1
    `operator>>` sets the stream's `failbit` state if it can't perform the requested conversion. `!iss` evaluates to true if `iss` is in a bad/failure state. So, the statement `!(iss >> m)` checks if `iss` successfully extracted an `unsigned int` value to `m` or not (same with `!(iss >> n)` for `n`). 0 is a valid `unsigned int` value. Your code looks fine to me (though the text of your `n > m` error message is misleading), so you will have to provide an example of the input you are actually entering, and explain what output you are expecting from it, and what output you are actually getting. – Remy Lebeau Mar 23 '18 at 01:47

1 Answers1

0

This code doesn't check for non-negative integer numbers, hopefully this illustrates. I'll use the local array char* args[3] as the argument values.:

#include <iostream>
#include <string>
#include <sstream>

using namespace std;

int main(int argc, char* argv[])
{
    unsigned int m;
    unsigned int n;
    argc = 3;
    const char* args[3];
    args[1] = "-1";
    args[2] = "-2";

    istringstream iss;
    if (argc != 3) // Passes because argument count is 3 
    {
        cerr << "Usage: " << argv[0] << " <integer m> <integer n>" << endl;
        return 1;
    }

    iss.str(args[1]); // iss now holds "-1"

                      // istringstream operator >> will set either eofbit, failbit or badbit
                      // on failure. The iss object is convertible to bool so you can check
                      // in an if statement.

    if (!(iss >> m))  // Extracts "-1" into unsigned int m.
                      // m holds 4294967295 because it's unsigned.
                      // if statement doesn't fail because istringstream can 
                      // can extract into signed ints also
    {
        cerr << "Error: The first argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    iss.clear();
    iss.str(args[2]); // iss object now holds "-2"
    if (!(iss >> n))  // Same here, extraction into unsigned in doesn't fail
    {
        cerr << "Error: The second argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    if (n > m) // This checks if n > m, but still nowhere in the code have you
               // checked if the argv[] values are negative or positive values.
    {
        cerr << "Error: The second argument is not a valid nonnegative integer." << endl;
        return 1;
    }

    cout << m << " x " << n << " = " << endl;
    return 0;
}
Zebrafish
  • 11,682
  • 3
  • 43
  • 119
  • 1
    Modifying `argv`, especially before validating `argc`, is a bad example. Using a separate local array would have been a better choice. – Remy Lebeau Mar 23 '18 at 05:53
  • @RemyLebeau You're right. Thanks for letting me know. I've changed the example to use a separate local. – Zebrafish Mar 23 '18 at 06:46