簡體   English   中英

使用C中的指針從字符串中刪除元音

[英]Remove Vowels from string using pointers in C

我正在嘗試使用指針從2D數組字符串中刪除元音。 我能夠通過其ASCII值檢測到元音,但是字符串沒有得到更新。

代碼的這一部分不能更改。

void remove_vowel(char strings[NUM_STRINGS][STRING_LENGTH])

我的代碼哪里出問題了?

更新的代碼:

void remove_vowel(char strings[NUM_STRINGS][STRING_LENGTH])
    {
        // loop through each row, starting intitally points to last element
        for (char(*p)[STRING_LENGTH] = strings; p != strings + NUM_STRINGS; ++p) {
            // variable q points to the first element       
            for (char *q = *p; q != *p + STRING_LENGTH; ++q) {

                if (*q != 'a' && *q != 'e' && *q != 'i' && *q != 'o' && *q != 'u') {
                    //printf("%c",*q);          
                    *q = *q;
                }
            }       
        }
    }

我能夠使用下面列出的解決方案重新編寫代碼。 感謝大家的幫助!

void remove_vowel(char strings[NUM_STRINGS][STRING_LENGTH])
    {
        // store the array in a pointer
        char(*wordHolder)[STRING_LENGTH] = strings; 

        // loop through each row
        for (int i = 0; i < NUM_STRINGS; i++)
        {
            // assign worl
            char *letter = *wordHolder;
            char *dest = *wordHolder;

            // check if null character
            while (*letter != '\0') {
                // check for vowels
                if (*letter != 'a' && *letter != 'e' && *letter != 'i' && *letter != 'o' && *letter != 'u') {
                    // assign non-vowel letter to destination
                    *dest++ = *letter;
                } 
                // move to next letter
                letter++;

            }
            // add null pointer to end of destination
            *dest = '\0';

            // increment pointer position to next word
            wordHolder++;
        }
    }

這個問題已經隨着時間而改變,最初是針對 我在這里留下它的歷史的目的,但它並不適用於新的目標


remove_if應該可以解決您的問題,其中:

刪除是通過移動(通過移動分配)范圍中的元素來完成的,要刪除的元素出現在范圍的開頭。 保留了剩余元素的相對順序,並且容器的物理大小未更改。

您可以像這樣利用remove_if

void removeVowel(char strings[][STRING_LENGTH]) {
    for (auto p = strings; p != next(strings, NUM_STRINGS); ++p) {
        remove_if(begin(*p), end(*p), [vowels = "aeiouAEIOU"s](const auto& i){return vowels.find(i) != string::npos;});
    }
}

現場例子

這個非常簡單的解決方案要求char[]元素以'\\0'結尾。 remove_if只是將所有元音字符移到忽略它們的'\\0'字符之后。 在以下情況下,這可能不是可行的解決方案:

  1. 您正在使用一個不以'\\0'結尾的char[] ,這是一個非常糟糕的設計決定,但是如果您在那兒,讓我們在評論中討論解決方法
  2. STRING_LENGTH非常大; remove_if每次都搜索STRING_LENGTH元素,因此,如果字符串比包含的數組短得多,請考慮使用next(*p, strlen(*p) + 1)代替end(*p)

注釋strings參數,用於C ++函數參數:

如果類型是“的陣列T ”或“結合的未知的陣列T ”,它是由型“指針替換T[ ]

因此,數組主要維度中的任何值都將被丟棄並視為參數被轉換為指針。 因此,您將在我的代碼中看到另一個代碼,其中未填充數組函數參數的主要維度,因為當對具有不同主要維度的數組進行排序時,它對傳遞的數組的實際大小沒有任何要求,並因此可能造成混亂未經警告即接受。

雄辯地說,您會注意到我的代碼和其他代碼中的所有非主要尺寸都將被填充。 這是由於以下事實:

多維數組與常規數組非常相似。 就像數組一樣,多維數組存儲為相同類型的對象的連續序列。 需要注意的重要事項是定義每個尺寸的尺寸的數字。 因此,在不提供多維數組長度的情況下也無法傳遞多維數組[ source ]

因此,您會注意到我們可以調用begin(*p)end(*p)但不能調用 begin(strings) end(strings)

對於初學者,您應該將現有的remove_vowel()例程分為(至少) 三個獨立的函數:

void remove_vowel(std::string& s)
{
...
}

void remove_vowel(std::vector<std::string>& strings)
{
    for(auto&& s : strings)
       remove_vowel(s);
}
void remove_vowel(char strings[NUM_STRINGS][STRING_LENGTH]) // can't change this signature
{
    ...
}

現在,您的問題減少到兩個(或三個)幾乎完全不相關的部分:

  • 從單個std::string刪除元音
  • 從C樣式的數組轉換為C ++
  • (也許:從C ++轉換回C樣式數組)

我建議您編寫更多的“類似於C ++”的代碼。

#include <string>  // needed for string container
#include <vector>  // needed for vector container

// This function removes all vowels from a std::string
std::string removeVowels(std::string input) {
    std::vector<std::string> vowels = {"a", "e", "i", "o", "u", "A", "E", "I", "O", "U"}; // create and initilise a dynamic array with all vowels, that should be filtered
    // Iterate over all vowels
    for(const std::string vowel : vowels) {
        // Get first position of the appearance of the vowel,
        // exit if none are found
        while(auto pos = input.find(vowel) != std::string::npos) {
            // replace vowel with empty string
            input.erase(pos, vowel.size());
        }
    }
    // return our result
    return input;
};

我編譯並測試了此示例。

我讓您編寫函數,該函數需要2D字符串數組並使用此函數。 考慮在c樣式數組上使用std :: vector。

讓我們考慮一下C語言的等效項。

在C語言中,您需要將文本視為數組。 對於陣列, 擦除插槽時,需要移動其余項目以覆蓋擦除的插槽。

讓我們從那里開始。

void dont_copy_vowels(char text_array[STRING_LENGTH])
{
   char * p_source = &text_array[0];
    char * p_destination = &text_array[0];
    const unsigned int length = strlen(text_array);
    while (*p_source != '\0')
    {
      static const char vowels[] = "aeiou";
      if (strchr(vowels, *p_source) != NULL)
      {
        ++p_source;
        continue; // don't copy vowels.
      }
      // Copy the letter or symbol.
      *p_destination++ = *p_source++;
    }
    *p_destination = '\0';
}

由於您使用的是C樣式字符串數組,因此需要將以上代碼放入循環中:

for (unsigned int string_index = 0;
     string_index < NUMBER_OF_STRINGS;
     ++string_index)
{
  dont_copy_vowels(strings[string_index]);
}

暫無
暫無

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

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