Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/56.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在C中使用Strtok()对2d数组进行分段错误_C_Strtok - Fatal编程技术网

在C中使用Strtok()对2d数组进行分段错误

在C中使用Strtok()对2d数组进行分段错误,c,strtok,C,Strtok,在尝试将字符串(如“1,2,3;4,5,6;7,8,9”)拆分为2d数组时,我不断遇到分段错误。为什么这段代码总是出现这种情况?有人能给我解释一下吗 int main(void){ char string[100]; char *token; char *end; int num; int row_counter; int column_counter; int counter_position; char *rows[100];

在尝试将字符串(如“1,2,3;4,5,6;7,8,9”)拆分为2d数组时,我不断遇到分段错误。为什么这段代码总是出现这种情况?有人能给我解释一下吗

int main(void){
    char string[100];
    char *token;
    char *end;
    int num;
    int row_counter;
    int column_counter;
    int counter_position;
    char *rows[100];
    int square_ints[40][40];

    row_counter = 0;
    column_counter = 0;
    string[] = "1,2,3;4,5,6;7,8,9";
    token = strtok(string, ";");
    rows[row_counter] = token;
    row_counter++;
    while (token != NULL){
        token = strtok(NULL, ";");
        rows[row_counter] = token;
        row_counter++;
    }

    counter_position = row_counter;

    for (row_counter = 0; row_counter < counter_position; row_counter++) {
        token = strtok(rows[row_counter], ",");
        num = strtol(token, &end, 10);
        square_ints[row_counter][column_counter] = num;
        printf("%d\n", square_ints[row_counter][column_counter]);
        column_counter++;
        while (token != NULL) {
            token = strtok(NULL, ",");
            num = strtol(token, &end, 10);
            square_ints[row_counter][column_counter] = num;
            printf("%d\n", square_ints[row_counter][column_counter]);
            column_counter++;
        }
    }
}
int main(无效){
字符串[100];
字符*令牌;
字符*结束;
int-num;
int row_计数器;
int列_计数器;
int计数器位置;
字符*行[100];
整数平方(整数[40][40];;
行计数器=0;
列_计数器=0;
字符串[]=“1,2,3;4,5,6;7,8,9”;
令牌=strtok(字符串“;”);
行[行计数器]=令牌;
行计数器++;
while(令牌!=NULL){
令牌=strtok(空,“;”);
行[行计数器]=令牌;
行计数器++;
}
计数器位置=行计数器;
用于(行计数器=0;行计数器<计数器位置;行计数器++){
令牌=strtok(行[行计数器],“,”);
num=strtol(标记和结束,10);
平方整数[行计数器][列计数器]=num;
printf(“%d\n”,平方整数[行计数器][列计数器]);
列_计数器++;
while(令牌!=NULL){
令牌=strtok(空,“”,“”);
num=strtol(标记和结束,10);
平方整数[行计数器][列计数器]=num;
printf(“%d\n”,平方整数[行计数器][列计数器]);
列_计数器++;
}
}
}
它应该是打印的:1 2 3 4 5 6 7 8 9相反,我得到1 2 3分段错误来扩展MikeCAT提到的内容:

作为
for
循环的开始,您需要:

token = strtok(rows[row_counter], ",");
num = strtol(token, &end, 10);
稍后你会:

token = strtok(NULL, ",");
num = strtol(token, &end, 10);
问题是,在这两种情况下,
strtok
将返回
NULL
,因此
token
的值是
NULL
。当您将
token
传递给
strtol
时,它将尝试使用/取消引用该标记,并将产生segfault

因此,要解决此问题,在每次调用strtok后,您需要添加:

if (token == NULL)
    break;

这是正确的代码。我添加了一些调试
printf
,因此您可以看到问题

我使用了
cpp
条件来区分新旧代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif
无论如何,这是:

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

#ifdef DEBUG
#define dbgprt(_fmt...) \
    do { \
        printf(_fmt); \
    } while (0)
#else
#define dbgprt(_fmt...) \
    do { \
    } while (0)
#endif

int
main(void)
{
#if 0
    char string[100];
#else
    char string[] = "1,2,3;4,5,6;7,8,9";
#endif
    char *token;
    char *end;
    int num;
    int row_counter;
    int column_counter;
    int counter_position;
    char *rows[100];
    int square_ints[40][40];

    row_counter = 0;
    column_counter = 0;
#if 0
    string[] = "1,2,3;4,5,6;7,8,9";
#endif
    token = strtok(string, ";");
    rows[row_counter] = token;
    row_counter++;
    while (token != NULL) {
        token = strtok(NULL, ";");
        rows[row_counter] = token;
        row_counter++;
    }

    counter_position = row_counter;

    for (row_counter = 0; row_counter < counter_position; row_counter++) {
        dbgprt("DEBUG: rows[%d]='%s'\n",row_counter,rows[row_counter]);
        token = strtok(rows[row_counter], ",");
        dbgprt("DEBUG: token='%s'\n",token);
#if 1
        if (token == NULL)
            break;
#endif
        num = strtol(token, &end, 10);
        square_ints[row_counter][column_counter] = num;
        printf("%d\n", square_ints[row_counter][column_counter]);
        column_counter++;
        while (token != NULL) {
            token = strtok(NULL, ",");
            dbgprt("DEBUG2: token='%s'\n",token);
#if 1
            if (token == NULL)
                break;
#endif
            num = strtol(token, &end, 10);
            square_ints[row_counter][column_counter] = num;
            printf("%d\n", square_ints[row_counter][column_counter]);
            column_counter++;
        }
    }

    return 0;
}

还有另一个类似的函数
strep
,被一些人认为是“strtok done right”。以下是使用该功能的版本:

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

int
main(void)
{
    char string[] = "1,2,3;4,5,6;7,8,9";
    char *token;
    char *end;
    int num;
    int row_counter;
    int column_counter;
    int counter_position;
    char *bp;
    char *rows[100];
    int square_ints[40][40];

    row_counter = 0;
    column_counter = 0;

    bp = string;
    while (1) {
        token = strsep(&bp,";");
        if (token == NULL)
            break;
        rows[row_counter] = token;
        row_counter++;
    }

    counter_position = row_counter;

    for (row_counter = 0; row_counter < counter_position; row_counter++) {
        bp = rows[row_counter];
        if (bp == NULL)
            break;

        while (1) {
            token = strsep(&bp,",");
            if (token == NULL)
                break;

            num = strtol(token, &end, 10);
            square_ints[row_counter][column_counter] = num;
            printf("%d\n", square_ints[row_counter][column_counter]);
            column_counter++;
        }
    }

    return 0;
}
#包括
#包括
#包括
int
主(空)
{
字符字符串[]=“1,2,3;4,5,6;7,8,9”;
字符*令牌;
字符*结束;
int-num;
int row_计数器;
int列_计数器;
int计数器位置;
char*bp;
字符*行[100];
整数平方(整数[40][40];;
行计数器=0;
列_计数器=0;
bp=字符串;
而(1){
标记=strep(&bp,“;”);
if(标记==NULL)
打破
行[行计数器]=令牌;
行计数器++;
}
计数器位置=行计数器;
用于(行计数器=0;行计数器<计数器位置;行计数器++){
bp=行[行计数器];
如果(bp==NULL)
打破
而(1){
标记=strep(&bp,“,”);
if(标记==NULL)
打破
num=strtol(标记和结束,10);
平方整数[行计数器][列计数器]=num;
printf(“%d\n”,平方整数[行计数器][列计数器]);
列_计数器++;
}
}
返回0;
}
要扩展MikeCAT提到的内容:

作为
for
循环的开始,您需要:

token = strtok(rows[row_counter], ",");
num = strtol(token, &end, 10);
稍后你会:

token = strtok(NULL, ",");
num = strtol(token, &end, 10);
问题是,在这两种情况下,
strtok
将返回
NULL
,因此
token
的值是
NULL
。当您将
token
传递给
strtol
时,它将尝试使用/取消引用该标记,并将产生segfault

因此,要解决此问题,在每次调用strtok后,您需要添加:

if (token == NULL)
    break;

这是正确的代码。我添加了一些调试
printf
,因此您可以看到问题

我使用了
cpp
条件来区分新旧代码:

#if 0
// old code
#else
// new code
#endif

#if 1
// new code
#endif
无论如何,这是:

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

#ifdef DEBUG
#define dbgprt(_fmt...) \
    do { \
        printf(_fmt); \
    } while (0)
#else
#define dbgprt(_fmt...) \
    do { \
    } while (0)
#endif

int
main(void)
{
#if 0
    char string[100];
#else
    char string[] = "1,2,3;4,5,6;7,8,9";
#endif
    char *token;
    char *end;
    int num;
    int row_counter;
    int column_counter;
    int counter_position;
    char *rows[100];
    int square_ints[40][40];

    row_counter = 0;
    column_counter = 0;
#if 0
    string[] = "1,2,3;4,5,6;7,8,9";
#endif
    token = strtok(string, ";");
    rows[row_counter] = token;
    row_counter++;
    while (token != NULL) {
        token = strtok(NULL, ";");
        rows[row_counter] = token;
        row_counter++;
    }

    counter_position = row_counter;

    for (row_counter = 0; row_counter < counter_position; row_counter++) {
        dbgprt("DEBUG: rows[%d]='%s'\n",row_counter,rows[row_counter]);
        token = strtok(rows[row_counter], ",");
        dbgprt("DEBUG: token='%s'\n",token);
#if 1
        if (token == NULL)
            break;
#endif
        num = strtol(token, &end, 10);
        square_ints[row_counter][column_counter] = num;
        printf("%d\n", square_ints[row_counter][column_counter]);
        column_counter++;
        while (token != NULL) {
            token = strtok(NULL, ",");
            dbgprt("DEBUG2: token='%s'\n",token);
#if 1
            if (token == NULL)
                break;
#endif
            num = strtol(token, &end, 10);
            square_ints[row_counter][column_counter] = num;
            printf("%d\n", square_ints[row_counter][column_counter]);
            column_counter++;
        }
    }

    return 0;
}

还有另一个类似的函数
strep
,被一些人认为是“strtok done right”。以下是使用该功能的版本:

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

int
main(void)
{
    char string[] = "1,2,3;4,5,6;7,8,9";
    char *token;
    char *end;
    int num;
    int row_counter;
    int column_counter;
    int counter_position;
    char *bp;
    char *rows[100];
    int square_ints[40][40];

    row_counter = 0;
    column_counter = 0;

    bp = string;
    while (1) {
        token = strsep(&bp,";");
        if (token == NULL)
            break;
        rows[row_counter] = token;
        row_counter++;
    }

    counter_position = row_counter;

    for (row_counter = 0; row_counter < counter_position; row_counter++) {
        bp = rows[row_counter];
        if (bp == NULL)
            break;

        while (1) {
            token = strsep(&bp,",");
            if (token == NULL)
                break;

            num = strtol(token, &end, 10);
            square_ints[row_counter][column_counter] = num;
            printf("%d\n", square_ints[row_counter][column_counter]);
            column_counter++;
        }
    }

    return 0;
}
#包括
#包括
#包括
int
主(空)
{
字符字符串[]=“1,2,3;4,5,6;7,8,9”;
字符*令牌;
字符*结束;
int-num;
int row_计数器;
int列_计数器;
int计数器位置;
char*bp;
字符*行[100];
整数平方(整数[40][40];;
行计数器=0;
列_计数器=0;
bp=字符串;
而(1){
标记=strep(&bp,“;”);
if(标记==NULL)
打破
行[行计数器]=令牌;
行计数器++;
}
计数器位置=行计数器;
用于(行计数器=0;行计数器<计数器位置;行计数器++){
bp=行[行计数器];
如果(bp==NULL)
打破
而(1){
标记=strep(&bp,“,”);
if(标记==NULL)
打破
num=strtol(标记和结束,10);
平方整数[行计数器][列计数器]=num;
printf(“%d\n”,平方整数[行计数器][列计数器]);
列_计数器++;
}
}
返回0;
}

编译时调用as
gcc-Wall-Wextra-g
然后使用行
字符串[]={“1,2,3;4,5,6;7,8,9”}将导致编译错误,因此不应发生分段错误。请发布一个。在
for
循环中,您忘记将
列\u计数器
重置为零。您必须检查
令牌!=更新
token
后和执行
num=strtol(token,&end,10)前为NULL@MikeCAT你什么意思?抱歉,我是C新手,我刚刚添加了一个if语句,其中您说的是,它与调用的as
gcc-Wall-Wextra-g
没有区别,compile使用
string[]={“1,2,3;4,5,6;7,8,9”}将导致编译错误,因此没有分段Fau