在 C 中,strtok() 适用于“,”(逗号)但不适用于空格“”。使用空格时出现段错误

In C strtok() is working for "," (commas) but not for spaces " ". Getting a seg fault when working with spaces

我是新来的。这是我的第一个post! 所以我用 C 编写了代码,以接收逗号分隔的文本文件并将其读入二维数组。我为此使用了 strtok() 。有效。下面是代码:

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

int main (int argc, char *argv[])
{
    FILE *data = fopen(argv[1], "r");

    if (data == NULL)
    {
        printf("Could not open 11.txt\n");
        return 1;
    }

    char table[20][20][3];
    char buffer[60];

    int i = 0;
    while (fscanf(data, "%s", buffer) != EOF)
    {
        int j = 0;
        for (char *s = strtok(buffer, ","); s != NULL; s = strtok(NULL, ","))
        {
            for (int k = 0; k < strlen(s) + 1; k++)
            {
                table[i][j][k] = s[k];
            }
            j++;
        }
        i++;
    }
    printf("%s\n", table[19][0]);
    return 0;
}

我试图读入二维数组的数据如下所示:

08,02,22,97
49,49,99,40
81,49,31,73
52,70,95,23

它是一个 20x20 的矩阵,数字之间用逗号分隔。 上面的程序工作正常(我打印出这个二维数组的一个元素来检查程序是否工作)。但是当数字被 spaces 分隔时:

08 02 22 97 
49 49 99 40 
81 49 31 73 
52 70 95 23 

当我在 strtok() 函数中将“,”替换为“”时,出现段错误。我不知道为什么会这样。 感谢您的帮助!

编辑: 错误已修复! 来自莫斯科的@Vlad 非常正确地指出 fcanf() 不是用于将带有白色 space 的字符串读入缓冲区的正确函数。他建议改为使用 fgets(),它可以读取白色 space。我仍然面临段错误,因为 strtok() 返回的第一个标记是指向 NULL 的指针。我不确定为什么要这样做,因为当我在 while 循环中使用相同字符串的 strtok() 数组而不使用 fgets() 时,如图所示,没有问题:

char str[] = "08 02 22 97";

因此,为了解决这个问题,我在 for 循环中放置了一个条件,如果 strtok() 返回 NULL 指针,则跳至下一次迭代。 第二个问题是我的缓冲区不够大(spaces 是 4 个字节,而 char 是 1 个字节)。解决了这两个问题后,我的代码就可以工作了!

下面是更正后的代码:

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

int main (int argc, char *argv[])
{
    FILE *data = fopen(argv[1], "r");

    if (data == NULL)
    {
        printf("Could not open 11.txt\n");
        return 1;
    }

    char table[20][20][3];
    char buffer[61];

    int i = 0;
    while (fgets(buffer, sizeof(buffer), data) != NULL)
    {
        int j = 0;
        for (char *s = strtok(buffer, " "); s != NULL; s = strtok(NULL, " "))
        {
            if (s == NULL)
            {
                continue;
            }
            else
            {
                for (int k = 0; k < strlen(s) + 1; k++)
                {
                    table[i][j][k] = s[k];
                }
                j++;
            }
        }
        i++;
    }
    printf("%i\n", atoi(table[19][19]));
    return 0;
}

带有格式说明符 %s 的函数 fscanf 读取数据,直到遇到白色 space 字符。所以你不能像在 while 语句

中那样使用函数 fscanf
while (fscanf(data, "%s", buffer) != EOF)

读取包含嵌入白色的字符串 spaces.

而是使用标准 C 函数 fgets

注意那个而不是这个for循环

for (int k = 0; k < strlen(s) + 1; k++)
{
    table[i][j][k] = s[k];
}

您可以使用标准字符串函数 strcpy 作为例子

strcpy( table[i][j], s );

还有这个电话

printf("%s\n", table[20][0]);

调用未定义的行为,因为对于声明为

的数组
char table[20][20][3];

第一个索引的有效范围是 ]0, 20 )。那就是你不能使用值 20 作为索引。