带有字符数组的分段故障&指针

时间:2017-06-30 23:53:33

标签: c

我试图对此进行调试并找出可能导致分段错误的原因。我很新。这是一个小方法,可以删除数组中连续的重复项。

 void removeddup(char *str){
  int i;
  int j;
  int len= str_len(str)-1;
  int removed = 0;
  for(i=0; i < (len-removed);)
    {
      if(str[i]==str[i+1])
        {
          for(j=i; i<(len-removed);j++)
            str[j]=str[j+1];
          removed++;
        }else{
        i++;
      }
    }
}

它被称为

char str1[100]
case '6':
      removeddup(str1);
      break;

1 个答案:

答案 0 :(得分:0)

你的想法不错,这里有一个问题

for(j=i; i<(len-removed);j++)
    str[j]=str[j+1];

您继续递增j,但条件i<(len-removed)将成立 永远。在某些时候,你会尝试远远地读取和写入内存 记忆的边界,你最终会得到segfault(就像彼得一样) 说过)。你的问题是没有正确计算多少重复 有角色。

让我们说你这样做

str[j]=str[j+1];

效率也不高。我明白了,你试着复制str[j] 下一个字符,直到找到\0。假设您的输入为abccccddddeee, 这是你要做的很多单拷贝。

最好计算重复副本的数量然后再使用 memmove一次移动整个内存块,效率更高。

我使用memmove代替您的方法修改了代码。我也离开了 解释如何计算重复的长度和 memmove的参数,有时可能很难。我经常拿一块 纸张先用手工做,然后你就能更快地得到它。

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

void removeddup(char *str){
    int i;
    int j;
    int len= strlen(str)-1;
    int removed = 0;

    for(i=0; i < (len-removed);)
    {
        if(str[i]==str[i+1])
        {
            // we calculate the length of the duplicates
            j = 0;
            while(str[i] == str[i + ++j]);

            // we have j duplicates of str[i] (counting str[i])
            // we copy the rest of the string after the j-1 duplicates
            // the destination is the next character after str[i] (str + i +1)
            // the source is str[i+j]
            //
            // now we have to determine how many chars to copy. In general
            // you do string_length - index_of_source + 1, which also copies
            // the \0 string-terminating character.
            //
            // In your case
            //   string_length: len - removed + 1 (the +1 because you 
            //                  defined len := strlen(str)-1;
            //   index_of_source: i + j 
            // ==> len - removed + 1 - (i + j) + 1
            // so

            memmove(str + i + 1, str + i + j, len - removed + 1 - (i+j) + 1);

            // now we set how many characters we've removed
            removed += j - 1;

            // we go the next character
            i++;

        }else{
            i++;
        }
    }
}


int main(void)
{

    char text[] = "abccccccdeeefffffffffffff";

    printf("Original: %s\n", text);
    removeddup(text);
    printf("removed:  %s\n", text);

    return 0;
}

另请注意,此方法仅在您具有写入权限时才有效 缓冲。如果你传递一个字符串文字(const char *text = "abcdddd";), 你会得到segfault因为字符串文字在只读内存中。

另请注意,while的行以;

结尾
while(condition);

// is equivalent to

while(condition)
{
}