簡體   English   中英

C 從字符串中刪除連續重復字符的程序

[英]C program to remove consecutive repeated characters from string

代碼: https://pastebin.com/nW6A49ck

/* C program to remove consecutive repeated characters from string. */
 
#include <stdio.h>
 
int main() {
    char str[100];
    int i, j, len, len1;

    /* read string */
    printf("Enter any string: ");
    gets(str);
 
    /* calculating length */
    for (len = 0; str[len] != '\0'; len++);
 
    /* assign 0 to len1 - length of removed characters */
    len1 = 0;
 
    /* Removing consecutive repeated characters from string */
    for (i = 0; i < (len - len1);) {
        if (str[i] == str[i + 1]) {
            /* shift all characters */
            for (j = i; j < (len - len1); j++)
                str[j] = str[j + 1];
            len1++;
        } else {
            i++;
        }
    }
 
    printf("String after removing characters: %s\n", str);
    return 0;
}

問題:假設我有字符串 'Hello' 作為輸入..我希望兩個l s 都被刪除(不僅僅是 1)...'Hello' 相同(我希望刪除 3 l s而不僅僅是 2 l s)...我該怎么做?

if (str[i] == str[i + 1]) {
    /* shift all characters */
    for (j = i; j < (len - len1); j++)
        str[j] = str[j + 1];
    len1++;
}

也許我可以計算每個字符重復的次數,然后在第 28 行中將 1 替換為字符重復的次數? 但是我怎樣才能將它實現到代碼中呢?

您可以制作一個 function 來刪除具有相同字符的范圍,方法是將一個字符一個字符地復制到字符串中的一個單獨的指針,如果發現重復字符,您不會向前移動:

void foo(char *str) {
    for(char *wr = str; (*wr = *str) != '\0';) {  // copy until `\0` is copied
        ++str;                 // step to the next character
        if(*wr != *str) {      // if the next char is not equal to `*wr`
            ++wr;              // step `wr` forward to save the copied character
        } else do { 
            ++str;             // `*wr == *str`, so step `str` forward...
        } while(*wr == *str);  // ...until a different character is found
    }
}
  • *wr = *strstr指向的當前字符復制到wr當前指向的位置。 \0 (null 終止符)被復制時, != '\0'檢查使循環結束。
  • 之后str增加以指向下一個字符。
  • 如果下一個字符不等於剛剛復制的字符,則增加wr以保存復制的字符。
  • 如果下一個字符確實等於被復制的字符,則不要增加wr以讓它被下一個被復制的字符覆蓋並向前移動str直到找到不同的字符。

演示

密集版本做完全相同的事情:

void foo(char *str) {
    for(char *wr = str; (*wr = *str) != '\0';) {
        if(*wr != *++str) ++wr;
        else while(*wr == *++str);
    }
}

此代碼片段應從字符串中刪除所有連續字符(請注意,某些 C 編譯器不允許您在內部塊中聲明變量):

for (int i=0; i<len; i++) {
    int j = i, repeats = 1;
    while (j < len-1 && str[j] == str[++j])
    {
        repeats++;
    }
    if (repeats > 1) {
        for (j = i; j < len - repeats; j++)
        {
            str[j] = str[j + repeats];
        }
        len -= repeats;
        i--;
        str[len] = '\0';
    }
}

不鼓勵鏈接,相反,您應該發布鏈接的內容。 另外,對於這類問題,我會建議先想出一個合適的算法,然后再實現它。 有時,您會發現這比獲取別人的代碼並對其進行更改以使其按您的需要工作要容易得多。

算法:

第 I 步:記錄要在字符串中寫入的字母 position(調用此 position - P)。 最初,它將是字符串的開頭。

第二步:如果當前處理字符與下一個字符相同,則

  • 不要對 P 做任何改變。
  • 設置一個標志以跳過下一個字符(調用此標志 - F)。

第三步:如果當前處理的字符和下一個字符不同,則

  • 如果標志 F 被設置,跳過這個字符,重置標志 F 並且不改變 P。
  • 如果未設置標志 F,則將此字符寫入字符串中的 position P,並將 P 設置為下一個 position。

第四步:移至字符串中的下一個字符,go 移至第二步。

執行:

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

void remove_all_consecutive_dup_chars (char * pstr) {
    if (pstr == NULL) {
        printf ("Invalid input..\n");
        return;
    }

    /* Pointer to keep track of position where next 
     * character to be write.
     */
    char * p = pstr;
    int skip_letter = 0;

    for (unsigned int i = 0; pstr[i] ; ++i) {
        /* Using tolower() to identify the consecutive characters 
         * which are same and only differ in case (upper/lower).
         */
        if ((tolower (pstr[i]) == tolower (pstr[i + 1]))) {
            skip_letter = 1;
            continue;
        }

        if (skip_letter) {
            skip_letter = 0;
        } else {
            *p++ = pstr[i];
        }
    }

    /* Add the null terminating character. 
     */
    *p = '\0';
}

int main (void) {
    char buf[256] = {'\0'};

    strcpy (buf, "WELL, well, welLlLl....");
    printf ("%s ----> ", buf);
    remove_all_consecutive_dup_chars (buf);
    printf ("%s\n", buf);

    strcpy (buf, "Hello");
    printf ("%s ----> ", buf);
    remove_all_consecutive_dup_chars (buf);
    printf ("%s\n", buf);

    strcpy (buf, "Helllo");
    printf ("%s ----> ", buf);
    remove_all_consecutive_dup_chars (buf);
    printf ("%s\n", buf);

    strcpy (buf, "aAaaaA    ZZz");
    printf ("%s ----> ", buf);
    remove_all_consecutive_dup_chars (buf);
    printf ("%s\n", buf);
    
    return 0;
}

Output:

# ./a.out
WELL, well, welLlLl.... ----> WE, we, we
Hello ----> Heo
Helllo ----> Heo
aAaaaA    ZZz ----> 

編輯:

在上面的程序中,我使用tolower()並假設作為參數傳遞給remove_all_consecutive_dup_chars()的字符串將僅包含字母 - [A - Z] / [a - z]和空格字符。
請注意,如果pstr[i] < 0tolower()可能導致 UB。 如果您使用tolower() ,只需確保您傳遞給tolower()的參數可以表示為unsigned char

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM