Home > Software design >  C: Global variable value changing by itself?
C: Global variable value changing by itself?

Time:09-29

The task itself is not the main focus of my problem here, but I will explain it so the code makes sense.

Basically I want to create a text-based KenKen puzzle game. I will not explain the rules of the game extensively since it is not that important. Basically it is a sudo-like game in a 2d board with different values. I read the values from a text file which is like the following:

5
9  (1,1) (2,1) (2,2)
4  (1,2)
2  (1,3)
10  (1,4) (2,4) (2,5)
1  (1,5)
8* (3,1) (4,1) (5,1)
11  (2,3) (3,2) (3,3)
3  (3,4)
4  (3,5)
15* (4,2) (5,2) (5,3)
12* (4,3) (4,4) (5,4)
2  (4,5)
5  (5,5)

The first number is always the board size of the game (in this case 5x5). Next lines are formatted as follows: IntegerCharacter and a set of points. The integer is the total value a group of points should hold once you add up or multiply their contents (this is specified by the character).

In any case, I read the contents from the text file in the following way:

struct point group_points[MAXN][MAXN] = {{}}; //
int board[MAXN][MAXN] = {{}}; //contents of board
char board_group[MAXN][MAXN] = {{}}; //group each point is in
int group_value[MAXN*MAXN] = {0}; //total value of i-th group
char group_operator[MAXN*MAXN] = {'\0'}; //operator of i-th group
int  group_length[MAXN] = {0}; //stores the number of cells in each group
int board_size = 0; //size of the group 
int group_count = 0; //total number of groups


/*** 
 * @brief Reads information on the puzzle 
 * ***/
void  readPuzzle(char *filename){
FILE *fp = NULL;
fp = fopen(filename, "r"); //open filename to be read 
printf("%s\n", filename);
int current_group = 0;

fscanf(fp, "%d", &board_size);
    printf("%d\n", board_size);
    char current_line[MAX_IN];
    int value = 0;
    char operator = '\0';
    while (fscanf(fp, "%d%c", &value, &operator)!=EOF){
        printf("%d %c\n", value, operator);
        group_value[current_group] = value;
        group_operator[current_group] = operator;
        int i = 1;
        int group_size = 0;
        fgets(current_line, MAX_IN, fp);

        while (current_line[i]!='\0'){
            group_size  ;
            int x = current_line[i 1] - '0';
            int y = current_line[i 3] - '0';
            printf("(%d, %d) ", x, y);
            board_group[x-1][y-1] = group_count   'a';
            board[x-1][y-1] = 0;
            group_points[group_count][group_size-1].x = x;
            group_points[group_count][group_size-1].y = y;
            i = i   6;
            }

        group_length[group_count] = group_size;
        group_count  ;
        current_group  ;
        printf("\n\n%d\n\n", board_size);
    }

}

Notice most of the variables used are global. Also, if this program is ran, even though the variable board_size is only read one, the value suddenly changes from 5 to 3 as witnessed through the printf statements. Also the board[][] contents seem to change. Any suggestions?

CodePudding user response:

The code is a bit too optimistic that the source file conforms to its expectations. An invisible trailing SP on any line will make i = i 6; wrong, and the precise target of while (current_line[i]!='\0'){ will be missed. What follows is adventures in "undefined behaviour"... (Plus mingling scanf with fgets is not recommended. The former will, on occasion, leave characters in the input buffer that subsequent reads will trip over.)

It's been a long time since the challenge to parse an input file has come along.

Here's a version that simulates loading your data by "loading" strings from an array. Rather than load into discrete arrays of arbitrary size, this initialises a board (I'm guessing filled with ASCII '0's) and displays that board. Then each row of conditions is put into its own struct (forming an array of structs), holding the important information translated from the input text. You may see the opportunity to 'tweak' the incoming values (subtract 1 when loading) in order to conveniently index into the zero-based addressing of the board array. This code does not do this offsetting. (And, the only 'global' is the collection of input strings.)

