My code counts how many occurrences of a char appears in a string, it works but it doesnt display it how I want it probably because of the ASCII table ordering.
My Desired Output:
enter string value: Prog
P - 1
r - 1
o - 1
g - 1
But instead I get it alphabetically:
enter string value: Prog
g - 1
o - 1
P - 1
r - 1
Here is my code:
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: I do need it to count the lowercase and uppercase letters seperately.
CodePudding user response:
First you can make your program a lot smaller(in size) and better(general) using std::map
Version 1: Does not display the output in insertion order
#include <iostream>
#include <map>
int main() {
std::string inputString;
std::cout<<"Enter a string: ";
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;
}
The output of the above Version 1 is as follows:
Enter a string: Prog
P-1
g-1
o-1
r-1
Note in the above order the order of the characters is alphabetical. If you want the output in order then do this:
Version 2: Displays the output in insertion order as you want
#include <iostream>
#include <map>
int main() {
std::string inputString;
std::cout<<"Enter a string: ";
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;
}
The output of this 2nd version is as follows:
Enter a string: Prog
P-1
r-1
o-1
g-1
Also the output of the above version 2 when the input has re-occuring characters like "AnoopRana" will be repeated as shown below:
Enter a string: AnoopRana
A-1
n-2
o-2
o-2
p-1
R-1
a-2
n-2
a-2
To display each character only once you can see this program which is as follows:
Version 3: For displaying each character exactly once and in insertion order
#include <iostream>
#include <map>
int main() {
std::string inputString;
std::cout<<"Enter a string: ";
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;
}
Note
Both of these version count small and capital letters separately which is what you want.CodePudding user response:
I like the std::map
approach, but if the intent is to preserve the input order while providing a count of characters, you must have some way to check for characters that have already been seen. std::map
does that for you, but does not preserve the input order. If you iterate over the original string to provide in-order output, you still need a way to avoid outputting multiple counts for the same character if it occurs more than once in the input string.
In the case where you iterate over the input string, you can keep track of the position and use std::basic_string::find to check the remainder of the string before outputting the next character.
Another way is to use a std::vector<std::pair<char, int>>
. However, this does not have the convenience of std::map
in that you will need to write the comparison to check whether a pair containing the character already exists or a pair needs to be added to track occurrences of that character. So you end up with an additional 10 or so lines of code.
For example, you could do:
#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';
}
}
Example Use/Output
Providing an input string with multiple occurrences of the same character, you could do:
$ ./bin/vector_pair_char-int
enter letters: abcd-dbbccc-*-
a - 1
b - 3
c - 4
d - 2
- - 3
* - 1
Look things over and let me know if this is what you were attempting to accomplish. There are several ways you can do this. The std::map
approach is also good, probably even preferred, but @AnooopRana already has a good example to work from there.
CodePudding user response:
#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;
}