c - 如何将位于结构体中的二维数组中的每个字符保存并加载到文件中? C

标签 c arrays

我正在尝试将二维字符数组保存到文件中。 我的二维数组是一 block 板,我可以在其中绘制、调整大小、删除和添加行/列。

我在将其保存到文件时遇到问题。

首先,我不知道这两个函数中哪一个有问题。 有没有办法查找我尝试保存到的 .txt 文件并查看它是否有效?

第二,这是两个函数,SAVE 和 LOAD to .txt 文件。

.txt 文件的名称通过用户的参数传递。 请忽略“itreachedhere”打印命令。

void save_board(char* textfile, board* theboard){
    FILE* outfile = NULL;
    int i,j;

    outfile=fopen(textfile, "w");
    if(outfile==NULL){
        printf("Could not open file %s.\n", textfile);
    }
    printf("itreachedhere\n");
    for(i=0;i<theboard->num_rows;i++){
        for(j=0;j<theboard->num_cols;j++){
            fprintf(outfile, " %c ", theboard->myboard[i][j]);
        }
        fprintf(outfile, "\n");
    }
    fclose(outfile);
}

void load_board(char* textfile, board* theboard){
    FILE* infile = NULL;
    int i, num_chars=0;
    char current_char;
    int lengths[10000];
    int index=0;
    int row=0;

    infile=fopen(textfile, "r");

    if(infile==NULL){
         printf("Could not open file %s.\n", textfile);
        // exit(1);
    }

    while(!feof(infile)){
        current_char=fgetc(infile);
        num_chars++;
        //printf("%d ", num_chars);
        if(current_char=='\n'){

             // This array stores the length of characters of each line
            lengths[index]=num_chars+1;
            //update index
            index++;
            // Increment the number of row read so far
            row++;
            // Reset the number of characters for next iteration
            num_chars=0;

        }
    }

    //printf("%d",lengths[1]);
    theboard->num_rows=row;
    theboard->num_cols=lengths[0];

    //recreate the board
    createboard(theboard);



    //now we need to copy the characters in infile to myboard
    for(i=0;i<theboard->num_rows;i++){
        fgets(theboard->myboard[i],(lengths[i]+1),infile);
        //printf("%c", theboard->myboard[i][0]);
    }
    printf("itreachedhere\n");
    printboard(theboard);
    //printf("itreachedhere\n");
    fclose(infile);


}

例如。 如果我有一 block 尺寸为 4 x 5 的木板

3  *  *  *  *  * 
2  *  *  *  *  * 
1  *  *  *  *  * 
0  *  *  *  *  * 
   0  1  2  3  4  

然后我会像这样保存它,

Enter your command: s e.txt

然后像这样加载它,

Enter your command: l e.txt

然后当我尝试打印板时我会得到类似的东西

3  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  � 
2  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  � 
1  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  � 
0  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  �  � 
   0  1  2  3  4  5  6  7  8  9  10  11  12  13  14  15  16

我的打印板功能没有任何问题。我认为我的错是我不知道如何正确保存文件或正确检索文件。

感谢您的评论。 现在我明白了

2     *        *        *        *     

1     *        *        *        *     

0     *        *        *        *     

   0  1  2  3  4  5  6  7  8  9  10  11  12  13 

最佳答案

继续评论,我将重点关注您的阅读。重新阅读有关 feof 的行错了。您的情况的简短版本是流错误条件(这就是 feof 所寻找的),直到您调用 fgetc(infile) 才设置。 (此时您已经在循环内并且已更新 num_chars,即使您在上次循环中读到 EOF)。

现在让我们谈谈为什么即使您正确使用了EOF,您的代码仍然会失败。 。当您声明char current_char;时然后尝试正确测试 while ((current_char = fgetc (infile)) != EOF) {...} ,你永远不会看到EOF设置比较 char反对int 。要解决此问题,您的current_char必须声明为int .

您阅读时遇到的其他问题。没有理由将每行的字符数存储在 lengths 中数组(除非你有一个锯齿状数组)。在正常的正方形/矩形板表示中,所有行都将具有相同数量的元素。您需要知道的是每行中的字符数,并且需要根据每行的固定数量验证您的读取。