Fun!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *inLns[] = { // your data
    "5\n",
    "9  (1,1) (2,1) (2,2)\n",
    "4  (1,2)\n",
    "2  (1,3)\n",
    "10  (1,4) (2,4) (2,5)\n",
    "1  (1,5)\n",
    "8* (3,1) (4,1) (5,1)\n",
    "11  (2,3) (3,2) (3,3)\n",
    "3  (3,4)\n",
    "4  (3,5)\n",
    "15* (4,2) (5,2) (5,3)\n",
    "12* (4,3) (4,4) (5,4)\n",
    "2  (4,5)\n",
    "5  (5,5)\n",
};

typedef struct {
    int val;
    char op;
    int nPairs; // number of r/c pairs stored
    int pairs[3][2]; // dimensioned for max. sufficient
} cond_t;

// Show the current board values
void display( char *brd, int sz ) {
    for( int r = 0; r < sz; r   ) {
        for( int c = 0; c < sz; c   )
            printf( "%c ", *brd   );
        putchar( '\n' );
    }
}

int main() {
    char *board = NULL;
    cond_t *cond = NULL; // collection of "conditions"
    int nCond = 0; // number of conditions

    // These 3 lines simulate `fgets()`
    for( int i = 0; i < sizeof inLns/sizeof inLns[0]; i   ) {
        char buf[ 100 ];
        strcpy( buf, inLns[i] );

        // first line is the dimension of the board
        if( i == 0 ) {
            int sz = atoi( buf );
            board = malloc( sz * sz ); // one byte 'cells' on board
            /* omitting test for NULL */
            memset( board, '0', sz * sz ); // all set to ASCII '0'
            display( board, sz );
        } else {
            // dissect "condition" line
            int pairMaj = 0, pairMin = 0;
            for( char *p = buf; (p = strtok( p, " \n") ) != NULL; p = NULL ) {
                // first piece is a value and an "operation"
                if( p == buf ) {
                    cond = realloc( cond, (nCond   1) * sizeof *cond );
                    /* omitting test for NULL */
                    memset( &cond[nCond], 0, sizeof *cond ); // zero new struct
                    cond[nCond].val = atoi( p );
                    cond[nCond].op = p[strlen(p)-1];
                } else {
                    // other piece(s) are x,y of other "cells"
                    for( ; *p; p   ) {
                        if( isdigit(*p) ) {
                            // note count 0,0 => 0,1 => 1,0 => 1,1 => 2,0 => 2,1
                            cond[nCond].pairs[pairMaj][pairMin] = *p - '0';
                            pairMaj  = pairMin  ; // omitting test for 3,0 overrun
                            pairMin %= 2;
                        }
                    }
                    cond[nCond].nPairs  ; // got a pair now
                }
            }
            nCond  ; // got a full definition now
        }
    }

    // report back what has been loaded/translated
    for( i = 0; i < nCond; i   ) {
        printf( "#%d - %d %c ", i, cond[i].val, cond[i].op );
        for( int j = 0; j < cond[i].nPairs; j   )
            printf( "[%d,%d] ", cond[i].pairs[j][0], cond[i].pairs[j][1] );
        printf( "\n" );
    }

    return 0;
}
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
0 0 0 0 0
#0 - 9   [1,1] [2,1] [2,2]
#1 - 4   [1,2]
#2 - 2   [1,3]
#3 - 10   [1,4] [2,4] [2,5]
#4 - 1   [1,5]
#5 - 8 * [3,1] [4,1] [5,1]
#6 - 11   [2,3] [3,2] [3,3]
#7 - 3   [3,4]
#8 - 4   [3,5]
#9 - 15 * [4,2] [5,2] [5,3]
#10 - 12 * [4,3] [4,4] [5,4]
#11 - 2   [4,5]
#12 - 5   [5,5]
  • Related