簡體   English   中英

刪除 c++ 中字符串中的所有元音

[英]Removing all the vowels in a string in c++

我編寫了一個代碼,從 c++ 中的字符串中刪除所有元音,但由於某種原因,它不會刪除一個特定輸入的元音'o' ,即: zjuotps

這是代碼:

#include<iostream>
#include<string>
using namespace std;

int main(){
    string s;
    cin >> s;

    string a = "aeiouyAEIOUY";

    for (int i = 0; i < s.length(); i++){
        for(int j = 0; j < a.length(); j++){
            if(s[i] == a[j]){
                s.erase(s.begin() + i);
            }
        }
    }
    cout << s;

    return 0;
}

當我輸入: zjuotps

我得到的 Output 是: zjotps

這是使用 C++ 標准庫的更簡潔的方法:

#include <algorithm>
#include <iostream>
#include <string>

using namespace std;

int main()
{
    std::string input = "zjuotps";
    std::string vowels = "aeiouyAEIOUY";

    auto predicate = [&vowels](char c) { return vowels.find(c) != std::string::npos; };
    auto iterator = std::remove_if(input.begin(), input.end(), predicate);
    input.erase(iterator, input.end());

    cout << input << endl;
}

您可以通過將匹配字符添加到新string object 來開發解決方案。 如果input object 中的字符與remove object 中的字符不匹配,則eliminate()方法將字符寫入result object。

#include <iostream>

/**
 * @brief This method scans the characters in the "input" object and writes
 *        the characters not in the "remove" object to the "result" object.
 * @param input This object contains the characters to be scanned.
 * @param remove This object contains characters that will not match.
 * @param result Non-match result data is writed to this object.
 */
void eliminate(std::string input, std::string remove, std::string &result);

int main()
{
    std::string input = "zjuotpsUK", remove = "aeiouyAEIOUY", result;
    eliminate(input, remove, result);
    std::cout << result << std::endl;
    return 0;
}

void eliminate(std::string input, std::string remove, std::string &result)
{
    for (size_t i = 0, j = 0; i < input.length(); i++)
    {
        for(j = 0; j < remove.length(); j++)
            if(input[i] == remove[j])
                break;

        if(j == remove.length())
            result += input[i];
    }
}

在您的代碼中,為了便於閱讀,我將s替換為input_str ,並將a替換為vowels

 for (int i = 0; i < input_str.length(); i++){ for(int j = 0; j < vowels.length(); j++){ if(input_str[i] == vowels[j]){ input_str.erase(input_str.begin() + i); } } }

上面當前代碼的問題是,每次刪除輸入字符串中的字符時,都應該跳出元音j循環並在輸入字符串中的同一i位置重新開始,檢查j循環中的所有元音再次。 這是因為擦除一個字符會左移所有位於右側的字符,這意味着相同的i位置現在將包含一個要檢查的新字符,因為它只是從一個 position 左移到該 position 到右側。 錯誤地允許i增加意味着您跳過該新字符以檢查相同的i position,例如,如果 2 個元音在一行中,則將第二個元音留在字符串中。 這是問題中對您的直接代碼的修復:

int i = 0;
while (i < s.length()){
    bool char_is_a_vowel = false;
    for(int j = 0; j < a.length(); j++){
        if(s[i] == a[j]){
            char_is_a_vowel = true;
            break; // exit j loop
        }
    }
    if (char_is_a_vowel){
        s.erase(s.begin() + i);
        continue; // Do NOT increment i below! Skip that.
    }
    i++;
}

但是,還有許多其他更好的方法可以做到這一點。 我將在下面介紹一些。 然而,我個人覺得這個最受好評的代碼難以閱讀 它需要額外的學習和查找東西來做如此簡單的事情。 所以,我將展示一些替代方法來解決這個問題。

許多方法之一:將非元音字符復制到新字符串:

因此,這是一種替代的、簡單的、更易讀的方法,您只需掃描輸入字符串中的所有字符,檢查該字符是否在元音字符串中,如果不是,則將其復制到 output 字符串因為它不是元音:

只是算法:

std::string output_str;
for (const char c : input_str) {
    if (vowels.find(c) == std::string::npos) {
        output_str.push_back(c);
    }
}

完整的、可運行的示例:

#include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.
#include <string>

int main()
{
    std::string input_str = "zjuotps";
    std::string vowels = "aeiouyAEIOUY";

    std::string output_str;
    for (const char c : input_str)
    {
        if (vowels.find(c) == std::string::npos)
        {
            // char `c` is NOT in the `vowels` string, so append it to the 
            // output string
            output_str.push_back(c);
        }
    }

    std::cout << "input_str  = " << input_str << std::endl;
    std::cout << "output_str = " << output_str << std::endl;
}

Output:

input_str  = zjuotps
output_str = zjtps

許多方法2:刪除輸入字符串中的元音字符:

