c

时间:2017-03-30 18:08:06

标签: c string

我是初学程序员。我正在尝试在字符串中反转元音的问题。

Ex:输入: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;
}

3 个答案:

答案 0 :(得分:1)

这里的问题是你将两个指针递增到0位置的一个指针,将指针放在结束位置。第一个指针应该递增,第二个指针应该递减,因此不是这样做:

++pc2;

你应该这样做

--pc2;

答案 1 :(得分:1)

当您要增加pc2的指针变量值时,问题就出现了,而不是像pc2那样递减指针变量--pc的值。

<强>更新

根据cleblanc comment,我之前的回答不适用于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;
}

答案 2 :(得分:1)

您有几个答案和评论指出代码中的根本缺陷 - 您正在递增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 commented

  

为何评论&#39; \ 0&#39;不是元音? ...

使用如图所示的代码,在p2初始化之后,*p2 == '\0'确实如此。如果字符串非空,则'\0'不是元音的观察值很重要,因为如果它与is_vowel()谓词匹配,则空字节可以移动到字符串中较早的某个点,截断它。 / p>

假设该函数为reverse_controls()而不是reverse_vowels(),并且测试使用iscntrl()而不是is_vowel()。然后代码必须以不同的长度字符串处理它,因为空字节将被报告为控制字符并且会发送错误 - 它将与第一个其他控制字符交换(如果有另一个)在字符串中,截断字符串。这不是他们想要的。