【问题标题】:How to count how many times a specific letter appears in a string? (C++)如何计算特定字母在字符串中出现的次数? (C++)
【发布时间】:2018-10-16 02:11:31
【问题描述】:

我一直在努力完成一项家庭作业,该作业计算字符串中大写字母、小写字母和数字的实例数量。出现在一个字符串中。

我使用的是一个常量大小为132的一维数组来存储输入的字符串,我需要用到两个函数。一个需要计算字符串中出现的字母数量,另一个函数将执行类似于上面的输出。我在程序本身的字母计数方面最挣扎。

目前,这就是我目前的家庭作业的大部分内容。这是一项正在进行的工作(当然),因此代码中的错误很可能发生。

void LetterCount(char c_input[], int l_count)
{
// code to count letters
}

void CountOut(//not sure what should go here yet until counting gets figured out)
{
// code that handles output
}

int main()
{
    const int SIZE = 132;
    char CharInput[SIZE];
    int LetterCount = 0;
    cout << "Enter a string of up to 132 characters in size: ";
    cin.getline(CharInput, SIZE); 
    cout << "You entered: " << CharInput << endl;

    Count(CharInput);
    CountOut(//not sure what goes here yet);
    return 0;
}

输出类似于:

  a - 2
  b - 1
  c - 1
  d - 0
  e - 1

等等……

我尝试了一些使用 for 循环来计算字母的实验,并看到了函数 gcount() 的一些示例,但我没有得到任何工作。有没有人建议我如何计算输入字符串中的字母?

【问题讨论】:

  • 发布您拥有的代码,gcount() 听起来不适用于我。您无法阅读单个字符吗?还是将它们添加到数组中会给您带来麻烦?
  • 我已经发布了我目前拥有的代码。我正在努力阅读输入字符串中每个字母的出现情况。
  • 这并没有解决问题,但是当您将输入读取到包含 132 个字符的数组中时,您不能读取超过 131 个字符。 getline 停在比 size 参数小 1 处,并在输入末尾放置一个 nul 终止符。

标签: c++ c++11


【解决方案1】:

map在这里是一个非常高效的数据结构

#include <iostream>
#include <map>
using namespace std;

int main(){
    string str = "a boy caught 2 fireflies";
    map<char, int> str_map;
    for(auto x : str) ++str_map[x];
    for(auto x : str_map) cout << x.first << ' ' << x.second << '\n';
}

【讨论】:

  • 这不会列出未出现的字符(d - 0 来自帖子)
  • @kmdreko 确实如此。解决方案并不完整。我会把它留给 OP :)
  • @kmdreko 这是一个简单的修复方法,方法是更改​​第二个循环以迭代所需的字符,使用每个字符来索引到地图中。如果一个给定的字符还没有被插入,它将读回为 0
【解决方案2】:

你想要的是构建一个简单的histogram,而且很容易做到。由于您正在查看的是 chars,并且 8 位 char 可能有 256 个可能的值(实际上您的输入字符串可能使用较少,但我们会在这里保守,因为内存很便宜),您需要从 256 个ints 的数组开始,所有这些数组都初始化为零。然后遍历 chars 您的字符串,并为您的字符串中的每个 char 使用该字符值作为数组的偏移量 (*),并简单地增加数组中的该项。

完成后,剩下的就是遍历数组中的ints 并打印出非零值,就完成了。

(*) 您可能希望在将char 用作数组的偏移量之前将其转换为unsigned char,以避免将其解释为负数组索引,这将导致未定义行为(如果您的输入字符串包含 ASCII 字符 128 或更高,这只是一个问题,因此在您的情况下可能无关紧要,但如果可以的话,让代码在所有情况下都做正确的事情总是好的形式)

【讨论】:

  • 如果您的编译器使用非 ASCII 字符编码,您也可能会得到越界值。使这段代码变得健壮是没有成本的,所以没有理由不这样做。
  • 这样的编译器存在吗?
  • @jeremy,天堂和地球上的事物比您的哲学所梦想的要多。 (向吟游诗人道歉)
  • 我会把它当作“我不知道”;)
  • 叹息。了解 EBCDIC。
【解决方案3】:

正如 Jeremy frisner 所说,您正在构建直方图,但我不同意所使用的类型。

您需要像这样声明您的直方图:

size_t histogram[sizeof(char)*CHAR_BIT] = {0};

size_t 因为没有它可能会溢出,如果它是非标准字节大小,则需要足够的空间。

至于打印出来。您应该查看 ASCII 表并检查需要打印出哪些值。

