genannt wird Ihre Idee ist nicht schlecht, ist ein Problem hier
for(j=i; i<(len-removed);j++)
str[j]=str[j+1];
halten Sie j
erhöht wird, aber die Bedingung i<(len-removed)
wird wahr für immer halten. An einem bestimmten Punkt versuchen Sie zu lesen und in den Speicher schreiben weit über Grenzen Ihres Gedächtnisses und Sie werden am Ende mit einem segfault
(wie Peter sagte). Ihr Problem ist, dass Sie nicht korrekt berechnen, wie viele Zeichen es gibt.
Angenommen, Sie tun, dass
str[j]=str[j+1];
auch nicht sehr effizient ist. Ich bekomme den Punkt, Sie versuchen, in das nächste Zeichen zu kopieren, bis Sie \0
finden. Lassen Sie uns sagen, Ihre Eingabe ist abccccddddeee
, das ist eine schrecklich lange Anzahl von einzelnen Kopien, die Sie tun werden.
Es wäre am besten, die Anzahl der doppelten Kopien zu berechnen und dann memmove
zu verwenden, um den gesamten Speicherblock auf einmal zu verschieben, was effizienter ist.
Ich änderte Sie Code mit memmove
anstelle Ihrer Ansatz. Ich ließ auch Kommentare erklären, wie man die Länge der Duplikate und die Parameter von memmove
berechnet, die manchmal hart sein können. Normalerweise nehme ich ein Stück Papier und mache es zuerst von Hand, dann bekommst du viel schneller die Idee.
#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;
}
Beachten Sie auch, dass diese Methode funktioniert nur, wenn Sie Schreibzugriff auf den Puffer haben. Wenn Sie ein Zeichenfolgenliteral übergeben (const char *text = "abcdddd";
), , erhalten Sie eine segfault
, da Zeichenfolgenliterale im schreibgeschützten Speicher sind.
Beachten Sie auch, dass die Zeile mit den while
endet mit ;
while(condition);
// is equivalent to
while(condition)
{
}
'for (j = i; i <(LEN-entfernt); j ++)': Da 'i <(LEN-entfernt)' ändert sich nicht, es kann eine Endlosschleife verursachen. – BLUEPIXY
@BLUEPIXY 'else {i ++; } ' – Barmar
Wie rufen Sie Ihre Funktion? – AnT