Run-time error Not sure where, how, or why

I'm ashamed that I wrote this program and am having a runtime error. What's even worse is I can't track it down. I also can't debug it since I'm not the one entering the input.

Anyways, here is my code.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <iostream>
#include <string>
#include <vector>

int main() {
   std::string command, command2;
   int thisBlock, thatBlock, numBlocks;
   
   std::cin >> numBlocks;
   std::vector< std::vector<int> > blocks(numBlocks);
   
   for (int i = 0; i < numBlocks; i ++)
      blocks[i].push_back(i);
   
   do {
      std::cin >> command;
      // End input
      if (command == "quit")
         break;
      // Get the rest of the information
      std::cin >> thisBlock >> command2 >> thatBlock;
      // Can't be the same block
      if (thisBlock == thatBlock)
         continue;
      // Can't have a block larger than ones that we have
      if (thisBlock > numBlocks || thatBlock > numBlocks)
         continue;
      
      // Variables to store locations
      int thisBlockRow, thisBlockCol, thatBlockRow, thatBlockCol;
      
      // Find the block locations
      for (int i = 0; i < blocks.size(); i ++)
         for (int j = 0; j < blocks[i].size(); j ++)
            if (blocks[i][j] == thisBlock) {
               thisBlockRow = i;
               thisBlockCol = j;
            }
            else if (blocks[i][j] == thatBlock) {
               thatBlockRow = i;
               thatBlockCol = j;
            }
      
      // If blocks are in the same row, try again
      if (thisBlockRow == thatBlockRow)
         continue;
         
      // Not a valid command
      if (command != "pile" && command != "move")
         continue;
         
      // Removes the blocks on thatBlock
      if (command2 == "onto") {
         // Take care of the removal
         for (int i = thatBlockCol; i < blocks[thatBlockRow].size(); i ++) {
            // Return the block to it's home
            blocks[blocks[thatBlockRow].back()].push_back(blocks[thatBlockRow].back());
            // Remove it from my stack
            blocks[thatBlockRow].pop_back();
         }
      }
      
      // Removes the blocks on thisBlock
      if (command == "move") {
         // Take care of the removal
         for (int i = thisBlockCol; i < blocks[thisBlockRow].size(); i ++) {
            // Return the block to it's home
            blocks[blocks[thisBlockRow].back()].push_back(blocks[thisBlockRow].back());
            // Remove it from my stack
            blocks[thisBlockRow].pop_back();
         }
         blocks[thatBlockRow].push_back(thisBlock);
         blocks[thisBlockRow].pop_back();
      }
      // Retains the blocks on thisBlock
      if (command == "pile") {
         // Copy blocks onto thatBlock
         for (int i = thisBlockCol; i < blocks[thisBlockRow].size(); i ++)
            blocks[thatBlockRow].push_back(blocks[thisBlockRow][i]);
         
         // Remove blocks from old row
         for (int i = blocks[thisBlockRow].size() - thisBlockCol; i > 0; i --)
            blocks[thisBlockRow].pop_back();
      }
      
   } while (command != "quit");
   
   for (int i = 0; i < blocks.size(); i ++) {
      std::cout << i << ":";
      for (int j = 0; j < blocks[i].size(); j ++)
         std::cout << " " << blocks[i][j];
      std::cout << "\n";
   }
   
   return 0;
}


At first, I thought it could have been in places where I was using the [] operator, but that's not the case, I don't think. During my tests, everything runs perfectly fine, however, when an unknown, supposedly properly formatted external file overloads stdin, much like I've tried, it returns a run-time error. I don't know the contents of this file, nor do I know which line or even the general vicinity of any errors.

I have been looking over it for quite some time now (well duh, I do do things other than stalk the forums). I figure it might be better to have someone else look at it quickly. If more information is needed, let me know. I've been having so many problems with these problems I'm ashamed, to be honest.

Thanks in advance guys.
If more information is needed, let me know.

What is it supposed to do, and sample input, would be nice. (Since it never std::cout's what it expects.)

And I know it's a drag, but how about you use std::vector::size_type instead of int, to get rid of those pesky signed compared to unsigned warnings?
Compiled it, ran it, after no outout to screen for 30 seconds, hit CTL-C.

C:\Temp>testxxx
This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Then I realized you have no cout comments before cin to tell the user what type data to type.

so I add some couts and run it again, and hit a endless loop after
std::cin >> numBlocks; because you don't check the intput to verify it's numeric.

reread your post and you said the user is using a file.
Well Of course your going to have runtime issues if you dont' know the format of the file, and you don't check the input to see if it's a number or text.

I also can't debug it since I'm not the one entering the input.


That's a bunch of BS, of course you can track it down, create a file and copy and paste the new page from yahoo. Start fixing your code instead of making excuses.
For reading while( std::cin>>command and command not_eq "quit" )

1
2
3
4
5
6
7
         for (int i = thisBlockCol; i < blocks[thisBlockRow].size(); i ++) {
            //...
            blocks[thisBlockRow].pop_back();//¿how many times does the loop run?
         }
         blocks[thatBlockRow].push_back(thisBlock);
         blocks[thisBlockRow].pop_back(); //¿what if empty()?
      }



