繁体   English   中英

来自“ strsep”的字符串标记不打印(seg错误)

[英]String token from `strsep` not printing (seg fault)

我正在使用一小段代码来测试较大(初学者)程序的功能,但是在显示从字符串中拔出的令牌时遇到问题。

我发现并使用了:

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

int main()
{

char *string, *found;

string = strdup ("1/2/3");
printf("Original string: '%s'\n",string);

while ((found = strsep(&string,"/")) != NULL )
  printf ("%s\n",found);

return (0);
}

并且工作正常,一次将标记作为字符串打印一次。

然后,当我尝试移动到用户输入的字符串时:

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

int main()
{
  char string[13];
  char *found, *cp = string;

  fprintf(stderr, "\nEnter string: ");
  scanf("%12s",string);
  printf("Original string: '%s'\n",string);

  while((found =  strsep(&cp,"/,-")) != NULL )
    printf("Test 1"); /*To pinpoint where the seg fault arises*/
    printf("%s\n",found);

  return(0);
}

我在printf("%s\\n",found);上遇到段错误printf("%s\\n",found); 线。 我掌握了指针,数组和字符串的基础知识,但显然我缺少了一些东西,希望有人告诉我它是什么!

另外-如果我更改了printf("%s\\n",found); 例如到printf("%i\\n",found); 我得到一些随机性,但总是正确的数量,例如,如果我输入1/2/3我将得到三行垃圾,输入1111/2222将得到两行。 我尝试了%c,%i,%d,%p,它们都执行相同的操作,但是出现了%s seg错误。

我完全迷住了。

出现段错误的原因是您while缺少括号。 您将继续打印“ Test 1”,直到strsep返回NULL ,然后尝试打印该结果(和segfault)。

使用几个警告标志(可能是-Wall ),gcc可以在这里帮助您:

sep.c:13:3: warning: this ‘while’ clause does not guard... [-Wmisleading-indentation]
   while((found =  strsep(&cp,"/,-")) != NULL )
   ^~~~~
sep.c:15:5: note: ...this statement, but the latter is misleadingly indented as if it is guarded by the ‘while’
     printf("%s\n",found);
     ^~~~~~

while周围添加大括号,该程序将按预期工作:

./sep 

Enter string: abc/def
Original string: 'abc/def'
Test 1abc
Test 1def

这就是问题:

while((found =  strsep(&cp,"/,-")) != NULL )
    printf("Test 1"); /*To pinpoint where the seg fault arises*/
    printf("%s\n",found);

并且您认为自己在循环中同时执行了两个printf ,但实际上此代码等效于

while((found =  strsep(&cp,"/,-")) != NULL )
{
    printf("Test 1"); /*To pinpoint where the seg fault arises*/
}
    printf("%s\n",found);

这意味着, printf("%s\\n",found); 基本上是在做printf("%s\\n",NULL); 这是未定义的行为,可能会导致段错误。

请注意,在C语言中,缩进与编译器无关紧要。 因此,您需要在代码周围使用{}

while((found =  strsep(&cp,"/,-")) != NULL )
{
    printf("Test 1"); /*To pinpoint where the seg fault arises*/
    printf("%s\n",found);
}

这样做我得到

$ ./a 

Enter string: aa/bb/cc/dd
Original string: 'aa/bb/cc/dd'
Test 1aa
Test 1bb
Test 1cc
Test 1dd

还要注意,您的第一个代码正在泄漏内存,您没有释放strdup返回的已分配内存。 您将必须保存一个指向的指针:

#include <stdio.h>
#include <stdlib.h> // for the free function
#include <string.h>

int main()
{

    char *orig = *string, *found;

    orig = string = strdup ("1/2/3");
    printf("Original string: '%s'\n",string);

    while ((found = strsep(&string,"/")) != NULL )
      printf ("%s\n",found);

    free(orig);

    return 0;
}

编辑

Stephen Newell和我似乎都没有对纠正后的代码版本有相同的问题。 OP提供了一个指向onlinegdb.com的链接,该链接显示已更正的版本以segfault结尾。

我在ideone.com上尝试了相同的代码,并且也遇到了段错误。 这对我来说似乎很奇怪,因此我打开了strsep手册页并发现了这一点:

曼斯特雷普

概要

  #include <string.h> char *strsep(char **stringp, const char *delim); 

glibc的功能测试宏要求(请参阅feature_test_macros(7)):

strsep()

 Since glibc 2.19: _DEFAULT_SOURCE Glibc 2.19 and earlier: _BSD_SOURCE 

重要的部分在这里: 从glibc 2.19开始: _DEFAULT_SOURCE

因此,如果您添加

#define _DEFAULT_SOURCE

在包含任何标准C头文件之前,该文件可在onlinegdb.com和ideone.com上运行。

因此,代码应为:

#define _DEFAULT_SOURCE   // <-- important
#include <stdio.h>
#include <string.h>

int main()
{
  char string[13];
  char *found, *cp = string;

  fprintf(stderr, "\nEnter string: ");
  scanf("%12s",string);
  printf("Original string: '%s'\n",string);

  while((found =  strsep(&cp,"/,-")) != NULL )
    {
    printf("Test 1"); /*To pinpoint where the seg fault arises*/
    printf("%s\n",found);
    }

  return(0);
}

看到:

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM