繁体   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