> because you don't check the intput to verify it's numeric.
just assume that the input is correct. Concentrate on the program logic
You could take care of that later (if needed).

> I also can't debug it since I'm not the one entering the input.
read as `the program crash for an unknown input'
ne555 wrote:
For reading while( std::cin>>command and command not_eq "quit" )

Turns out the same rule applies for std::getline(), as in:
while (std::getline(std::cin, s))
Pretty ugly, no? Yes.
I'm sorry, I was really tired last night and forgot to add some things. Anyways, here are the restrictions on the input:

The input begins with an integer n on a line by itself representing the number of blocks in the block world. You may assume that 0 < n < 25.
The number of blocks is followed by a sequence of block commands, one command per line. Your program should process all commands until the quit command is encountered.

You may assume that all commands will be of the form specified above. There will be no syntactically incorrect commands.


Sample input provided:
10
move 9 onto 1
move 8 over 1
move 7 over 1
move 6 over 1
pile 8 over 6
pile 8 over 5
move 2 over 1
move 4 over 9
quit


Sample output expected:
 0: 0
 1: 1 9 2 4
 2:
 3: 3
 4:
 5: 5 8 7 6
 6:
 7:
 8:
 9:


My code runs that properly and has the correct output but is still receiving a runtime error using the judge's input. Maybe I misunderstood the input restrictions, but I thought that meant that only lines in that format, string int string int or just string, are the only possible inputs.

For complete rules, refer to here: http://uva.onlinejudge.org/external/1/101.pdf

Note: This is just like Project Euler and I didn't want to exactly specify what I was doing to make sure everyone had a chance to attempt it. I did a little searching on their forums and it seems like there are a lot of people that get runtime errors.

I also made two small modifications to my code here:
1
2
3
      if (command == "move") {
         // Take care of the removal
         for (int i = thisBlockCol + 1; i < blocks[thisBlockRow].size(); i ++) {


1
2
3
      if (command2 == "onto") {
         // Take care of the removal
         for (int i = thatBlockCol + 1; i < blocks[thatBlockRow].size(); i ++) {


1
2
3
4
5
6
      // Not a valid command
      if (command != "pile" && command != "move")
         continue;
      
      if (command2 != "onto" && command2 != "over")
         continue;


I hope this will help make things easier to understand. Sorry again about the confusion, however, I was expecting it.
Last edited on
You should modularize your code.
Make functions from the `remove' and `copy' operations.

Here's a test
10
pile 2 over 1
pile 3 over 1
pile 4 over 1
pile 5 over 1
move 2 over 6
quit

(you make the `3' disappear, and duplicate the `2')
you make the `3' disappear, and duplicate the `2'

I observed this.

Now, the problem is to figure out why.

You should modularize your code.
Make functions from the `remove' and `copy' operations.

Can you explain a little bit more? I understand to modularize means to put it into functions and pass the correct parameters, but to what extent?

Do you mean the remove and copy operations of vector? Or are you generalizing?
> Now, the problem is to figure out why.
1
2
3
4
5
6
7
8
9
         //`removal'
         for (int i = thisBlockCol; i < blocks[thisBlockRow].size(); i ++) {
            //...
            blocks[thisBlockRow].pop_back();
         }
         //`copying'
         blocks[thatBlockRow].push_back(thisBlock);
         blocks[thisBlockRow].pop_back();
      }
After the removal the bucket has: 1 2 3
In the loop you are increasing `i' (the counter), but also decreasing `size()' (the limit)
so the number of operations is not what you originally expected.

Instead of taking care of the cells 1-10, you just affect 5-10.
About modularizing
1
2
3
4
5
6
7
8
9
//preparing the buckets
if (command2 == "onto")
	remove_blocks( blocks, thatBlockRow, thatBlockCol );
if (command == "move")
	remove_blocks( blocks, thisBlockRow, thisBlockCol );

//translating the content
//a `move' can be done as pile, as the block is the last element
copy_blocks( blocks, thisBlockRow, thisBlockCol, thatBlockRow );
Last edited on
I made the correction, and after I while I began to realize why I was getting a runtime error, I had this line:

1
2
3
      // Can't have a block larger than ones that we have
      if (thisBlock > numBlocks || thatBlock > numBlocks)
         continue;


Which was incorrect. This allowed them, based off of 10 blocks, to enter 10 as thisBlock of thatBlock. This was giving me an out of bounds and in turn a RE.

Between fixing that and making my code modular, I submitted and failed. I then realized I had left some debugging lines which displayed the output after every command. Removed that and passed. Thanks guys.
Topic archived. No new replies allowed.