或者,您可以像最初嘗試那樣刪除元音字符。 但是,如果字符被擦除,則不能增加輸入字符串的索引i ,因為擦除元音字符會左移字符串中的剩余字符,這意味着我們需要在下一次迭代中再次檢查相同的索引位置為了讀取下一個字符。 請參閱下面評論中的注釋。

只是算法:

size_t i = 0;
while (i < input_str.length()) {
    char c = input_str[i];
    if (vowels.find(c) != std::string::npos) {
        input_str.erase(input_str.begin() + i);
        continue;
    }
    i++;
}

完整的、可運行的示例:

#include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.
#include <string>

int main()
{
    std::string input_str = "zjuotps";
    std::string vowels = "aeiouyAEIOUY";

    std::cout << "BEFORE: input_str = " << input_str << std::endl;

    size_t i = 0;
    while (i < input_str.length())
    {
        char c = input_str[i];
        if (vowels.find(c) != std::string::npos)
        {
            // char `c` IS in the `vowels` string, so remove it from the
            // `input_str`
            input_str.erase(input_str.begin() + i);
            // do NOT increment `i` here since erasing the vowel char above just
            // left-shifted the remaining chars in the string, meaning that we
            // need to check the *same* index location again the next
            // iteration!
            continue;
        }
        i++;
    }

    std::cout << "AFTER:  input_str = " << input_str << std::endl;
}

Output:

BEFORE: input_str = zjuotps
AFTER:  input_str = zjtps

許多方法中的 3:高速 C 風格 arrays:就地修改輸入字符串

我從我之前回答的“方法 1”中借用了這種方法: Removing elements from array in C

如果您遇到需要高速的情況,我敢打賭這可能是最快的方法之一。 它使用 C 風格的字符串(字符數組)。 它掃描輸入字符串,檢測任何元音。 如果它看到一個不是元音的字符,它會將其復制到輸入字符串的最左側,從而就地修改字符串,過濾掉所有元音。 完成后,它會在新位置以空值終止輸入字符串。 如果您最后需要 C++ std::string類型,我會在完成后從 C 字符串創建一個。

只是算法:

size_t i_write = 0;
for (size_t i_read = 0; i_read < ARRAY_LEN(input_str); i_read++) {
    bool char_is_a_vowel = false;
    for (size_t j = 0; j < ARRAY_LEN(input_str); j++) {
        if (input_str[i_read] == vowels[j]) {
            char_is_a_vowel = true;
            break;
        }
    }
    if (!char_is_a_vowel) {
        input_str[i_write] = input_str[i_read];
        i_write++;
    }
}
input_str[i_write] = '\n';

完整的、可運行的示例:

#include <iostream>  // For `std::cin`, `std::cout`, `std::endl`, etc.
#include <string>

/// Get the number of elements in an array
#define ARRAY_LEN(array) (sizeof(array)/sizeof(array[0]))

int main()
{
    char input_str[] = "zjuotps";
    char vowels[] = "aeiouyAEIOUY";

    std::cout << "BEFORE: input_str = " << input_str << std::endl;

    // Iterate over all chars in the input string
    size_t i_write = 0;
    for (size_t i_read = 0; i_read < ARRAY_LEN(input_str); i_read++)
    {
        // Iterate over all chars in the vowels string. Only retain in the input
        // string (copying chars into the left side of the input string) all
        // chars which are NOT vowels!
        bool char_is_a_vowel = false;
        for (size_t j = 0; j < ARRAY_LEN(input_str); j++)
        {
            if (input_str[i_read] == vowels[j])
            {
                char_is_a_vowel = true;
                break;
            }
        }
        if (!char_is_a_vowel)
        {
            input_str[i_write] = input_str[i_read];
            i_write++;
        }
    }
    // null-terminate the input string at its new end location; the number of
    // chars in it (its new length) is now equal to `i_write`!
    input_str[i_write] = '\n';

    std::cout << "AFTER:  input_str = " << input_str << std::endl;
    // Just in case you need it back in this form now:
    std::string str(input_str);
    std::cout << "          C++ str = " << str << std::endl;
}

Output:

BEFORE: input_str = zjuotps
AFTER:  input_str = zjtps
          C++ str = zjtps

也可以看看:

  1. [我在 C 中的類似答案] 從 C 中的數組中刪除元素

這段代碼是錯誤的,因為當你刪除元素時,你必須為下一個元素取回索引

    #include<iostream>
#include<string>
using namespace std;

int main(){
    string s;
    cin >> s;

    string a = "aeiouyAEIOUY";
int i=0;
    while ( i < s.length()){
        for(int j = 0; j < a.length(); j++){
            if(s[i] == a[j]){
                s.erase(s.begin() + i);
                i--;
            }
        }
        i++;
    }
    cout << s;

    return 0;
}

暫無
暫無

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

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