繁体   English   中英

计算字符串中所有字符的函数-C ++

[英]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 >> inputgetline(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不是longint

您也可以这样做:

 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM