Thread: Weird error whith strstr

  1. #1
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555

    Weird error whith strstr

    I've encountered a problem with reading settings from a file. It gives me some "Floating point division by zero" I don't remember exactly, and I don't want to reproduce it since it made some things go bad so I had to restart after a while.
    I'm using BCC 5.5.1 in Windows and here's the code:
    Code:
    short snakepos[897][2] = {39, 11}, applepos[2], key, alive = 1, do_over, err, score[2] = {0, 0}, i, i2, i3 = 0;
    short speed[2] = {8, 62}, size = 5, dir[2], sizeincrease = 3, allowpause = 1, beep = 0, wrap = 1, applecount = 1, colors[3][2] = {{3, 0},{12, 4},{2, 11}}, staticspeed = 0;
    long timeout;
    unsigned char snake = 177, apple[2] = {178, 176}, screen[81] = "", area[80][23], test[2], filename[260];
    FILE *settings;
    
    int main(int argc, char *argv[])
    {
        randomize();
    
        // Loop for playing the game again
        while (1) {
    
        // Read settings
            if (argc >= 3)
                strcpy(filename, argv[2]);
                else
                    strcpy(filename, "settings.cfg");
            if (settings = fopen(filename, "r")) {
                while (1) {
                    fscanf(settings, "%s%*c", screen);
                    if (strstr(screen, "SNAKE=")) {
                        getvalue(6);
                        snake = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "APPLE=")) {
                        getvalue(6);
                        apple[0] = strtol(screen, NULL, 10);
                        apple[1] = strtol(strchr(screen, ',') + 1, NULL, 10);
                    }
                    else if (strstr(screen, "APPLECOUNT=")) {
                        getvalue(11);
                        applecount = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "SIZEINCREASE=")) {
                        getvalue(13);
                        sizeincrease = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "SPEED=")) {
                        getvalue(6);
                        setspeed(strtol(screen, NULL, 10));
                    }
                    else if (strstr(screen, "STARTPOSITION=")) {
                        getvalue(14);
                        snakepos[0][0] = strtol(screen, NULL, 10) + 1;
                        snakepos[0][1] = strtol(strchr(screen, ',') + 1, NULL, 10) + 1;
                    }
                    else if (strstr(screen, "STARTSIZE=")) {    
                        getvalue(10);
                        size = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "BEEP=")) {
                        getvalue(5);
                        beep = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "ALLOWPAUSE=")) {
                        getvalue(11);
                        allowpause = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "WRAP=")) {
                        getvalue(5);
                        wrap = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "STATICSPEED=")) { // BLARGH! Doesn't work. Help!
                        getvalue(12);
                        staticspeed = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "BACKGROUNDCOLOR=")) {
                        getvalue(16);
                        colors[0][0] = strtol(screen, NULL, 10);
                        colors[0][1] = strtol(strchr(screen, ',') + 1, NULL, 10);
                    }
                    else if    (strstr(screen, "APPLECOLOR=")) {
                        getvalue(11);
                        colors[1][0] = strtol(screen, NULL, 10);
                        colors[1][1] = strtol(strchr(screen, ',') + 1, NULL, 10);
                    }
                    else if (strstr(screen, "SNAKECOLOR=")) {
                        getvalue(11);
                        colors[2][0] = strtol(screen, NULL, 10);
                    }
                    else if (strstr(screen, "SCORECOLOR=")) {
                        getvalue(11);
                        colors[2][1] = strtol(screen, NULL, 10);
                    }
                    else {
                        fclose(settings);
                        break;
                    }
                }
    
    //There's more too but this the necessary stuff
    The getvalue function:
    Code:
    // Jumps to pos in an array and puts whatever is on and after it in the beginning.
    void getvalue(short pos)
    {
        short length = 0;
        while (screen[pos] != '\0') {
            screen[length] = screen[pos];
            pos++; length++;
        }
        screen[length] = '\0';
    }
    Also, here's settings.cfg:
    Code:
    SNAKE=177
    APPLE=176,178
    APPLECOUNT=1
    SIZEINCREASE=3
    SPEED=10
    STARTPOSITION=39,11
    STARTSIZE=5
    BEEP=0
    ALLOWPAUSE=1
    WRAP=1
    STATICSPEED=0
    BACKGROUNDCOLOR=3,0
    APPLECOLOR=12,4
    SNAKECOLOR=2
    SCORECOLOR=11
    The problem occurs when trying to read STATICSPEED=, I've tried commenting off the block but I still got the error so it seems the problem is in the if-statement. I can't figure out what's wrong because it's exactly the same as the rest which works like it should.

    I tried looking for another way to read stored settings, like using INI-files but after searching around all I got was functions for reading ini-files in a bunch of other languages like basic and java.

    Heres the whole thing: http://onionknight.no-ip.org/c/nibbles/

  2. #2
    Registered User
    Join Date
    Sep 2004
    Location
    California
    Posts
    3,268
    you will never reach the line that says "STATICSPEED=" because of:
    Code:
    else if (strstr(screen, "SPEED=")) {
        getvalue(6);
        setspeed(strtol(screen, NULL, 10));
    }
    Since "STATICSPEED=" contains the string "SPEED=", it will enter the if statement I posted above twice. A better option would be to use the function strcmp() instead of strstr().

  3. #3
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    A devide by zero error occurs when you try to divide a number by zero.
    Code:
    /* This will trigger a divide by zero error... */
    float num = 10.0 / 0.0;
    Since there is no valid result for 10 / 0, the machine will trigger an exception. It is your responsibility to make sure that you never try to divide a number by zero.

    A quick search of your code shows only one division operation in your setspeed function:
    Code:
        speed[1] = (1.0/speed[0]) * 500;
    At some point speed[0] must be zero. The only way speed[0] could be zero is if setspeed(0) is called. The only place that setspeed is called with a non-constant value is:
    Code:
                    else if (strstr(screen, "SPEED=")) {
                        getvalue(6);
                        setspeed(strtol(screen, NULL, 10));
                    }
    So for some reason the SPEED setting is returning zero([edit]See bithub's post for why it is returning zero[/edit]). You should protect your program against input settings that are out of range. Also, you can use the assert macro. This macro will show a message if the argument passed to it is false.
    Code:
    #include <assert.h>
    
    void somefunc(float number)
    {
       float newNumber;
    
       assert(number != 0);
     
       newNumber = 10.0 / number;
    }
    Last edited by anonytmouse; 02-11-2005 at 10:31 PM.

  4. #4
    Registered User OnionKnight's Avatar
    Join Date
    Jan 2005
    Posts
    555
    I get it. I moved STATICSPEED= above SPEED= to fix it but one thing bothers me. You said that I should get a code that protects against numbers out of range, but I already had that! Why didn't it help?
    Code:
    			// Don't want settings to be out of range, so we need to fix this here
    			if (applecount < 0 || applecount > 897)
    				applecount = 1;
    			if (sizeincrease < 0 || sizeincrease + size > 897)
    				sizeincrease = 1;
    			if (speed[0] < 1 || speed[0] > 10)
    				setspeed(5);
    			if (snakepos[0][0] < 2 || snakepos[0][0] > 78 || snakepos[0][1] < 2 || snakepos[0][1] > 22) {
    				snakepos[0][0] = 2;
    				snakepos[0][1] = 2;
    			}
    			if (snakepos[0][0] % 2 == 1)
    				snakepos[0][0]--;
    			if (size < 0 || size > 897)
    				size = 3;
    			if (colors[0][0] < 0 || colors[0][0] > 15)
    				colors[0][0] = 10;
    			if (colors[0][1] < 0 || colors[0][1] > 15)
    				colors[0][1] = 0;
    			if (colors[1][0] < 0 || colors[1][0] > 15)
    				colors[1][0] = 12;
    			if (colors[1][1] < 0 || colors[1][1] > 15)
    				colors[1][1] = 4;
    			if (colors[2][0] < 0 || colors[2][0] > 15)
    				colors[2][0] = 9;
    			if (colors[2][1] < 0 || colors[2][1] > 15)
    				colors[2][1] = 14;
    		}
    		if (settings = fopen("highscore.txt", "r")) {
    			fgets(screen, 5, settings);
    			score[1] = strtol(screen, NULL, 10);
    			fclose(settings);
    		}
    		if (score[1] < 0)
    			score[1] = 0;

    Also, I don't understand how I can replace strstr with strcmp. But I think I can replace getvalue() with strcpy.

  5. #5
    Yes, my avatar is stolen anonytmouse's Avatar
    Join Date
    Dec 2002
    Posts
    2,544
    Yes, but you only check the speed after you have already called setspeed:
    Code:
                    else if (strstr(screen, "SPEED="))
                        setspeed(strtol(strcpy(screen, &screen[6]), NULL, 10));
    By the time you check your settings, your program has already crashed! You need to check your settings before using them.

    You could use the fscanf statement to split up your name/value pairs.
    Code:
               while (1) {
                    if (fscanf(settings, "%20s=%20s%*c", name, value) == 2)
                    {
                         if (0 == strcmp(name, "SNAKE"))
                         {
                             snake = strtol(value, NULL, 10);
                         }
    
                         if (0 == strcmp(name, "APPLECOUNT"))
                         {
                           ...
    Last edited by anonytmouse; 02-12-2005 at 10:45 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Create Copies of Files
    By Kanshu in forum C++ Programming
    Replies: 13
    Last Post: 05-09-2009, 07:53 AM
  2. weird things with my linked list of queue
    By -EquinoX- in forum C Programming
    Replies: 3
    Last Post: 11-22-2008, 11:23 PM
  3. Quick Ques on String Manipulation
    By ckuttruff in forum C Programming
    Replies: 8
    Last Post: 06-22-2008, 09:32 PM
  4. linked list using strstr
    By ilovec.. in forum C Programming
    Replies: 3
    Last Post: 11-04-2006, 01:30 PM
  5. strstr on a wchar array
    By cloudy in forum C++ Programming
    Replies: 5
    Last Post: 06-28-2006, 06:42 AM