[英]Function to count all characters in a string - C++
我想用C ++写一个functioin,它计算字符串中的所有字符。#我有一个称为input的字符串,程序的用户可以在其中输入一个句子,这些重要的字母我像这样存储在字符串字母表中:
string alphabet {"ABCDEFGHIJKLMNOPQRSTUVWXYZ"};
一个用于存储字母出现频率的向量,例如A位于位置0,B位于位置0,依此类推。
vector<long> letterCount (26);
我已经写出了我认为应该可以使用的功能,并且似乎可以找出字符的出现,但是之后将这个数字乘以字母在字母表中的位置。 这是函数:
long countLetters(int& p) {
for(int i = 0; i < alphabet.size(); ++i) {
for(long j = 0; j < count(input.begin(), input.end(), alphabet.at(i)) {
countLetters.at(i)++;
}
}
return letterCount.at(p);
}
例如,如果输入为“ HELLO”,则程序将输出:
E : 5
H : 8
L : 24
O : 15
因此,您看到例如字符串中的字母“ L”包含两次,但“ L”的结果为24,因为“ L”在字母表中的第12位。
如果您意识到我的问题所在,请提供帮助。
编辑:我已经找到一种有效的方法,至少部分地:
long countLetters(int& p) {
for(size_t i = 0; i < input.length(); ++i) {
for(size_t j = 0; j < alphabet.length(); ++j) {
letterCount.at(j) = count(input.begin(), input.end(), alphabet.at(j));
}
}
return letterCount.at(p);
}
但是,当输入两个或多个单词时,该功能只会计算出第一个单词中的字母出现率。 如何分析更多单词?
编辑:在我有cin >> input
但getline(cin, input);
是对的。
您正在执行某种奇怪的双循环。 取而代之的是,在一个循环中遍历字符串,并在正确的组中对其进行计数:
for (int i = 0; i < input.length(); i++) {
char c = input[i];
if (c < 'A' || c > 'Z') continue;
countLetters[c-'A'] += 1;
}
我将分两个步骤执行此操作:
#include <unordered_map>
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
std::string input = "hello world";
std::unordered_map<char, unsigned int> counts;
std::unordered_map<char, unsigned int> counts2;
std::for_each(std::begin(input), std::end(input), [&counts](char c) {
counts[c]++;
});
std::for_each(std::begin(alphabet), std::end(alphabet), [&counts, &counts2] (char c) {
const auto& it = counts.find(c);
if( it != counts.end()) counts2.insert(*it);
});
for(auto& kv: counts2)
{
std::cout << kv.first << ": " << kv.second << "\n";
}
return 0;
}
由于访问无序映射的顺序应为O(1)
这将导致O(N+M)
的复杂性,其中N
为输入字符串的长度, M
为输出字符串的长度。 您也许可以改善counts和counts2之间的复制,或者完全消除多余的地图,我在撰写本文时有点着急;)。 您还可以返回将输出放入向量中,但我将其作为练习。
另一个变体是将您的字母存储在一个集合中,并在第一个循环中执行if(alphabetset.count(c))
,而不执行第二个循环。 这将具有复杂度O(N*log(M))
,这也可能足够好,并且代码也更简单:
#include <unordered_map>
#include <algorithm>
#include <string>
#include <iostream>
#include <set>
int main()
{
std::string alphabet = "abcdefghijklmnopqrstuvwxyz";
std::set<char> alphabetset{std::begin(alphabet), std::end(alphabet)};
std::string input = "hello world";
std::unordered_map<char, unsigned int> counts;
std::for_each(std::begin(input), std::end(input), [&counts, &alphabetset](char c) {
if(alphabetset.count(c)) counts[c]++;
});
for(auto& kv: counts)
{
std::cout << kv.first << ": " << kv.second << "\n";
}
return 0;
}
当然,如果您的输入集具有某些数学属性(例如精确的范围),则可以使用Tom van der Woerdt的解决方案,因为这将是O(N)
而且您将无法获得更快的速度。
这是我的版本,用于解决问题并按降序打印结果。
void printNumofLetterinString(std::string sentence){
int frequencyArray[26]; //FrequencyArray is used to store the frequency
for(int i=0;i<26;i++){ //of the letters and Initialize
frequencyArray[i] = 0; //frequencyArray to all zero.
}
int ascii;
for(int i=0;i<sentence.length();i++){
if(!isalpha(sentence[i])){
continue;
}
ascii = tolower(sentence[i]) - 'a'; //Convert A-Za-z to number between 0-25.
frequencyArray[ascii]++;
}
for(int i=0;i<26;i++){ //Find the biggest number in frequencyArray
int max = frequencyArray[0]; //print it, then set it to zero
int index = 0; //and find the next biggest number.
for(int j=0;j<26;j++){
if(frequencyArray[j] > max){
max = frequencyArray[j];
index = j;
}
}
if(max == 0){
break;
}
char c = index + 'a';
std::cout<<c<<" "<<max<<std::endl;
frequencyArray[index] = 0;
}
}
结果如下
input caaabb
output a 3
b 2
c 1
char arr[] = {"aaabbaccdaadac"};
map<char,int> mymap;
for(int i= 0 ;i<strlen(arr);i++)
{
mymap.insert(pair<char,int>(arr[i],0));
auto it = mymap.find(arr[i]);
++it->second;
mymap.insert(pair<char,int>(arr[i],it->second));
}
map<char, int> ::iterator mapit;
for(mapit = mymap.begin(); mapit != mymap.end() ; mapit++)
{
cout<<mapit->first<< " occurence == " <<mapit->second<<endl;
}
该字符串可以作为用户的参数。
cin >> inputString;
unordered_map<char, int> characterMap;
for (char c : inputString){
characterMap[c]++;
}
for (std::pair<char, int> characterCount : characterMap) { // Alternatively use 'auto' as type
cout << characterCount.first << " count: " << characterCount.second << endl;
}
正如@KillianDS在评论中所提到的,如果您想要一个通用的解决方案(即可以变化的“字母”),最简单的方法可能是计算每个可能字符的出现次数,然后根据您的实际字母进行过滤:
// count every possible character
std::array<size_t, (1 << (8 * sizeof(char)))> countChars;
countChars.fill(0);
for (auto i = input.begin(); i != input.end(); ++i)
countChars[*i]++;
// extract only the ones you're interested in
std::vector<size_t> countLetters;
for (auto i = alphabet.begin(); i != alphabet.end(); ++i)
countLetters.push_back(countChars[*i]);
注意:计算项目时,最好使用size_t
不是long
或int
。
您也可以这样做:
char *x = "cmnasdkASFSAFASDisdajkhasdfjqwedz" ; // work UPPER , lower
static int c[26] ;
int main ( void ) {
while ( *x ) {
int ndx= *x - (islower(*x) ? 'a' : 'A') ;
c[ ndx] += isalpha(*x++) ? 1 : 0 ;
}
for ( int i =0;i<26;i++) printf ( "\n%d", c[i] );
}
您可以执行以下操作:
std::string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
std::string input = "MISSISSIPPI yukon.";
// First insert the characters that we want to count.
std::unordered_map<char, size_t> map;
for (auto ch : alphabet)
map[ch] = 0;
// Then count ONLY the inserted characters.
for (auto ch : input) {
auto it = map.find(ch);
if (it != map.end())
++it->second;
}
for (auto pair : map)
if (pair.second > 0)
std::cout << '\'' << pair.first << "\'\t" << pair.second << std::endl;
打印...
'I' 4
'M' 1
'P' 2
'S' 4
...因为我们只计算alphabet
的字符。
如果您想保证有序的结果,请用std::map
替换std::unordered_map
(在上面的示例中,它们是无意中排序的)。
测试这个宏
#define FOR_ALL(cont , block)\
for (const auto &itr : cont)\
block;
而这部分代码
map<char, int> countLetters;
FOR_ALL(str, countLetters[itr]++);
并打印结果
for (const auto &element : m)
cout << element.first << ' ' << element.second<<endl;
#include<iostream>
#include <conio.h>
using namespace std;
int main (){
char str[50];
cin.getline(str,50);
int arr[1234]={0};
///extraction of every character
int i=0;
while(str[i]!='\0'){
arr[str[i]-' ']++; /* converting characters into integer type implicitly
and storing freq of the ASCII characters at that
position of the array.' ' space char is just a
reference point... */
i++;
}
///show character freq
for (i=0;i<256;i++) {
if (arr[i]!=0)
cout <<"letter "<<char(i+' ')<<" is present "<<arr[i]<<" times "<<endl;
}
return 0;
}
/* the arr array contains freq of all the characters and symbols occuring in
a string after ' '(space) character ..so beware of entering the characters
that are before ' ' on the standard ASCII table and your program should run
fine..if you want to do so just replace the ' ' everywhere with the first
character of the ASCII table.....*/
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.