C使用字符串和SEGFAULT

时间:2013-12-04 00:34:46

标签: c pointers segmentation-fault

你好,抱歉我的英语不好 我从C语言开始,但我没有得到很好的指示...
我搜索了类似的主题,但我没有从他们那里得到它,所以我创建了自己的主题 我有主要功能,我称之为函数newSpeak 有我的newSpeak代码,但没有一切......

char * newSpeak ( const char * text, const char * (*replace)[2] )
{
int i;
char * alpha;
for(i=0;i<4;i++)
    {
        alpha=strstr(text, replace[0][4]);
        if(alpha[0])
            strncpy (alpha,replace[1][0],10);   
    }
return 0;

}


谢谢回答 编辑:我找到了问题的根源。 它工作,当我不用于循环并运行一次。但即使周期中的条件为i <1,它也不起作用,这应该只使它运行一次......这对我来说很奇怪......

2 个答案:

答案 0 :(得分:2)

该行

 strncpy (alpha,replace[1][0],10);   

应该生成编译器警告(并且永远不会忽略编译器警告)。函数原型是

char *strncpy( char *dest, char *source, int n);

但是你传递的是replace[1][0]这是一个角色。如果您通过了

,它可能会有效
strncpy( alpha, &replace[1][0], 10);

即便如此,我仍然担心。可能是因为alpha指向由text const char*指向的块中的内存块,所以不允许修改该内存。

编辑我认为我的第一点是错的 - 我误读了你的原型。但我很确定第二点是有效的(可能是段错误的原因)。

第二次修改 text可能没有足够的内存分配来从replace复制10个字符。意识到你匹配的东西(replace[0][4])和你正在复制的东西(replace[1][0]])不是一回事;另外,你正在循环i但没有使用那个值...让我想知道是否存在拼写错误(我不是透视,也无法弄清楚你想要从循环到循环改变什么)。

您需要检查要复制的内容的大小:

strncpy(alpha, replace[1][0], (strlen(alpha)<10)?strlen(alpha):10);

将确保您复制不超过10个字符,并且不会超过alpha中的空格。

这是“最重要的”已经指出的所有内容(使用if (alpha!=NULL)代替if(alpha[0])是一个很大的。)

编辑3 - 我想我现在已经解决了您的代码中的大部分问题...请参阅http://codepad.org/YK5VyGAn了解一个小的“工作”示例。

您的代码存在问题:

  1. 您将text声明为const char*,然后继续修改
  2. 您将replace声明为const char* (*replace)[2],然后地址元素replace[0][4](4> 2 ...)
  3. 您将strstr的返回值指定为alpha;这可能是NULL(不匹配),但您要测试alpha[0](如果alpha == NULL则会失败。)
  4. 当您复制替换字符串时,您复制了“最多10个字符” - 无论(a)目标字符串是否可以容纳此字符串,以及(b)源字符串是否包含这么多字符。结果可能是您复制完整的源字符串(包括终止'\ 0'),以便之后找不到另一个匹配项(您已“删除”其余字符串)。然后你会遇到“strstr return NULL”错误......
  5. 不确定(没有看到您的输入字符串或“替换”字符串)这些实际上导致您的代码失败 - 我编写了一个小程序来解决所有这些错误。您可以在http://codepad.org/4jSOnmPy找到它 - 转载于此处:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #define MIN(a,b) (a>b)?(b):(a)
    
    char * newSpeak (const char *text, const char *(*replace)[5] ){
      int ii=0, n;
      char *alpha, *beta;
      printf("length of input string is %d\n", strlen(text));
      beta = malloc(strlen(text)+1);
      printf("allocated %d bytes\n", strlen(text)+1);
      fflush(stdout);
      strcpy(beta, text);
      printf("copy OK: beta now %s\n", beta);
      fflush(stdout);
      for(ii = 0; ii < 4; ii++) {
    //    alpha=strstr(beta, replace[0][0]);
        alpha=strstr(beta, "a");
        printf("alpha is '%s'\n", alpha);
        fflush(stdout);
        if(alpha!=NULL) {
          char *rs;
          rs = replace[1][ii];
          printf("ii = %d; alpha now: '%s'\n", ii, alpha);
          fflush(stdout);
          n = MIN(strlen(alpha), strlen(rs));
          printf("n is now %d\n", n);
          fflush(stdout);
          printf("going to copy at most %d characters from '%s' into '%s'\n", n, rs, alpha);
          fflush(stdout);
          strncpy (alpha,rs,n);  
          printf("beta is now '%s'\n", beta);
          fflush(stdin); 
        }
        else printf("no match found\n");
      }
      return beta;
    }
    
    int main(void) {
      char* r[2][5]={{"a","b","c","d", "e"}, {"o","e","i","u","s"}};
      char* myText = "this is a vary sally strang";
      printf("NewSpeak: %s\n", "hello world");
      printf("converted: %s\n", newSpeak(myText, r));
      return 0;
    }
    

    输出:

    NewSpeak: hello world
    length of input string is 27
    allocated 28 bytes
    copy OK: beta now this is a vary sally strang
    alpha is 'a vary sally strang'
    ii = 0; alpha now: 'a vary sally strang'
    n is now 1
    going to copy at most 1 characters from 'o' into 'a vary sally strang'
    beta is now 'this is o vary sally strang'
    alpha is 'ary sally strang'
    ii = 1; alpha now: 'ary sally strang'
    n is now 1
    going to copy at most 1 characters from 'e' into 'ary sally strang'
    beta is now 'this is o very sally strang'
    alpha is 'ally strang'
    ii = 2; alpha now: 'ally strang'
    n is now 1
    going to copy at most 1 characters from 'i' into 'ally strang'
    beta is now 'this is o very silly strang'
    alpha is 'ang'
    ii = 3; alpha now: 'ang'
    n is now 1
    going to copy at most 1 characters from 'u' into 'ang'
    beta is now 'this is o very silly strung'
    converted: this is o very silly strung
    

    注意 - 我添加了许多“无用”输出,包括fflush(stdout);语句。这是一种很好的方法,可以确保调试打印输出显示您到达程序的确切位置,以及崩溃前发生的事情 - 如果没有fflush,您可能会丢失多行输出(因为它们从不“进入屏幕”。

    从上面可以明显看出,如果你的替换字符串的长度与它们替换的字符串的长度不同,你会得到一些奇怪的覆盖(我留下了搜索和替换字符串长度为1,但没有理由为什么应该如此)。

    我希望这有帮助!

答案 1 :(得分:2)

    alpha=strstr(text, replace[0][4]);
    if(alpha[0])
        // looks crashy

man strstr:

  

这些函数返回指向子字符串开头的指针,   如果找不到子字符串,则返回NULL。

编辑:

很难说出你想要做什么,但下面会找到你的代码的任意改编。如果是我的程序,我会以非常不同的方式编写它。我之所以提到这一点,是因为我不希望有人读这篇文章,并认为应该这样做。

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

void newSpeak (char *text, const char *replace[4][2])
{
  int i, j;
  char *alpha;
  for (i = 0; i < 4; i++) {
    if (alpha = strstr(text, replace[i][0])) {
      for (j = 0; alpha[j] && replace[i][1][j]; j++)
        alpha[j] = replace[i][1][j];
    }
  }
}

int main ()
{
  char buf[100] = "abc";
  const char *replace[4][2] = {
    { "a", "e" },
    { "b", "f" },
    { "c", "g" },
    { "d", "h" },
  }; 
  newSpeak(buf, replace);
  puts(buf);
}