-2

Here's the code to count occurencies of each character in a string:

int cnt[1000];
string s = "fooooobar";
for (char i : s) cnt[i]++;
cout << cnt['o'] << '\n';
cout << cnt['a'] << '\n';
cout << cnt['r'] << '\n';
cout << cnt['b'] << '\n';

Output 1:

5
1
33262
129355441

Output 2:

5
1
33262
328199857

Output 3:

5
1
33262
-1913409871

Output 4:

5
1
33262
-826184015

How can I access an array of int values indexing with a char values to count specific occurrences of a character?

Why is the first 2 results are valid, the third one is invalid, and the fourth one is invalid and different every time?

I use a g++ compiler as follows:

g++ -std=c++11 -Wall filename.cpp -o
πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
Ganduras
  • 19
  • 1
  • 7
    `cnt` is not initialized and using [unintialized values is undefined behavior](https://stackoverflow.com/q/23415661/1708801) – Shafik Yaghmour Oct 31 '18 at 16:57
  • 8
    You probably want a `std::map` instead of `int cnt[1000];`. This should work as intended. – πάντα ῥεῖ Oct 31 '18 at 16:58
  • 2
    Post code that compiles, runs, and shows the problem. It's likely that `cnt` hasn't been initialized, so any results are simply unpredictable. But that's not clear from this code fragment. – Pete Becker Oct 31 '18 at 16:59
  • 3
    Why do you allocate an array of 1000 integers, when your character set is probably ASCII and needs only 127? Use a `std::map`. And make sure you initialize the counters with 0 before starting. – Marius Bancila Oct 31 '18 at 17:00
  • Big thanks to everybody. This really helped me. – Ganduras Oct 31 '18 at 17:32
  • I don't think this deserves a separate answer, but to answer your first question, using a `char` to access an array (of `int` or any other type) makes sense because `char` is just an integer type. Now, it's a little tricky, in that there are only 128 values that are guaranteed not to trip you up, because a signed char can easily give you a negative array index. – Tim Randall Oct 31 '18 at 17:48
  • @Ganduras Think twice before accepting an answer that seems to solve your problem ATM, but might cause other problems coming in at wider sight. – πάντα ῥεῖ Oct 31 '18 at 18:04

2 Answers2

4

The simplest solution is to initialize all values in your array with zero:

int cnt[1000] = {0};

You have to do that explicitly, unless you're using global variables.

But as mentioned in several comments, this might cause other problems, up to calling undefined behavior regarding signed char interpretation of the compiler with character values exceeding 126 in decimal representation.

Exchanging int cnt[1000]; with std::map<char,int> your code works perfectly fine:

std::map<char,int> cnt; // <<<<<<<<
string s = "fooooobar";
for (char i : s) cnt[i]++;
cout << cnt['o'] << '\n';
cout << cnt['a'] << '\n';
cout << cnt['r'] << '\n';
cout << cnt['b'] << '\n';

See the working live demo.

With standard c++ this turns out as the natural and most convenient approach for your problem (unless you have to do micro-optimizations when running into use case specific performance problems).

πάντα ῥεῖ
  • 1
  • 13
  • 116
  • 190
2

Your problem is that you forget to set your cnt array to 0 at all indexes, because you just declared it and didn't initialize every cnt[i]=0 at every ith element, and by default, every ith element in cnt gets an unspecified (or random) value, and because of this, you are getting the wrong result. You just need to use your debugger to view of what is going on in your code, or just cout every value of i and cnt[i] before cnt[i]++ and after, so you can see what is going on.

Here is my fixed code:

int cnt[1000];

string s = "fooooobar";
for (int i = 0; i < 1000; i++){
    cnt[i] = 0;
}

for (char i : s){
    cout << "i = " << i << "cnt[" << i << "] = " << cnt[i] << endl;
    cnt[i]++;
    cout << "i = " << i << "cnt[" << i << "] = " << cnt[i] << endl;
}

cout << cnt['o'] << '\n';
cout << cnt['a'] << '\n';
cout << cnt['r'] << '\n';
cout << cnt['b'] << '\n';

when you're done debugging, just delete the cout functions because you don't need them :) Best Regards

alter_igel
  • 6,899
  • 3
  • 21
  • 40
RistoS
  • 64
  • 2