Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/57.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 *字符数组末尾的分段错误_C_Arrays_Linux_Segmentation Fault_Memory Segmentation - Fatal编程技术网

C *字符数组末尾的分段错误

C *字符数组末尾的分段错误,c,arrays,linux,segmentation-fault,memory-segmentation,C,Arrays,Linux,Segmentation Fault,Memory Segmentation,我刚开始使用C语言,现在遇到了一个问题。我想使用以下代码将linux命令行中的字符串输入(类似于date |./date_split)拆分为一个数组,稍后我将访问和修改该数组。最初分割是有效的,但最后我发现了一个分割错误。谁能解释我做错了什么 int main() { char *indate[10]; int i= 1; char str[100][50]; fgets(&str [0], 50, stdin); const char s[2] = " "

我刚开始使用C语言,现在遇到了一个问题。我想使用以下代码将linux命令行中的字符串输入(类似于
date |./date_split
)拆分为一个数组,稍后我将访问和修改该数组。最初分割是有效的,但最后我发现了一个分割错误。谁能解释我做错了什么

int main()
{
   char *indate[10];
   int i= 1;
   char str[100][50];
   fgets(&str [0], 50, stdin);
   const char s[2] = " ";
   char *token;

  /* get the first token */
  token = strtok(str, s);
  indate[i] = malloc(strlen(token)+1);
  strcpy(indate[i], token);
  printf( "Array before: %s\n", indate[i]);     

 /* walk through other tokens */
 while( token != NULL )
{
  printf( "Token before: %s\n", token );

  token = strtok(NULL, s);
  indate[i] = malloc(strlen(token)+1);
  strcpy(indate[i], token);

printf( "Token2 After: %s\n", token );
printf( "Array2 After: %s\n", indate[i]);     
i++;   
}

    return(0);
}
它提供终端输出:

Array before: Thu
Token before: Thu
Token2 After: 20
Array2 After: 20
Token before: 20
Token2 After: Oct
Array2 After: Oct
Token before: Oct
Token2 After: 11:37:56
Array2 After: 11:37:56
Token before: 11:37:56
Token2 After: EDT
Array2 After: EDT
Token before: EDT
Token2 After: 2016

Array2 After: 2016

Token before: 2016

Segmentation fault (core dumped)
来自strtok()手册

返回值 strtok()和strtok_r()函数返回指向下一个 令牌,如果没有更多令牌,则为NULL

一旦不再有令牌,
token
包含一个空指针,因此
strlen(令牌)
seg故障。请参见strtok()手册中的

返回值 strtok()和strtok_r()函数返回指向下一个 令牌,如果没有更多令牌,则为NULL


一旦不再有令牌,
token
包含一个空指针,因此
strlen(令牌)
seg故障。请参阅程序的问题:日期组件的索引,
i
,从1开始,而不是0(这是一个非常糟糕的变量名),并且没有持续更新(第一个条目被覆盖);
str();您假设第一个
strtok()
成功,但输入错误的情况可能不是这样;在使用结果之前,不测试后续的
strtok()
调用是否成功;您没有尝试
free()
内存
malloc()
,甚至丢失了一些内存

下面是对原始代码的重做,它还添加了一些错误检查和其他细节:

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

#define MAXIMUM_TOKENS 16
#define MAXIMUM_TOKEN_LENGTH 32

const char *separator = " ";

int main()
{
    char string[(MAXIMUM_TOKEN_LENGTH + strlen(separator)) * MAXIMUM_TOKENS + 1]; // estimate

    char *result = fgets(string, sizeof(string), stdin);

    if (result == NULL)
    {
        fprintf(stderr, "An appropriate error message goes here.\n");
        return EXIT_FAILURE;
    }

    /* strip final newline (\n) if present */
    size_t last_index = strlen(string) - 1;

    if (string[last_index] == '\n')
    {
        string[last_index] = '\0';
    }

    /* get the first token */
    char *token = strtok(string, separator);

    char *date_parts[MAXIMUM_TOKENS];
    int date_parts_index = 0;

    /* walk through other tokens */
    while (token != NULL)
    {
        date_parts[date_parts_index++] = strdup(token);
        token = strtok(NULL, separator);
    }

    /* print the tokens and free the strdup/malloc memory */
    for (int i = 0; i < date_parts_index; i++)
    {
        (void) puts(date_parts[i]);
        free(date_parts[i]);
    }

    return EXIT_SUCCESS;
}

尽管这是对strtok()的适当使用,但要小心。它是早期的产物,应该避免使用更安全的现代库函数,如
strep()
strtok_r()
,程序问题:日期组件的索引
i
,从1开始,而不是从0开始(这是一个可怕的变量名),并且更新不一致(第一个条目被覆盖)
str()数组是一个总的混乱分配方式(例如,两个维度,仅使用一个);您假设第一个
strtok()
成功,但可能不是输入错误的情况;您不测试后续的
strtok()是否成功
调用成功,直到您已经使用了结果;您没有尝试
free()
malloc()
的内存,甚至丢失了一些内存

下面是对原始代码的重做,它还添加了一些错误检查和其他细节:

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

#define MAXIMUM_TOKENS 16
#define MAXIMUM_TOKEN_LENGTH 32

const char *separator = " ";

int main()
{
    char string[(MAXIMUM_TOKEN_LENGTH + strlen(separator)) * MAXIMUM_TOKENS + 1]; // estimate

    char *result = fgets(string, sizeof(string), stdin);

    if (result == NULL)
    {
        fprintf(stderr, "An appropriate error message goes here.\n");
        return EXIT_FAILURE;
    }

    /* strip final newline (\n) if present */
    size_t last_index = strlen(string) - 1;

    if (string[last_index] == '\n')
    {
        string[last_index] = '\0';
    }

    /* get the first token */
    char *token = strtok(string, separator);

    char *date_parts[MAXIMUM_TOKENS];
    int date_parts_index = 0;

    /* walk through other tokens */
    while (token != NULL)
    {
        date_parts[date_parts_index++] = strdup(token);
        token = strtok(NULL, separator);
    }

    /* print the tokens and free the strdup/malloc memory */
    for (int i = 0; i < date_parts_index; i++)
    {
        (void) puts(date_parts[i]);
        free(date_parts[i]);
    }

    return EXIT_SUCCESS;
}

尽管这是strtok()的恰当用法,但要小心。它是早期的产物,应该避免使用更安全的现代库函数,如strep()和strtok_r()
fgets(&str[0],50,stdin);
在我看来是错误的。您正在传递一个
char**
值,而不是
char*
。编译此代码时是否启用了警告?请尝试将
-Wall
添加到命令行选项中。编辑:
token=strtok(str,s);
也是错误的;
str
应该是
char*
,而不是
char**
。这将是开始学习如何使用a的好时机。正如你所说,它确实在fgets上给了我警告,我不知道存在调试器。谢谢你让我知道!我已经找到了如何让它在没有分段错误的情况下运行的方法,when在更新数组之前,我添加了一个
if(token==Null){break;}
。但我仍然不知道为什么会这样做!
fgets(&str[0],50,stdin);
在我看来是错误的。您正在传递一个
char**
值,而不是
char*
。编译此代码时是否启用了警告?请尝试将
-Wall
添加到命令行选项中。编辑:
token=strtok(str,s);
也是错误的;
str
应该是
char*
,而不是
char**
。这将是开始学习如何使用a的好时机。正如你所说,它确实在fgets上给了我警告,我不知道存在调试器。谢谢你让我知道!我已经找到了如何让它在没有分段错误的情况下运行的方法,whe我添加一个
if(token==Null){break;}
在更新数组之前。但我仍然不知道为什么会这样!哇,这比我之前写的要好得多,非常感谢!我会牢记你的建议,并据此修改我写的内容哇,这比我之前写的好得多,非常感谢!我会牢记你的建议并修改至少我已经写了相应的信