我是初学程序员。我正在尝试在字符串中反转元音的问题。
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;
}
答案 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标准中的保留名称:
以
is
或to
开头的函数名称和小写字母可以添加到<ctype.h>
标题中的声明中。
使用isVowel()
也可以;使用isvowel()
将使用保留名称。
为何评论&#39; \ 0&#39;不是元音? ...
使用如图所示的代码,在p2
初始化之后,*p2 == '\0'
确实如此。如果字符串非空,则'\0'
不是元音的观察值很重要,因为如果它与is_vowel()
谓词匹配,则空字节可以移动到字符串中较早的某个点,截断它。 / p>
假设该函数为reverse_controls()
而不是reverse_vowels()
,并且测试使用iscntrl()
而不是is_vowel()
。然后代码必须以不同的长度字符串处理它,因为空字节将被报告为控制字符并且会发送错误 - 它将与第一个其他控制字符交换(如果有另一个)在字符串中,截断字符串。这不是他们想要的。