【讨论】:

  • 根据提问者的代码,输入字符串的大小似乎保证为 132 个字符或更少。鉴于此,溢出int 不是他会遇到的问题。
【解决方案4】:

您可以通过将 c-strings 与其他 c-strings 进行比较来做到这一点。但是对于字符和字符串,您可能会遇到如下错误:“const *char 不能与字符串进行比较”。因此,您必须将每个 c 字符串(数组)索引与其他 c 字符串索引进行比较。在这个程序中,我使用 if 语句来查找某些元音。它的工作方式是每个“字符串Alphabet_letter”都等于它各自的小写和大写字母(用于比较)。这是一种非常多余的方法,如果您想计算所有字母的总数,也许您应该尝试另一种方法,但是这种方法不使用需要更深入理解的非常复杂的方法。

using namespace std;

int main(){
int vowel;

string A = "aA";
string E = "eE";
string I = "iI";
string O = "oO";
string U = "uU";
string str;
string str1;

bool userLength = true; 
int restart = 0;

    do{
        cout << "Enter a string." <<endl;
            getline(cin, str);
int VowelA = 0;
int VowelE = 0;
int VowelI = 0;
int VowelO = 0;
int VowelU = 0;

    for(int x = 0; x < 100; x++){

if(restart == 1){
    restart = 0;
    x = 0;
}
if(A[0] == str[x]){
    VowelA = VowelA + 1;
}
if(E[0] == str[x]){
    VowelE = VowelE + 1;
}
if(I[0] == str[x]){
    VowelI = VowelI + 1;
}
if(O[0] == str[x]){
    VowelO = VowelO + 1;    
}
if(U[0] == str[x]){
    VowelU = VowelU + 1;    
}

if(A[1] == str[x]){
    VowelA = VowelA + 1;
}
if(E[1] == str[x]){
    VowelE = VowelE + 1;
}
if(I[1] == str[x]){
    VowelI = VowelI + 1;
}
if(O[1] == str[x]){
    VowelO = VowelO + 1;    
}
if(U[1] == str[x]){
    VowelU = VowelU + 1;    
}
int strL = str.length();
if(x == strL){
    cout << "The original string is: " << str << endl;
cout << "Vowel A: "<< VowelA << endl;
cout << "Vowel E: "<< VowelE << endl;
cout << "Vowel I: "<< VowelI << endl;
cout << "Vowel O: "<< VowelO << endl;
cout << "Vowel U: "<< VowelU << endl;
cout << " " << endl;
}
}

char choice;
cout << "Again? " << endl;

cin >> choice;

if(choice == 'n' || choice == 'N'){userLength = false;}
if(choice == 'y' || choice =='Y')
{
restart = 1;  userLength = true;
cin.clear();
cin.ignore();

}
//cout << "What string?";
//cin.get(str, sizeof(str),'\n');

}while(userLength == true);
}



/*
Sources:


printf help
http://www.cplusplus.com/reference/cstdio/printf/

This helped me with the idea of what's a vowel and whats not.
http://www.cplusplus.com/forum/general/71805/

understanding gets()
https://www.programiz.com/cpp-programming/library-function/cstdio/gets

Very important functional part of my program...Logic behind my if statements, fixed my issues with string comparison
What i needed to do was compare each part of one cstring with another c string
strstr compares two strings to see if they are alike to one another this source includes that idea-> https://www.youtube.com/watch?v=hGrKX0edRFg
so I got the idea: What is one c string was all e's, I could then compare each index for similarities with a c string whos definition was all e's.  
At this point, why not just go back to standard comparison with strings?  But you cant compare const chars to regular chars, so I needed to compare const chars to const chars
hence the idea sparked about the c strings that contained both e and E.
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string
https://stackoverflow.com/questions/18794793/c-comparing-the-index-of-a-string-to-another-string

Fixed Error with using incremented numbers outside of involved forloop.
https://stackoverflow.com/questions/24117264/error-name-lookup-of-i-changed-for-iso-for-scoping-fpermissive

understanding the use of getline(cin, str_name)
https://stackoverflow.com/questions/5882872/reading-a-full-line-of-input
http://www.cplusplus.com/reference/istream/istream/getline/
http://www.cplusplus.com/forum/beginner/45169/

cin.clear - cin.ignore --fixing issue with cin buffer not accepting new input.
https://stackoverflow.com/questions/46204672/getlinecin-string-not-giving-expected-output


*/

【讨论】:

    猜你喜欢
    • 2021-08-22
    • 1970-01-01
    • 2019-12-10
    • 2021-09-17
    • 2011-07-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多