c - Checking for null in a 2d array

2019-09-15 02:14发布

I am filling a 10 x 10 grid of characters from an input file. I need to check if the grid is a square (i.e, has N x N characters, where N <= 10)

The input file is such:

pitk
olpe
pkey
tope

When I print the grid in gdb, I get the following result:

$1 = {"pitk\000\000\000\000\366h", 
      "olpe\000\000\001\000\000", 
      "pkey\000\000\000\000\000", 
      "tope\000\000\000\000\000", 
      "\000\344\241\367\377\177\000\000", <incomplete sequence \336>, 
      "\000\377\377\177\000\000\037\355\336", <incomplete sequence \367>, 
      "\000\177\000\000\000\000\000\000\000", 
      "\000\000\000\000\000\000\000\000\000", 
      "\000\000\000\000\000\000\000\000\r\020", 
      "\000\000\000\000\000\000\000\000\000"}

The part of my main function that checks if the grid is valid, is:

  bool check = (checknxn(grid));
  if(check == false) {
    fprintf(stderr, "Invalid Input!\n");
    exit(0);
  }

The checknxn function:

bool checknxn(char grid[10][10]) {
  int columns = 0;
  for(int i=0;i<10;i++) {
    if(grid[0][i]!=NULL)
      columns++;
    else {
      break;
    }
  }

  for(int i=1;i<10;i++) {
    for(int j=columns;j<10;j++) {
    if(grid[i][j]!=NULL)
      return false;
    }
  }

  int rows = 0;
  for(int i=0;i<10;i++) {
    if(grid[i][0]!=NULL)
      rows++;
    else {
      break;
    }
  }
  if (!(rows == columns))
    return false;
  for(int i=0;i<rows;i++) {
    for(int j=0;j<columns;j++) {
      if(grid[i][j]==NULL) {
        return false;
      }
    }
  }
  return true;
}

This returns false, and my program exits, even though the input grid in this case is valid.

I can't figure out why the checknxn function is returning false in this case.

UPDATE: This is how I initialize my grid:

FILE *file1 = fopen(argv[1], "r"); // "r" for read

  char grid[10][10];

  char c;
  for(int i=0;i<10;i++){
    for(int j=0;j<10;j++){
      fscanf(file1,"%c", &c);
      if (c == '\n') {
        grid[i][j] = '\0';
        break;
      }
      if (c == ' ') {
        grid[i][j] = '\0';
        continue;
      }
      if (c == '\0') {
        grid[i][j] = '\0';
        continue;
      }
      else {
        grid[i][j] = c;
      }
    }
  }

2条回答
姐就是有狂的资本
2楼-- · 2019-09-15 02:50

Classic C mistake of not initializing data. Memset probably the way to go (see below).

memset(grid, 0, sizeof(grid[0][0]) * rows * columns);
查看更多
冷血范
3楼-- · 2019-09-15 03:03

Your grid is not fully initialized (you did not set every cell to e.g.: \0) so you have only the strings and the start of every row properly defined. And when you have done so, initialized the grid that is, you do not check for the cells being NULL because they are not pointers but actual content, so you check for e.g.: \0 if you have initialized the grid to that value.

EDIT after additional information from the OP

To initialize that grid you can do something like

char grid[10][10];
for(int i=0;i<10;i++){
  for(int j=0;j<10;j++){
    grid[i][1j] = '\0';
  }
} 

And only then do the fillings. Don't mix it.

If you want to check if every cell is filled, that is: not \0

  for(int i=0;i<rows;i++) {
    for(int j=0;j<columns;j++) {
      if(grid[i][j] != `\0`) {
        return false;
      }
    }
  }

But you want to load C-string in it and C-strings end with a \0. Either load the strings into the cells without the trailing \0 or adjust the loops to check up to row_length-2 instead of row_length -1.

A much simpler approach if you have strings: measure the string length in every row and if they are all the same and the number of rows corresponds to the string length you have a square grid.

查看更多
登录 后发表回答