c - 读取矩阵的字符串和整数

标签 c

所以我试图从这样的文件中加载信息:

TREE 1 2
BURN 5 6
...


我代码上的所有内容都运行良好,但是在读取文件的过程中,它读取了第一行并停留在那里。这是我在做什么:

int lines=0, columns=0, MAX=5;
FILE *file=NULL;
char *string;

...

string=(char *)malloc(sizeof(char)*MAX);

while ((fscanf(file, "%s %d %d", string, &lines, &colums))!=EOF) { 
    matrix[lines][colums]=string;
    string=NULL;
}


这是代码中唯一无法正常工作的部分,其他所有工作都很好。文件打开,矩阵正确分配。它只是在1行被阻塞。 “ ...”只是分配40x40矩阵的一部分。

先感谢您!

最佳答案

将文件中的信息加载到矩阵中并不难,但是您的代码有很多方面令人困惑。首先,您似乎正在创建一个40 x 40矩阵,然后读取一个4个字符的字符串以及其在row矩阵中的预期column40 x 40位置,尽管创建部分字符串没有错填充矩阵,您所采用的方法存在多个问题点。

如前所述,检查fscanf(...) != EOF)不正确。 Xscaf函数系列返回的匹配计数等于根据您的格式字符串进行的成功转换次数。例如,使用格式为"%s %d %d"的字符串,成功读取并将行转换为returnfscanfstring的匹配计数(因此为linescolumns)将是3return的正确用法是检查3有效转换。例如。:

fscanf (file, "%s %zu %zu", string, &lines, &columns) == 3)


(正如其他人指出的那样,最好使用像fgets这样的面向行的输入功能来读取文件的行,以防止在columns之后出现文件中的乱字符或其他格式问题,从而导致读取或转换但是,如果保证在整个输入文件中使用一致的格式,则在这种情况下可以非最佳地使用fscanf

在阅读和分配给matix的过程中,还应该检查两个其他问题。首先,您应该跟踪行索引,以确保您现在确实在matrix的末尾进行写入(例如,尝试写入41行,等等。)。例如,使用idx跟踪索引以读取/添加的行数,并且ROWS是常量40,您可以执行以下操作:

while (idx < ROWS &&    /* read each line, validate conversion */
       fscanf (file, "%s %zu %zu", string, &lines, &columns) == 3) {
...

    idx++;
}


其次,您需要对照lines40检查columns的值以及字符串的长度(包括nul终止符),以确保其长度不超过matix的末尾(例如放置超过row or column 39的字符。假设您的字符串的最大长度为5(4个字符+ 1),并且常量COLS定义为40,则可以在阅读开始时执行以下操作环:

    if (lines >= ROWS) { /* validate row position for string */
        fprintf (stderr, "warning: invalid row index, line '%zu'\n",
                idx);
        continue;
    }

    if (columns + MAX + 1 >= COLS) { /* validate position for string */
        fprintf (stderr, "warning: invalid columns + MAX, line '%zu'\n",
                 idx);
        continue;
    }


如果打算将matrix打印为字符串以确认代码,则还必须处理0列与位于string列的columns开头之间的字符。如果需要,可以使用快速memset进行处理。例如。:

    memset (matrix[lines], ' ', columns);


(您还需要确认从文件读取的linescolumns是从零开始还是从一开始)

最后,无需动态声明string。您知道string不能超过40,并且出于示例输入的目的,它也不能超过5,因此,简单的静态声明大小为5的字符数组就足够了。

将所有部分放在一起,并仅为示例的打印目的添加maxrow限制,您可以执行以下操作:

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

#define ROWS 40
#define COLS 40
#define MAX 5

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

    char matrix[ROWS][COLS] = {{0}};
    char string[MAX] = {0};
    FILE *file = argc > 1 ? fopen (argv[1], "r") : stdin;
    size_t lines, columns, idx, maxrow, i;
    lines = columns = idx = maxrow = i = 0;

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

    while (idx < ROWS &&    /* read each line, validate conversion */
        fscanf (file, "%s %zu %zu", string, &lines, &columns) == 3) {

        if (lines >= ROWS) { /* validate row position for string */
            fprintf (stderr, "warning: invalid row index, line '%zu'\n",
                    idx);
            continue;
        }

        if (columns + MAX + 1 >= COLS) { /* validate position for string */
            fprintf (stderr, "warning: invalid columns + MAX, line '%zu'\n",
                    idx);
            continue;
        }

        memset (matrix[lines], ' ', columns);     /* set leading spaces    */
        strcpy (&matrix[lines][columns], string); /* copy string to matrix */

        maxrow = lines > maxrow ? lines : maxrow; /* track max row filled  */
        idx++;
    }
    if (file != stdin) fclose (file);

    for (i = 0; i < maxrow + 1; i++)  /* simple test print of matrix */
        printf (" %s\n", matrix[i]);

    return 0;
}


(注意:如果您的编译器无法处理输入/转换为size_t(例如%zu),则可以将声明更改为int。选择size_t的目的是linescolumns不能否定的。选择适当的类型可使编译器提供其他警告)

编译

始终在启用警告的情况下进行编译。例:

gcc -Wall -Wextra -o bin/matrix_strings matrix_strings.c


(如果不使用gcc,则编译器将具有类似的选项)

示例/输出

使用示例输入文件将导致以下结果:

$ ./bin/matrix_strings ../dat/tb.txt

   TREE



       BURN


如果您还有其他问题,请告诉我。

关于c - 读取矩阵的字符串和整数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34645933/

相关文章:

c - 浮点: how many matching significant figures?

c - 无符号变量发生整数溢出

python - C函数执行在哪里停止

c - 对于大多数数据包,我的 TCP 校验和函数返回 0

c - valgrind 给出错误但无法找到位置

c - 编译器会在每个语句的多个比较中检查 UB 优先级吗?

C 指针,段错误

c - 在数组上下文中 int* p 和 int (*p)[] 有什么区别?

c - 如何理解 "return *test== ‘\0’ ;"

c - 在 C 中打印字符串数组时出错