LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 2028|回复: 7

为何strsep只能够操作堆中的字符串呢?

[复制链接]
发表于 2006-11-24 11:37:46 | 显示全部楼层 |阅读模式
想要分析一个配置文件,格式例如下:
channel = 1-9,20,3,12-15
如果我定义我的配置item的结构体如下:

  1. struct item
  2. {
  3.    char name[32]; //配置项的名字不会超过31个字符
  4.    char value[128]; //其值也控制在一定的范围内,所以就这样声明了
  5.    struct item *next;
  6. }
复制代码

这时,如果我用strsep来分析我的value,将发生段错误,但是如果我声明成这个样子:

  1. struct item
  2. {
  3.    char name[32];
  4.    char *value; //由malloc来分配
  5.    struct item *next;
  6. }
复制代码

strsep就能够正常的工作了。
这就有点让人不理解了,难道strsep仅仅能够对堆中的数据进行操作???
发表于 2006-11-24 14:06:33 | 显示全部楼层
为struct填值的代码和调用strsep的代码贴来看看
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-24 18:48:58 | 显示全部楼层

这是我写的测试程序,其中还有问题--没有检测value的有效性

  1. #include <stdio.h>
  2. #include <string.h>
  3. struct item
  4. {
  5.         char name[32];
  6.         char *value;
  7.         struct item *next;
  8. };
  9. int main()
  10. {
  11.         char *channel,*start,*end;
  12.         struct item test;
  13.         snprintf(test.name,31,"%s", "channel");
  14.         test.value = (char *)malloc(128);
  15.         snprintf(test.value,127,"%s","1-15,17-31,43,55");
  16.        
  17.         if(!strcasecmp(test.name,"channel"))
  18.         {
  19.                 while(channel = strsep(&test.value,","))
  20.                 {
  21.                         start = strsep(&channel,"-");
  22.                         if(channel)
  23.                         {
  24.                                 end = channel;
  25.                                 printf("include channel start from %s to %s\n",start,end);
  26.                         }
  27.                         else
  28.                                 printf("include channel %s\n",start);
  29.                 }
  30.         }
  31.         return 0;
  32. }
  33. [root@localhost program]# ./strsep
  34. include channel start from 1 to 15
  35. include channel start from 17 to 31
  36. include channel 43
  37. include channel 55
  38. #include <stdio.h>
  39. #include <string.h>
  40. struct item
  41. {
  42.         char name[32];
  43.         char value[128];
  44.         struct item *next;
  45. };
  46. int main()
  47. {
  48.         char *channel,*start,*end;
  49.         struct item test;
  50.         snprintf(test.name,31,"%s", "channel");
  51.         //test.value = (char *)malloc(128);
  52.         snprintf(test.value,127,"%s","1-15,17-31,43,55");
  53.        
  54.         if(!strcasecmp(test.name,"channel"))
  55.         {
  56.                 while(channel = strsep(&test.value,","))
  57.                 {
  58.                         start = strsep(&channel,"-");
  59.                         if(channel)
  60.                         {
  61.                                 end = channel;
  62.                                 printf("include channel start from %s to %s\n",start,end);
  63.                         }
  64.                         else
  65.                                 printf("include channel %s\n",start);
  66.                 }
  67.         }
  68.         return 0;
  69. }
  70. [root@localhost program]# ./strsep
  71. Segmentation fault
复制代码
回复 支持 反对

使用道具 举报

发表于 2006-11-25 18:48:58 | 显示全部楼层
strsep要修改传进去的指针的,第二个例子中你传的test.value是个不可修改的常量指针,所以出错了
回复 支持 反对

使用道具 举报

发表于 2006-11-25 18:55:22 | 显示全部楼层
  1. int main()
  2. {
  3.         char *channel,*start,*end;
  4.         struct item test;
  5.         snprintf(test.name,31,"%s", "channel");
  6.         test.value = (char *)malloc(128);
  7.         snprintf(test.value,127,"%s","1-15,17-31,43,55");
  8.        
  9.         if(!strcasecmp(test.name,"channel"))
  10.         {
  11.                 char * temp = (char*)test.value;     /////////////   notice    ////////////
  12.                 while(channel = strsep(&temp,","))  //////////////////////////////////////
  13.                 {
  14.                         start = strsep(&channel,"-");
  15.                         if(channel)
  16.                         {
  17.                                 end = channel;
  18.                                 printf("include channel start from %s to %s\n",start,end);
  19.                         }
  20.                         else
  21.                                 printf("include channel %s\n",start);
  22.                 }
  23.         }
  24.         return 0;
  25. }
复制代码

char ** 和 char *[] 是两个不同的类型,至于为什么会出错,跟这个类型应该有关,你可以查看一下glibc关于该函数的实现, 我手上暂时没有
回复 支持 反对

使用道具 举报

发表于 2006-11-25 23:43:38 | 显示全部楼层
改成这样就ok了
  1. #include <stdio.h>
  2. #include <string.h>
  3. struct item
  4. {
  5.         char name[32];
  6.         char value[128];
  7.         struct item *next;
  8. };
  9. int main()
  10. {
  11.         char *channel,*start,*end,*p;
  12.         struct item test;
  13.         snprintf(test.name,31,"%s", "channel");
  14.         //test.value = (char *)malloc(128);
  15.         snprintf(test.value,127,"%s","1-15,17-31,43,55");
  16.        
  17.         if(!strcasecmp(test.name,"channel"))
  18.         {
  19.                 p = test.value;
  20.                 while(channel = strsep(&p,","))
  21.                 {
  22.                         start = strsep(&channel,"-");
  23.                         if(channel)
  24.                         {
  25.                                 end = channel;
  26.                                 printf("include channel start from %s to %s\n",start,end);
  27.                         }
  28.                         else
  29.                                 printf("include channel %s\n",start);
  30.                 }
  31.         }
  32.         return 0;
  33. }
复制代码
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-27 11:11:22 | 显示全部楼层
多谢各位,不过我一直都没有注意过char ** 和char *[]的区别,因为总是看到 int main(int argc, char *argv[]) 和int main(int argc, char **argv)这两种写法,似乎都把这两种类型当着一样的而没有区分。去看看这两个究竟有什么区别!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2006-11-27 11:27:48 | 显示全部楼层
看了一圈,大致明白char ** 和char *[]的区别了,确切的说在strsep里是因为char * 和char []这两者的区别引起的。char *纯粹是一个指针,它指向的地方可以更改,而char []虽然平时把它和char *同等对待,但是它所指向的地方却不能更改。
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表