使用C中的指针从字符串中删除元音

时间:2017-02-13 14:49:41

标签: c pointers

我试图使用指针从一串二维数组中删除元音。我能够通过ASCII值检测元音,但字符串没有得到更新。

代码的此部分无法更改。

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++;
        }
    }

我能够使用下面列出的解决方案重新编写代码。感谢大家的帮助!

解决方案

=filter(DEC_JAN!F5:F82,(DEC_JAN!F5:F82<65))

4 个答案:

答案 0 :(得分:3)

这个问题随着时间的推移而发生了变化,最初是针对提出的。我是出于历史目的将其留在此处,但它不适用于新定位的

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;});
    }
}

Live Example

这个非常简单的解决方案要求您char[]元素'\0'被终止。 remove_if只是将所有元音字符移动到忽略它们的'\0'字符之后。如果出现以下情况,这可能不是可行的解决方案:

  1. 您使用的char[]未被'\0'终止,这是一个非常糟糕的设计决定,但如果您在那里让我们在评论中讨论解决方法< / LI>
  2. STRING_LENGTH非常大; remove_if每次都会搜索STRING_LENGTH个元素,因此,如果您的字符串比包含的数组短得多,请考虑使用next(*p, strlen(*p) + 1)代替end(*p)
  3. 评论strings参数,对于C ++函数参数:

      

    如果类型是&#34;数组T&#34;或者&#34; T&#34;的未知范围的数组,它被类型&#34;指向T&#34; [source]

    因此,当转换参数作为指针时,将丢弃并处理数组主要维度中的任何值。因此,您将在我的代码中看到另一个代码,即数组函数参数的主要维度未填充,因为它不需要传递的数组的实际大小,因此当具有不同主要数组的数组时可能会产生混淆尺寸在没有警告的情况下被接受。

    在此基础上滔滔不绝,您会注意到我的代码和其他代码中的所有非主要维度都将被填充。这是因为:

      

    多维数组与传统数组非常相似。多维数组存储为相同类型的连续对象序列,就像数组一样。需要注意的重要事项是定义每个维度的大小的数字。因此,如果不提供其尺寸的长度 [source]

    ,则无法传递多维数组。

    因此,您会注意到我们可以致电begin(*p)end(*p),但绝不会 begin(strings) end(strings)

答案 1 :(得分:2)

对于初学者,您应该将现有的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风格的数组)

答案 2 :(得分:2)

我建议你写更多&#34; C ++ - 喜欢&#34;代码。

#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。

答案 3 :(得分:2)

让我们考虑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-Style字符串数组,因此需要将上述代码放在循环中:

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