编写一个 C++ 程序,找出字符串中使用的元音个数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21627999/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Write a c++ program that finds the number of vowels used in an string
提问by Singh
Write a c++ program that finds the number of vowels used in an string.
编写一个 C++ 程序,找出字符串中使用的元音数。
For the above problem I written a program as follows:
针对上面的问题我写了一个程序如下:
int main()
{
char x[10];
int n,i,s=0;
cout<<"Enter any string\n";
cin>>x;
n=strlen(x);
for(i=0;i<n;++i)
{
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
{
s=s+1;
}
}
cout<<s;
return 0;
}
Output of the program is as:
程序的输出如下:
Enter any string
elephant
3
输入任意字符串
大象
3
Here in 'elephant' at three places vowels are used but the total number of vowels used is 2(e and a) not 3
在'elephant'中的三个地方使用了元音,但使用的元音总数是2(e和a)而不是3
I am asking to improve the program so that it counts the total number of vowels and print the total number.(e.g. in case of elephant it must give 2)
我要求改进程序,以便它计算元音的总数并打印总数。(例如,在大象的情况下,它必须给出 2)
回答by Michael
Make another array(), with 5 index, like
制作另一个数组(),具有 5 个索引,例如
vowels[5] = array(0,0,0,0,0);
Then make if else if, with eache vowel, and add
然后用每个元音制作 if else if,并添加
if(x[i] == 'a') vowels[0] =1;
elseIf(x[i] == 'e') vowels[1] =1;
etc, and then check if vowels array is set to 1 or 0, and count only, these which are 5.
等等,然后检查元音数组是否设置为 1 或 0,并且只计数,这些是 5。
int count=0;
foreach vowels as item {
if(item == 1) count++
}
return count;
回答by James Kanze
The easiest solution would be to just insert each vowel you see
into an std::set
, and use its size
function when you're
done.
最简单的解决方案是将您看到的每个元音插入std::set
,并size
在完成后使用其功能。
And for heaven's sake, use a table lookup to determine whether something is a vowel (and put the logic in a separate function, so you can correct it when you need to handle the "sometimes y" part).
看在上帝的份上,使用查表来确定某个东西是否是元音(并将逻辑放在单独的函数中,以便在需要处理“有时是 y”部分时可以更正它)。
Alternatively, without using the standard algorithms:
或者,不使用标准算法:
int charCount[UCHAR_MAX + 1];
// and for each character:
++ charCount[static_cast<unsigned char>( ch )];
(Of course, if you're using C++, you'll read the characters
into an std::string
, and iterate over that, rather than having
an almost guaranteed buffer overflow.)
(当然,如果您使用 C++,您会将字符读入一个std::string
,并对其进行迭代,而不是几乎保证缓冲区溢出。)
Then, just look at each of the vowels in the table, and count those which have non-zero counts:
然后,只需查看表中的每个元音,并计算那些具有非零计数的元音:
int results = 0;
std::string vowels( "aeiou" ); // Handling the sometimes "y" is left as an exercise for the reader.
for ( auto current = vowels.begin(); current != vowels.end(); ++ current ) {
if ( charCount[static_cast<unsigned char>( *current )] != 0 ) {
++ results;
}
}
Of course, neither of these, implemented na?vely, will handle
upper and lower case correctly (where 'E' and 'e' are the same
vowel); using tolower( static_cast<unsigned char>( ch ) )
will
solve that.
当然,这两个,天真地实现,都不能正确处理大写和小写(其中“E”和“e”是相同的元音);使用tolower( static_cast<unsigned char>( ch ) )
将解决这个问题。
EDIT:
编辑:
Since others are proposing solutions (which are only partially correct):
由于其他人提出了解决方案(仅部分正确):
bool
isVowel( unsigned char ch )
{
static std::set<int> const vowels{ 'a', 'e', 'i', 'o', 'u' };
return vowels.find( tolower( ch ) ) != vowels.end();
}
int
main()
{
std::string text;
std::cout << "Enter any word:";
std::cin >> text;
std::set<unsigned char> vowelsPresent;
for ( unsigned char ch: text ) {
if ( isVowel( ch ) ) {
vowelsPresent.insert( tolower( ch ) );
}
}
std::cout << vowelsPresent.size() << std::endl;
}
Separating the definition of a vowel into a separate function is
practically essential in well written code, and at the very
least, you need to mask differences in case. (This code also
punts on the question of "y", which would make isVowel
several
orders of magnitude more difficult. It also ignores characters
outside of the basic character set, so "na?ve"
will report two
different vowels.)
在编写良好的代码中,将元音的定义分离成一个单独的函数实际上是必不可少的,至少,您需要屏蔽差异以防万一。(这段代码还针对“y”的问题,这会增加isVowel
几个数量级的难度。它还忽略了基本字符集之外的字符,因此"na?ve"
会报告两个不同的元音。)
回答by Lightness Races in Orbit
Sets already eliminate duplicates, so instead of counting vowels as you encounter them, add them into a set. Then, at the end, count the number of [non-duplicate] vowels by querying the set for its size.
集合已经消除了重复项,因此不要在遇到元音时计算它们,而是将它们添加到集合中。然后,最后,通过查询集合的大小来计算 [非重复] 元音的数量。
#include <set>
#include <string>
#include <iostream>
int main()
{
std::string x;
int n = 0;
std::set<char> vowels;
std::cout << "Enter any string\n";
std::cin >> x;
n = x.size();
for (int i = 0; i < n; ++i)
if (x[i] == 'a' || x[i] == 'e' || x[i] == 'i' || x[i] == 'o' || x[i] == 'u')
vowels.insert(x[i]);
std::cout << vowels.size() <<'\n';
}
Live demo
现场演示
g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && echo "elephant" | ./a.out
Enter any string
2
g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && echo "elephant" | ./a.out
输入任意字符串
2
Note that I also exchanged your use of fixed-sized arrays with an std::string
, so that you're not at risk of dangerous circumstances when someone happens to input more than 9 characters.
请注意,我还将您对固定大小数组的使用换成了std::string
,这样当有人碰巧输入超过 9 个字符时,您就不会面临危险情况。
回答by zzz2991
I find a really easy way to solve this problem is by using map <char, int>
. This will allow you to make pairs, indexed by a char
, ie. the vowels, and connect an integer counter to them.
我发现解决这个问题的一个非常简单的方法是使用map <char, int>
. 这将允许您配对,由 a 索引char
,即。元音,并将一个整数计数器连接到它们。
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main()
{
map <char, int> vowels;
int n,i,s=0;
string x;
cout<<"Enter any string\n";
cin>>x;
for(i=0;i< x.length();++i)
{
if(x[i]=='a'||x[i]=='e'||x[i]=='i'||x[i]=='o'||x[i]=='u')
{
vowels[x[i]]++;
}
}
for (map<char,int>::const_iterator print = vowels.begin(); print != vowels.end(); ++print){
cout << print -> first << " " << print -> second << endl;
}
return 0;
}
For the string elephant
we would get the following output:
对于字符串,elephant
我们将得到以下输出:
a 1
e 2
By saying vowels[x[i]]++;
we are adding the found vowel into our map, if it already has not been added, and incrementing its paired int
by one. So when we find the first e
it will add e
to our map and increment its counter by one. Then it will continue until it finds the next e
and will see that it already has that indexed, so it will simply increment the counter to 2. This way we will avoid the problem with duplicates. Of course, if you wanted to get a single digit we could just print out the size of our map:
通过说vowels[x[i]]++;
我们将找到的元音添加到我们的映射中,如果它还没有被添加,并且将它的配对int
增加一。因此,当我们找到第一个时e
,它将添加e
到我们的地图中并将其计数器加一。然后它将继续,直到它找到下一个,e
并会看到它已经索引了,所以它只会将计数器增加到 2。这样我们将避免重复的问题。当然,如果你想得到一个数字,我们可以打印出我们地图的大小:
cout << vowels.size() << endl;
回答by graham.reeds
Okay. My turn. To handle both upper and lower cases we convert to just lower:
好的。轮到我了。为了处理大写和小写,我们转换为小写:
std::string x("Elephant");
std::transform(x.begin(), x.end(), x.begin(), std::function<int(char)>(std::tolower));
Now remove duplicates:
现在删除重复项:
std::sort(x.begin(), x.end());
std::unique(x.begin(), x.end());
Now to count the vowels. I was hoping for something specific in locale but alas... Never mind we can create our own. Bit more complex, but not overly:
现在来计算元音。我希望在语言环境中有一些特定的东西,但是唉......没关系我们可以创建自己的。有点复杂,但不过分:
struct vowel : public std::ctype<char>
{
static const mask* make_table()
{
static std::vector<mask> v(classic_table(), classic_table() + table_size);
v['a'] |= upper;
v['e'] |= upper;
// etc.
return &v[0];
}
vowel(std::size_t refs = 0) : ctype(make_table(), false, refs){}
};
While I am sure you can create your own but can't quite figure out how going by the documentation on cppreference so I say lower case vowels are uppercase. With the earlier call to std::tolower this should be safe.
虽然我确信您可以创建自己的,但不能完全弄清楚 cppreference 上的文档是如何进行的,所以我说小写元音是大写的。使用较早调用 std::tolower 这应该是安全的。
With this we can use it easily like:
有了这个,我们可以轻松地使用它,例如:
int i = std::count_if(x.begin(), x.end(), [](const char c)
{
return std::isupper(c, std::locale(std::locale(""), new vowel));
});
std::cout << "Number of vowels:" << i << std::endl;
However I am not particularly happy with the two std::locale
next each other.
然而,我对std::locale
彼此相邻的两个并不特别满意。
回答by rashedcs
C++ Code Snippet :
C++ 代码片段:
#include <bits/stdc++.h>
using namespace std;
int main()
{
char s[100];
int cnt;
cnt=0;
cin>>s;
for(int i=0;s[i];i++)
{
char c =s[i];
if(s[i]=='A' || s[i] =='E' || s[i]=='I' ||s[i]=='O'|| s[i]=='U') cnt++;
else if(s[i]=='a' || s[i] =='e' || s[i]=='i'||s[i]=='o' || s[i]=='u') cnt++;
}
cout<<cnt<<endl;
return 0;
}
回答by Petr Javorik
Version utilizing std::find()
and std::transform()
:
使用std::find()
和的版本std::transform()
:
#include <string>
#include <iostream>
#include <algorithm>
using std::string;
using std::cout;
using std::cin;
using std::getline;
using std::transform;
int main()
{
cout << " Type sentence: ";
string sentence;
getline(cin, sentence);
transform(sentence.begin(), sentence.end(), sentence.begin(), toupper);
string vowels = "AEIOU";
size_t vowCount = 0;
for (int i = 0; i < vowels.length(); ++i)
{
if (sentence.find(vowels[i], 0) != string::npos)
{
++vowCount;
}
}
cout << "There is " << vowCount << " vowels in the sentence.\n";
return 0;
}
PROS
优点
std::find()
searches just for firstoccurrence of given vowel so there is no iteration over rest of the given string- using optimized algorithms from
std
std::find()
仅搜索给定元音的第一次出现,因此不会对给定字符串的其余部分进行迭代- 使用优化的算法来自
std
CONS
缺点
std::transform()
transforms eachlower-case letter regardless of its "vowelness"
std::transform()
转换每个小写字母,而不管其“元音”
回答by kenhero
#include<iostream> //std::cout
#include<string> //std::string
#include<cctype> //tolower()
#include<algorithm> //std::for_each
using namespace std;
int main()
{
string s;
getline(cin, s);
int count = 0;
for_each(s.begin(), s.end(), [&count](char & c) //use of lambda func
{
c = tolower(c); //you can count upper and lower vowels
switch (c)
{
case 'a':
case 'e':
case 'i':
case 'o':
case 'u':
count++;
break;
}
});
cout << count << endl;
return 0;
}
回答by cpp-progger
try this
尝试这个
for( string text; getline( cin, text ) && text != "q"; )
{
set< char > vowels;
copy_if( begin(text), end(text), inserter( vowels, begin(vowels) ),
[]( char c ) { return std::char_traits< char >::find( "aeiou", 5, c ) != nullptr; } );
cout << "the string [" << text << "] contains " << vowels.size() << " vowels" << endl;
}
You need the includes string, iostream, set, algorithm and iterator. What do You want to do with the upper ones "AEIOU" ?
您需要包含字符串、iostream、集合、算法和迭代器。你想对上面的“AEIOU”做什么?
回答by nhgrif
Easiest solution I can think of would be an array of bools representing each vowel and whether or not they've been counted.
我能想到的最简单的解决方案是代表每个元音的布尔数组,以及它们是否被计算在内。
bool vowelCounted[5] = { false };
Now, as you count the vowels:
现在,当您计算元音时:
if (x[i]=='a' && !vowelCounted[0]) {
vowelCounted[0] = true;
s += 1;
} else if (x[i]=='e' && !vowelCounted[1]) {
vowelCounted[1] = true;
s += 1;
}
And just repeat this structure for all 5 vowels.
只需对所有 5 个元音重复此结构即可。
The readability can be improved by using an enum
rather than 0
, 1
, 2
, 3
, 4
for your indices... but you're using variables named x[]
and s
, so it's probably fine...
可以通过对索引使用enum
而不是0
, 1
, 2
, 3
,来提高可读性4
……但是您使用的是名为x[]
and 的变量s
,所以可能没问题……