此外,如果您正在读取不包含 '\n' 的板文件怎么办?在最后一行的末尾(称为非 POSIX 行尾/文件尾)。您可以通过简单检查读取的最后一个字符是否确实是 '\n' 来防止出现这种情况。或不。如果不是,那么您需要将行索引增加 1否则你会丢失数据。 (这意味着您需要保存最后读取的字符以进行比较)

下面是一种将固定长度的未知数量的行/列读取到 lengths 中的方法的简短示例。大批。我用fp为您infilerows x colsncol用于索引和每行字符比较。我还声明了一个常量 NDATA而不是使用像 10000 这样的魔数(Magic Number)在代码中。 (这使得调整大小成为一个简单的改变)代码只是从作为程序第一个参数给出的文件名中读取(如果没有给出文件名,则默认从 stdin 读取)尝试以下操作:

#include <stdio.h>

enum { NDATA = 1000 };

int main (int argc, char **argv) {

    char lengths[NDATA] = "", last = 0; /* initialize all variables */
    int current_char = 0,   /* must be int to indicate EOF (-1) */
        rows = 0,           /* row index */
        cols = 0,           /* col index */
        ncol = 0,           /* num cols per-row, must be equal for each row */
        ndx = 0;            /* lengths index */
    FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;

    if (!fp) {  /* validate file open */
        fprintf (stderr, "fileio() error: file open failed '%s'\n", argv[1]);
        return 0;
    }

    while ((current_char = fgetc (fp)) != EOF) { /* read each char until EOF */

        if (current_char == '\n') { /* if end of line encountered on read */

            if (!ncol)                  /* is ncols set?, if not */
                ncol = cols;            /* set it */
            else if (cols != ncol) {    /* otherwise, if not correct - error */
                fprintf (stderr, "error: unequal number of cols at row '%d'\n",
                        rows);
                return 1;
            }
            cols = 0;   /* reset column index  */
            rows++;     /* increment row index */
        }
        else {  /* normal char, add to lengths, increment index */
            lengths[ndx++] = current_char;
            cols++;
        }
        last = current_char;
        if (ndx == NDATA) { /* verify you don't exceed storage */
            fprintf (stderr, "warning: lengths array is full.\n");
            break;
        }
    }
    if (fp != stdin) fclose (fp);   /* close file */

    /* protect against non-POSIX end-of-line on last line in file */
    if (last != '\n') {
        if (!ncol)                  /* is ncols set?, if not */
            ncol = cols;            /* set it */
        else if (cols != ncol) {    /* otherwise, if not correct - error */
            fprintf (stderr, "error: unequal number of cols at row *'%d'\n",
                    rows);
            return 1;
        }
        cols = 0;   /* reset column index  */
        rows++;     /* increment row index */
    }

    printf ("board: %d x %d\n\n", rows, ncol);
    for (int i = 0; i < ndx; i++) {
        if (i && i % ncol == 0)
            putchar ('\n');
        printf (" %c", lengths[i]);
    }
    putchar ('\n');

    return 0;
}

板输入文件示例

$ cat dat/board.txt
01234
56789
abcde
fghij

示例使用/输出

$ ./bin/boardread <dat/board_neol.txt
board: 4 x 5

 0 1 2 3 4
 5 6 7 8 9
 a b c d e
 f g h i j

查看如何执行读取以及如何完成验证。当您看完面向字符的内容后,请阅读 fgetc ,想想使用 fgets面向行输入可以使整个读取变得多么简单。读取每一行,然后简单调用 strlen验证长度(考虑到 '\n' 在读取中包含 fgets。如果您有任何问题,请告诉我。

关于c - 如何将位于结构体中的二维数组中的每个字符保存并加载到文件中? C,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41007784/

相关文章:

c - 队列数据结构实现

c - C11 中多参数 C 函数的泛型

c - 如何将txt文件放入文件夹C编程

c - C 中的共享日志文件 - 如何?

php - 从 mysql 导入的数组有效,但 php 不能将数组用作数组?

arrays - 使用 Node 仅使用对象键的值查找对象数组的索引

VC 中的复杂 double

php - Javascript:通过post发送数组

java - JSON 对象如果重复则不应添加

c++ - 常量数组和常量指针的重载函数