-1

I have the following code for parsing a text file which contains lines of data such as 1,1,1,1,1,1.

while(file >> line)
    {
        words.push_back(line);
    }

    for(int i = 0; i < words.size(); i++)
    {
            if(words.at(i).substr(0, 1) == "[" && words.at(i) != "[header]")
                layers.push_back(words.at(i));

            if(words.at(i).substr(0, 4) == "type")
            {
                temp = words.at(i);
                temp.substr(4, 1);
                types.push_back(temp);
            }

            if(words.at(i) == "[header]")
            {
                map_width = words.at(i+1).substr(6, words.at(i+1).size());
                map_height = words.at(i+2).substr(7, words.at(i+1).size());

                stringstream(map_width) >> width;
                stringstream(map_height) >> height;
            }

            if(words.at(i) == "type=background")
            {
                for(int j = i+1; j <= height + (i+1); j++)
                {
                    int l = 0, m = 1, number = 0, extracted;
                    string extracted_line = words.at(j);

                    for(int k = 0; k <= extracted_line.size(); k++)
                    {
                        cout << number << endl;
                        string ph_character = words.at(j).substr(l, m);
                        if(ph_character == ",")
                        {
                            number = 0;
                            break;
                        }
                        if(ph_character == "0") cout << "Found 0.\n";

                        stringstream(ph_character) >> extracted;
                        number = (number*10) + extracted;

                        switch(number)
                        {
                            case 1:
                                //cout << "Found 1" << endl;
                                break;

                            case 4:
                                cout << "Found 4" << endl;
                                break;
                        }
                        l++; m++;
                    }
                }
            }
    }
    file.close();
}

The code above is supposed to iterate over the file, store each line in a string array, store each line in a string then check each character of the string. The number must reset every time it encounters a ',' character, however output is crazy:

0
1
11
111
1111
11111
111111
1111111
11111111
111111111
1111111111
-1773790777
-558038505
and so on.

What have I done wrong? The output should be the exact content of the file which is normally 1, then 1 then 1 then 10, basically the number before the ','. I'm running Windows XP Sp3, using code::blocks.

EDIT:

A sample from the file I'm trying to parse:

> 1,1,1,1,1,2,23,23,23,23,23,1,1,1,1,1,1,1,1,1
> 10,10,10,23,1,1,1,1,1,1,1,1,23,23,23,23,1,1,1

and there's more lines of such data, but there's no point to further flood this question.

