我一直在try 制作一个tic-tac-toe的游戏,它从用户的输入中打印出一块棋盘,我已经设法保存了棋盘的当前状态、网格的大小和轮数. 但当我试图加载这些数据时,出于某种原因,我无法从.txt文件中获取要加载的电路板的状态.

void FileLoad(char ***Board, int *x, int *y, int *roundcount, const char *filename) {
    FILE *Load =fopen(filename, "r");
    if (Load == NULL) {
        printf("Error");
        return;
    }

    fscanf(Load, "%d", *roundcount);
    fgetc(Load);
    fscanf(Load, "%d %d ", *x, *y);

    *Board = (char **)malloc(*y * sizeof(char *));

    (*Board)[0] = (char *)malloc((*y * *x) * sizeof(char));
    for (int i = 1; i < *y; ++i)
         (*Board)[i] = (*Board)[0] + i * *x;

    fgetc(Load);

    for (int i = 0; i < *y; ++i) {
        for (int j = 0; j < *x; ++j)
            fscanf(Load, "%c", &(*Board)[i][j]);
        fgetc(Load);
    }
    fclose(Load);
}

使用调试器时,当我try 使用fscanf获取数据时,我发现问题的根源是代码的最后几行,但我不知道如何解决这个问题.

这是保存文件在5*5网格上的外观,其中包含一些放置的字符.第一个数字用于计数,其余数字用于棋盘的网格.

2
5 5
X

  O

推荐答案

在加载电路板 struct 之前还有一个额外的fgetc(Load),它可能应该跳过挂起的换行符,但由于格式字符串中的尾随空格,fscanf(Load, "%d %d ", ...)已经使用了这个换行符.

还要注意,您必须将指针传递给fscanf,而不是值*roundcount*x*y.指定值和指向值的指针使用相同的标识符是非常令人困惑的.要避免这种容易出错的方法,请对从文件中读取的值使用局部变量,并仅在成功完成后才将它们存储到调用方的变量中.

为便于故障排除,请测试所有错误 case 并输出信息性错误消息.

以下是修改后的版本:

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

int FileLoad(char ***pboard, int *pcols, int *prows,
             int *proundcount, const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp == NULL) {
        fprintf(stderr, "FileLoad: cannot open file %s: %s\n", filename, strerror(errno));
        return -1;
    }

    int rows, cols, roundcount;
    char eol[2];

    // read exactly 3 numbers and a newline.
    if (fscanf(fp, "%d %d %d%1[\n]", &roundcount, &cols, &rows, eol) != 4) {
        fprintf(stderr, "FileLoad: file %s: invalid format\n", filename);
        fclose(fp);
        return -1;
    }

    char **board = (char **)malloc(rows * sizeof(char *));
    char *p = (char *)malloc(sizeof(char) * rows * cols));
    if (board == NULL || p == NULL) {
        fprintf(stderr, "FileLoad: file %s: allocation error\n", filename);
        free(board);
        free(p);
        fclose(fp);
        return -1;
    }
    for (int i = 0; i < rows; ++i) {
        board[i] = p + i * cols;
    }

    // Read the game board
    for (int i = 0; i < rows; ++i) {
        for (int j = 0; j < cols; ++j) {
            // should be a space, an 'X' or an 'O'
            board[i][j] = fgetc(fp);
        }
        if (fgetc(fp) != '\n') {
            fprintf(stderr, "FileLoad: file %s: invalid contents\n", filename);
            free(board);
            free(p);
            fclose(fp);
            return -1;
        }
    }
    fclose(fp);
    *poard = board;
    *proundcount = roundcount;
    *pcols = cols;
    *prows = rows;
    return 0;
}

C++相关问答推荐

问关于C中的指针和数组

librsvg rsvg_handle_get_dimensions获取像素大小与浏览器中的渲染大小没有不同

如何避免重新分配指针数组时,我们从一开始就不知道确切的大小

getchar读css + z还是返回css?

将 struct 变量赋给自身(通过指针取消引用)是否定义了行为?

如何按顺序将所有CSV文件数据读入 struct 数组?

I2C外设在单次交易后出现故障

OpenSSL:如何将吊销列表与SSL_CTX_LOAD_VERIFY_LOCATIONS一起使用?

不同原型的危险C函数是可能的

用C++构建和使用DLL的困惑

如何在不使用字符串的情况下在c中编写函数atof().h>;

当我用scanf(&Q;%S%S%S&Q;,单词0,单词1,单词2)输入多个单词时,除了最后一个单词外,每个单词的第一个字符都丢失了

C-try 将整数和 struct 数组存储到二进制文件中

隐藏测试用例无法在c程序中计算位数.

赋值两侧的后置增量,字符指针

&stdbool.h&q;在嵌入式系统中的使用

为什么程序在打印每个数字之前要等待所有输入?

为什么创建局部变量的指针需要过程在堆栈上分配空间?

比 * 更快的乘法

OpenGL 中的非渐变 colored颜色 变化