2

I am currently working on a dynamic programming problem, and I decided code it in C++ instead of my usual Java/C# to improve my skills. However, I am getting an error that I cannot figure out. EDIT: I will post my entire solution here:

int main() {
    /* Enter your code here. Read input from STDIN. Print output to STDOUT */
    int linecounter = 0;
    int value = -1;
    int differentCoins = -1;
    int uniqueCoinCount = -1;
    std::vector<std::vector<int>> array;
    int *uniqueCoins;
    int totalAmount = -1;

    for (std::string line; std::getline(std::cin, line); ) {
        if (linecounter % 2 == 0) {
            string inputs[2];
            int i = 0;
            stringstream ssin(line);
            while (ssin.good() && i < 2){
                ssin >> inputs[i];
                ++i;
            }
            cout << inputs[0];
            cout << inputs[1];
            totalAmount = std::stoi(inputs[0]);
            uniqueCoinCount = std::stoi(inputs[1]);
            uniqueCoins = new int[uniqueCoinCount + 1];

        }
        if (linecounter % 2 == 1) {
            array.resize(uniqueCoinCount + 1, std::vector<int>(totalAmount + 1));
            for (int i = 0; i < totalAmount; i++) {
                array[i][0] = 0;
            }
            for (int i = 0; i <= uniqueCoinCount; i++) {
                array[0][i] = 1;
            }


            stringstream ssin(line);
            int coinCounter = 0;
            uniqueCoins[coinCounter] = 0;
            coinCounter++;
            while (ssin.good() && coinCounter < uniqueCoinCount + 1){

                ssin >> uniqueCoins[coinCounter];
                coinCounter++;
            }

            for (int i = 1; i < totalAmount; i++) {
                for (int j = 1; j <= uniqueCoinCount; j++) {
                    int totalExcludingCoin = array[i][j - 1];
                    if (uniqueCoins[j] <= i) {
                        array[i][j] = totalExcludingCoin + array[i - uniqueCoins[j]][j];
                    }
                    else {
                        array[i][j] = totalExcludingCoin;
                    }
                }
            }
        }
        linecounter++;
    }

    //cout << array[totalAmount][uniqueCoinCount + 1];
}

When I use cout << inputs[0], I can see that it prints out 4. However, the hackerrank compiler gives me an error saying

"terminate called after throwing an instance of 'std::invalid_argument'
what(): stoi"

What could be the problem? I've also tried atoi(), which returns me 40 instead of 4, possibly due to atoi returning 0 when it errors? Is it because it reads the null terminator or something?

Thanks

Here is the output on hackerrank:

Nice try, but you did not pass this test case.

Input (stdin)
4 3
1 2 3 

Your Output (stdout)
43

Expected Output
4

Compiler Message
Abort Called
Error (stderr)
terminate called after throwing an instance of 'std::invalid_argument'  
what():  stoi
Zereges
  • 4,833
  • 1
  • 20
  • 47
Arthur Lee
  • 161
  • 1
  • 2
  • 12
  • 3
    What are the contents of the strings? – Ilya Kogan Nov 21 '15 at 09:28
  • cout << inputs[0] returns "4" and cout < – Arthur Lee Nov 21 '15 at 09:30
  • 2
    Your loop exhibits the [istream::eof](http://stackoverflow.com/questions/5605125/why-is-iostreameof-inside-a-loop-condition-considered-wrong) bug, in thin disguise (using `good` instead of `!eof` as the loop condition). The loop should be `while ( ssin >> inputs[i] && ++i < 2 ) {}` (or a `for` loop) – M.M Nov 21 '15 at 10:55
  • Update the posted code to include the output statements you mentioned , and post the output (and verify that the exact posted code generates that output). Preferably post a [MCVE](http://stackoverflow.com/help/mcve). Your code is correct so most likely the problem is that `line` actually does not contain what you think it does , or has some non-printable characters or characters you aren't noticing. – M.M Nov 21 '15 at 10:58
  • You could hexdump `line` and look for strange characters – M.M Nov 21 '15 at 10:59
  • Also you should abort if both reads didn't succeed (if you use my suggested loop, then `if ( i != 2 ) { errorhandling...` – M.M Nov 21 '15 at 10:59
  • Printing out the contents of inputs[0] doing this: unsigned char *p = (unsigned char *)&inputs[0]; size_t q; for (q=0; q < sizeof inputs[0]; ++q) printf("%02x\n", p[q]); Gives me 98 dc 64 00 00 00 00 00 98 44 60 00 00 00 00 00 – Arthur Lee Nov 21 '15 at 21:58
  • These hex values look suspicious, does getline or stringstream not work like I expected? – Arthur Lee Nov 21 '15 at 22:12
  • did you find a solution?? – Mohsin Oct 29 '16 at 02:01
  • Did you debug the program? Did you create a _minimal_ reproducing testcase? Did you add exception handling for all the documented exceptions that can be thrown by `std::stoi`? – Lightness Races in Orbit May 18 '19 at 21:29

2 Answers2

2
        while (ssin.good() && i < 2){
            ssin >> inputs[i];
            ++i;
        }

You are using a status-reporting function to predict the future. The good function does not tell you what the results of a future operation will be, only the results of past operations. You need to actually check if the operation (ssin >> inputs[i]) succeeds, not assume that it must succeed if the stream was good in the past.

David Schwartz
  • 166,415
  • 16
  • 184
  • 259
0

In competitive programming, it is customary to use scanf for speed reasons: http://www.cplusplus.com/reference/cstdio/scanf/

Another good way is using cin. I believe it's a bit slower but I have gotten by with it just fine.

Example code to read from stdin for most competitions.

int main() {
  int n;
  cin >> n;

  std::vector<int> xs(n);
  for (int i = 0; i < n; ++i) { 
    cin >> xs[i];
  }
  // do actual computation
}
Matthias Kauer
  • 7,007
  • 5
  • 15
  • 18