簡體   English   中英

C中字符串中的反元音

[英]reverse vowels in string in c

我是一個初學者程序員。 我正在嘗試反轉一串元音的問題。

例如:輸入:zabedfigu,輸出:zubidfega

當我運行以下代碼時,出現運行時錯誤。 我試圖在將指針pc1遞增到僅直到中間索引等范圍內更改條件,但是這給了我運行時錯誤或沒有給我所需的輸出。 我想要一些有關如何使我的代碼正常工作以及解決問題的新方法的幫助。 TIA。

#include<stdio.h>

char* reverseVowels(char* str)
{
    char *pc1, *pc2;
    int i;
    pc1 = &str[0];
    for(i=0; str[i]!='\0';++i)
        ;
    pc2 = &str[i-1];

    while(pc1!=pc2)
    {
      if((*pc1=='a')||(*pc1=='e')||(*pc1=='i')||(*pc1=='o')||(*pc1=='u'))
      {
        while(pc2!=pc1)
        {
            if((*pc2=='a')||(*pc2=='e')||(*pc2=='i')||(*pc2=='o')||(*pc2=='u'))
            {
              char temp;
              temp = *pc1;
              *pc1 = *pc2;
              *pc2 = temp;
              ++pc2;
              break;
            }
            else
              ++pc2;
        }
        ++pc1;
      }
      else
        ++pc1;
    }
    //return str;
    return NULL;
}
int main()
{
    char string[20], *pstr;
    scanf("%s", string);
    //pstr = reverseVowels(string);
    //printf("%s", pstr);
    reverseVowels(string);
    printf("%s", string);
    return 0;
}

這里的問題是,您將兩個指針都在0位置遞增,並將一個指針在結束位置遞增。 第一個指針應該增加,第二個指針應該減少,因此不要這樣做:

++pc2;

你應該做這個

--pc2;

當您要遞增pc2的指針變量值,而不是像--pc這樣遞減指針變量pc2值時, --pc

更新

根據cleblanc評論 ,我先前的答案不適用於abade類的輸入,因此我更改了代碼以解決該問題。

#include <stdio.h>

char* reverseVowels(char* str)
{
    char *pc1, *pc2;
    int i;
    pc1 = &str[0];
    for(i=0; str[i]!='\0';++i)
        ;
    pc2 = &str[i-1];

    while(pc1<pc2)
    {
      if((*pc1=='a')||(*pc1=='e')||(*pc1=='i')||(*pc1=='o')||(*pc1=='u'))
      {
        while(pc2!=pc1)
        {
            if((*pc2=='a')||(*pc2=='e')||(*pc2=='i')||(*pc2=='o')||(*pc2=='u'))
            {
              char temp;
              temp = *pc1;
              *pc1 = *pc2;
              *pc2 = temp;
              --pc2;
              break;
            }
            else
              --pc2;
        }
        ++pc1;
      }
      else
        ++pc1;
    }
    //return str;
    return NULL;
}
int main()
{
    char string[20], *pstr;
    scanf("%s", string);
    //pstr = reverseVowels(string);
    //printf("%s", pstr);
    reverseVowels(string);
    printf("%s\n", string);
    return 0;
}

您有幾個答案和注釋,指出了代碼的基本缺陷-您要遞增pc2而不是遞減pc2 但是,我認為您的算法比需要的復雜。 你可以:

  • 始終受pc1 < pc2
    • 如果pc1沒有指向元音,則將其遞增
    • 如果pc2沒有指向元音,則將其遞減
    • 如果指針不同,請交換元音並調整指針

使用測試代碼,並添加了一個is_vowel()函數,該函數可以同時檢測大寫和小寫的元音,最后我得到了:

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

