Как мне упорядочить символы в выводе массива в этом вложенном цикле for?

Мой код подсчитывает, сколько вхождений символа появляется в строке, он работает, но не отображает его так, как я хочу, вероятно, из-за упорядочения таблицы ASCII.

Мой желаемый результат:

      enter string value: Prog
P - 1
r - 1
o - 1
g - 1

Но вместо этого я получил его по алфавиту:

      enter string value: Prog
g - 1  
o - 1      
P - 1
r - 1

Вот мой код:

          char str[100] = "";
    int sum = 0;
    
    cout<<"Enter String Value: ";
    gets(str);
    
    //char counter uppercase
    for (int i = 65; i<=90; i++)
    {
      sum = 0;
      for (int j=0; j<sizeof(str); j++)
      {
        if((int)str[j] == i)
        {
          sum = sum + 1;    
        }
      }
      if (sum > 0)
      {
        cout<<(char)i<<" - "<<sum<<endl;;
      }
    }
    
    //char counter lowercase
    for (int i = 97; i<=122; i++)
    {
      sum = 0;
      for (int j=0; j<sizeof(str); j++)
      {
        if((int)str[j] == i)
        {
          sum = sum + 1;    
        }
      }
      if (sum > 0)
      {
        cout<<(char)i<<" - "<<sum<<endl;;
      }
    }

PS: Мне это нужно, чтобы отдельно подсчитывать строчные и прописные буквы.

3 ответа

Решение

Сначала вы можете сделать свою программу намного меньше (по размеру) и лучше (в целом), используя std::map

Версия 1 : вывод не отображается в порядке вставки

      #include <iostream>
#include <map>

int main() {
    std::string inputString;
    std::cout<<"Enter a string: ";
    std::getline(std::cin,inputString);
    //this map maps the char to their respective count
    std::map<char, int> charCount;
    
    for(char &c: inputString)
    {
        charCount[c]++;
        
    }
    
    for(std::pair<char, int> pairElement: charCount)
    {
        std::cout << pairElement.first <<"-" << pairElement.second<<std::endl;
    }
    return 0;
}

Результат вышеупомянутой версии 1 выглядит следующим образом:

      Enter a string: Prog
P-1
g-1
o-1
r-1

Обратите внимание, что в указанном выше порядке символы расположены в алфавитном порядке. Если вы хотите, чтобы вывод был в порядке, сделайте следующее:

Версия 2 : отображает вывод в нужном вам порядке вставки.

      #include <iostream>
#include <map>
int main() {
    std::string inputString;
    std::cout<<"Enter a string: ";
    std::getline(std::cin,inputString);
    //this map maps the char to their respective count
    std::map<char, int> charCount;
    
    for(char &c: inputString)
    {
        charCount[c]++;
    }
    
    //just go through the inputString instead of map
    for(char &c: inputString)
    {
        std::cout << c <<"-" << charCount.at(c)<<std::endl;
    }
    return 0;
}

Результат этой второй версии выглядит следующим образом:

      Enter a string: Prog
P-1
r-1
o-1
g-1

Также вывод вышеупомянутой версии 2, когда на входе есть повторяющиеся символы, такие как "AnoopRana", будет повторяться, как показано ниже:

      Enter a string: AnoopRana
A-1
n-2
o-2
o-2
p-1
R-1
a-2
n-2
a-2

Чтобы отобразить каждый символ только один раз, вы можете увидеть эту программу, которая выглядит следующим образом:

Версия 3: для отображения каждого символа ровно один раз и в порядке вставки

      #include <iostream>
#include <map>
int main() {
    std::string inputString;
    std::cout<<"Enter a string: ";
    std::getline(std::cin,inputString);
    //this map maps the char to their respective count
    std::map<char, int> charCount;
    
    for(char &c: inputString)
    {
        charCount[c]++;
    }
    
    std::size_t i = 0;
    //just go through the inputString instead of map
    for(char &c: inputString)
    {
        std::size_t index = inputString.find(c);
        if(index != inputString.npos && (index == i)){
         std::cout << c <<"-" << charCount.at(c)<<std::endl;
         
        }
        ++i;
    }
    return 0;
}

Примечание

Обе версии считают строчные и заглавные буквы отдельно, что вам и нужно.
      #include <filesystem>
#include <iostream>
#include <fstream>
#include <map>
#include <cmath>
#include <chrono>
#include <algorithm>
#include <vector>
#include <execution>
#include <thread>
#include <condition_variable>
#include <mutex>
#include <string>
#include <atomic>

std::vector<std::pair<char,int>> tfinal;

int main(int argc, char *argv[])
{

    std::string c = "rgjukuilo";
    std::for_each(std::execution::par, c.begin(), c.end(), [&](auto a){ int wr = std::count(c.begin(), c.end(), a);
        tfinal.insert(tfinal.end(), { a , wr } ); });

    for (auto c : tfinal)
        std::cout << c.first << " " << c.second << std::endl;

}

Мне нравится этот подход, но если цель состоит в том, чтобы сохранить порядок ввода при указании количества символов, у вас должен быть какой-то способ проверить символы, которые уже были замечены. делает это за вас, но не сохраняет порядок ввода. Если вы перебираете исходную строку, чтобы обеспечить вывод по порядку, вам все равно нужен способ избежать вывода нескольких счетчиков для одного и того же символа, если он встречается более одного раза во входной строке.

В случае, когда вы перебираете входную строку, вы можете отслеживать позицию и использовать std::basic_string::find для проверки оставшейся части строки перед выводом следующего символа.

Другой способ - использовать . Однако в этом нет того удобства, что вам нужно будет написать сравнение, чтобы проверить, существует ли уже пара, содержащая символ, или пару необходимо добавить для отслеживания вхождений этого символа. Таким образом, вы получаете дополнительные 10 или около того строк кода.

Например, вы могли бы сделать:

      #include <iostream>
#include <string>
#include <vector>

/* returns index if c is contained in vector, vector.size() if not */
size_t vpairContains (const std::vector<std::pair<char,int>>& vp, char c)
{
    size_t ndx = 0;                 /* zero index */
    
    for (const auto& p : vp) {      /* loop over pairs */
        if (p.first == c) {         /* compare char */
            break;
        }
        ndx++;                      /* increment index */
    }
    
    return ndx;
}

int main (void) {
    
    std::string input {};
    std::vector<std::pair<char,int>> vp {};     /* vector pairs */
    
    std::cout << "enter letters: ";             /* get/validate string */
    if (!getline (std::cin, input)) {
        return 1;
    }
    
    for (const auto& c : input) {               /* loop over chars */
        size_t ndx = vpairContains (vp, c);     /* get index in vector */
        if (ndx < vp.size()) {                  /* check if found */
            vp[ndx].second++;                   /* increment count */
        }
        else {
            vp.push_back({c, 1});               /* add new element */
        }
    }
    
    for (const auto& p : vp) {      /* output results */
        std::cout << p.first << " - " << p.second << '\n';
    }
}

Пример использования / вывода

Предоставляя входную строку с несколькими вхождениями одного и того же символа, вы можете:

      $  ./bin/vector_pair_char-int
enter letters: abcd-dbbccc-*-
a - 1
b - 3
c - 4
d - 2
- - 3
* - 1

Посмотрите на вещи и дайте мне знать, если это то, чего вы пытались достичь. Есть несколько способов сделать это. В подход тоже хорош, возможно, даже предпочтителен, но у @AnooopRana уже есть хороший пример для работы оттуда.

Другие вопросы по тегам