Bugster
  • 1,552
  • 8
  • 34
  • 56
  • 3
    have u tried using a debugger? – pm100 Oct 23 '12 at 17:38
  • I don't see how that could help since I don't have any crashes. I've tried debugging my code by hand but to no result – Bugster Oct 23 '12 at 17:38
  • 3
    What is the biggest number you can store in an `int`? What happens if you try to store an even bigger number? – Bo Persson Oct 23 '12 at 17:40
  • 3
    a debugger allows you to step through the program and inspect the data as it progresses. You can set breakpoints in various places and see whats going on – pm100 Oct 23 '12 at 17:40
  • @Bo Persson, I'm not trying to store massive values, the values number needs to take are from 1 to 100. – Bugster Oct 23 '12 at 17:42
  • If you don't want to use a debugger, add lots of debugging output to your program so you can figure out where it first does something other than what it should do. – David Schwartz Oct 23 '12 at 17:42
  • 2
    @ThePlan - You do `number = (number*10)` in a loop. That will quickly produce really large numbers. – Bo Persson Oct 23 '12 at 17:43
  • @Bo Persson, I also specify that when it hits a ',' character the number gets resetted to 0. Those are very frequent in the file, and I ran some manual debugging to check if the number ever gets resetted and it does. – Bugster Oct 23 '12 at 17:44
  • I really wish that someone would just read my code instead of telling me to debug, I have debugged manually and I cannot find where the mistake is at, instead of suggesting me to use debuggers or telling me the int size I could be using google for that. – Bugster Oct 23 '12 at 17:49
  • maybe an example of your data file would help. – AShelly Oct 23 '12 at 17:58
  • Thanks to whoever downvoted. Clearly a very logical question which several programmers have yet to solve doesn't belong here, in a programming problems Q&A... Perhaps it would fit better in fitness Q&A? This site is honestly going down the drain... – Bugster Oct 23 '12 at 18:09
  • @ThePlan: You have the input file. You can replicate the failure. We can't. If you've debugged manually, you should have found the first place where the code did something other than what you expected it to do. – David Schwartz Oct 23 '12 at 18:25
  • @ThePlan, honestly, this question does not show any research effort; it is unclear and not useful. See [this question](http://stackoverflow.com/q/236129/1025391) for splitting a string and [this question](http://stackoverflow.com/q/194465/1025391) for parsing integers in C++. – moooeeeep Oct 23 '12 at 18:51
  • @moooeeeep, what is there to research? My code clearly is supposed to do something which I have researched about... This is a PROBLEM which I have no found on the internet so far, your comment is simply not constructive. – Bugster Oct 23 '12 at 19:01
  • @ThePlan - it's like this. The easiest way, by far, of finding the error/s in this page of code is to debug it where it is already available and going wrong - on your box. For us all to debug it, we will have to go through all the steps that you have already gone through to build it, and then do all the hard work of actually debugging it. Please, please run such code under a debugger first and get some more information to save us all doing what you have already done. Who knows - you may actually find the bug yourself. – Martin James Oct 23 '12 at 19:01
  • Debugging is at the core of all software development. Writing code that compiles is easy, writing code that works is not. – Martin James Oct 23 '12 at 19:03
  • @ThePlan debugging is research. Trying to reduce the code to a minimum, self contained, yet compilable example is research. Generating a large amount of code that is (almost) doing stuff as intended is not. – moooeeeep Oct 23 '12 at 19:09
  • @moooeeeep what you and many other people reading this question have failed to understand is that I have manually debugged my entire code, and I have said this at least 3 times in this question. How else could I have found the odd number behavior without debugging? – Bugster Oct 23 '12 at 19:12
  • @ThePlan what you have done is _testing_, not _debugging_. – moooeeeep Oct 23 '12 at 19:16
  • @moooeeeep what you are saying makes no sense, you are telling me compilable example is research, and that debugging which is testing where something fails is testing. – Bugster Oct 23 '12 at 19:22

3 Answers3

1

Your problem is that number isn't big enough to hold 11111111111 so you get signed integer overflow, creating the numbers you see get printed. You could try to use a larger type, or a bigint from say boost.

Mark B
  • 95,107
  • 10
  • 109
  • 188
0

Yup, your number is overflowing. The largest value as signed 32-bit int can hold is 2147483648. You see the overflow occurs after you print out 11111111111.

number = (number*10) + extracted; Will cause your number to overflow after 10 iterations, which is exactly what is happening.

Upon further review, the line stringstream(ph_character) >> extracted; could be overwriting your number after it is reset to zero. If the condition is setting the number to zero, something is overwriting number again. Usually, this is caused by accessing an array out of bounds.

Steve Barna
  • 1,378
  • 3
  • 13
  • 23
  • But the number is not supposed to be holding such massive values, the number only has to take values from 1 to 100, and it resets every 1-2 iterations. – Bugster Oct 23 '12 at 17:48
  • It appears `ph_character == ","` never evaluates to true. – Steve Barna Oct 23 '12 at 17:51
  • I already manually debugged if the statement executes, and it does, and I can notice that in my output where number becomes 0 then increments to a crazy number again. – Bugster Oct 23 '12 at 17:52
0

You should improve your indentation, make your code clearer and then fix your number parsing. Apparantly your ',' delimiter is parsed before the number, not thereafter. Admittedly, your code is hard to understand (all these .at and .substr) and 80% of it is just not related to the problem, which is the parsing of the word strings, I suppose.

So, if I haven't understood your question, nevermind, you really could have been clearer.


Here's a suggestion how to do better:

// TODO: add error handling

// TODO: define start and end position of your vector appropriately
std::vector<std::string>::iterator it = words.begin();
std::vector<std::string>::const_iterator end = words.end();

// iterate over your lines
for( ; it != end; ++it) {

    // tokenize using getline
    std::stringstream this_row( *it );
    std::string substr;
    while (std::getline(this_row, substr, ',')) {

        // extract formatted data using stringstream
        std::stringstream str(substr);
        int number;
        str >> number;
        std::cout << number << std::endl;

        // TODO: do whatever you like with that number
    }
}

For further reading I recommend (and for better error handling than in my simple example):

Community
  • 1
  • 1
moooeeeep
  • 31,622
  • 22
  • 98
  • 187