static inline int is_vowel(int c)
{
    c = tolower(c);
    return (c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u');
}

static void reverse_vowels(char *string)
{
    char *p1 = string;
    char *p2 = p1 + strlen(p1);     // '\0' is not a vowel

    while (p1 < p2)
    {
        while (p1 < p2 && !is_vowel((unsigned char)*p1))
            p1++;
        while (p1 < p2 && !is_vowel((unsigned char)*p2))
            p2--;
        if (p1 != p2)
        {
            char c = *p1;
            *p1++ = *p2;
            *p2-- = c;
        }
    }
}

int main(void)
{
#ifdef INTERACTIVE
    char line[1024];
    while (fgets(line, sizeof(line), stdin) != NULL)
    {
        line[strcspn(line, "\n")] = '\0';
        printf("Input:  [%s]\n", line);
        reverse_vowels(line);
        printf("Output: [%s]\n", line);
    }
#else
    char strings[][40] =
    {
        "",
        "a",
        "b",
        "ab",
        "abe",
        "abeci",
        "nnnnummmmmmmmmmmmippppoqq",
        "AbleWasIEreISawElba",
        "A Man, A Plan, A Canal - Panama!"
    };
    enum { NUM_STRINGS = sizeof(strings) / sizeof(strings[0]) };

    for (int i = 0; i < NUM_STRINGS; i++)
    {
        printf("Input:  [%s]\n", strings[i]);
        reverse_vowels(strings[i]);
        printf("Output: [%s]\n", strings[i]);
    }
#endif /* INTERACTIVE */
    return 0;
}

您可以使用-DINTERACTIVE進行編譯,以提供交互式測試,或者默認情況下,它提供一組固定的測試。

默認輸出:

Input:  []
Output: []
Input:  [a]
Output: [a]
Input:  [b]
Output: [b]
Input:  [ab]
Output: [ab]
Input:  [abe]
Output: [eba]
Input:  [abeci]
Output: [ibeca]
Input:  [nnnnummmmmmmmmmmmippppoqq]
Output: [nnnnommmmmmmmmmmmippppuqq]
Input:  [AbleWasIEreISawElba]
Output: [ablEWasIerEISawelbA]
Input:  [A Man, A Plan, A Canal - Panama!]
Output: [a Man, a Plan, a CAnal - PAnamA!]

樣本交互式會話(我的程序稱為rv61 ):

$ rv61

Input:  []
Output: []
a
Input:  [a]
Output: [a]
b
Input:  [b]
Output: [b]
ab
Input:  [ab]
Output: [ab]
ae
Input:  [ae]
Output: [ea]
abcde
Input:  [abcde]
Output: [ebcda]
ablewasiereisawelba
Input:  [ablewasiereisawelba]
Output: [ablewasiereisawelba]
palindromic nonsense 
Input:  [palindromic nonsense]
Output: [pelendromic nonsinsa]
vwlsmssng
Input:  [vwlsmssng]
Output: [vwlsmssng]
AManAPlanACanal-Panama!
Input:  [AManAPlanACanal-Panama!]
Output: [aManaPlanaCAnal-PAnamA!]
  a big and complex sentence with multiple words of a number of lengths and so on  
Input:  [  a big and complex sentence with multiple words of a number of lengths and so on  ]
Output: [  o bog and cemplox sentunca woth moltepli wurds if e nember ef longths and si an  ]
$

請注意,該測試會測試多種退化的情況-空字符串,不帶元音的字符串,不帶元音的字符串等。回文測試得益於支持混合大小寫的情況-很難發現如果元音已被交換,都是小寫,文字是回文。

可以應用的另一個測試是將元音反轉兩次。 輸出應與輸入相同。 保存測試可能很重要。 (如果您的排序沒有保留數組中的所有元素,而是添加了隨機的新元素和/或刪除了初始元素,那么您將不會感到高興。但這是另一天的主題。)

沿所示方向使用簡單的測試工具有助於庫功能。 我的許多庫函數的末尾都有一個#ifdef TEST#endif ,以便對其進行完整性測試。 最好的測試可以驗證結果是否符合預期。 這些都是懶惰的,將其留給目視檢查以驗證輸出。 如果它是一個庫函數,那么將有一個標頭聲明該函數,該標頭在源代碼中將是#include d,而該函數將不是static (我的默認編譯選項或者需要一個功能的聲明中定義之前,或函數必須是static 。我做的功能static樣品中像這樣的代碼,因為沒有其他文件中引用的功能,所以沒有必要為一個頭聲明該函數,並且只有標頭應該聲明外部可見的函數。)

還要注意, is_vowel名稱是精心選擇的,以避免在C標准中保留名稱:

isto開頭的函數名稱以及小寫字母可以添加到<ctype.h>標頭中的聲明中。

使用isVowel()也可以。 使用isvowel()將使用保留名稱。


Bill Woodger 評論

為什么有關“ \\ 0”不是元音的評論? ...

使用所示的代碼,在p2初始化之后,確實*p2 == '\\0' 如果字符串非空,則觀察到'\\0'不是元音很重要,因為如果字符串與is_vowel()謂詞匹配,則可以將空字節移至字符串中的較早位置,從而將其截斷。

假設函數是reverse_controls()而不是reverse_vowels() ,並且測試使用了iscntrl()而不是is_vowel() 然后,對於非零長度的字符串,代碼將不得不以不同的方式處理它,因為空字節將被報告為控制字符,並且會發送錯誤消息-將與第一個其他控制字符(如果有另一個)交換在字符串中,截斷字符串。 那不是故意的。

暫無
暫無

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

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