String.at() - 'a'

Seeking help to see if I'm deducing correctly.

for the code example below,
s[i] - 'a'
means to subtract 97 so that the char 'a' starts at s[0] and 'b' is at 1, am i right?


I googled, but couldn't find any answers directly, but found this related topic
http://cplusplus.com/forum/beginner/166060/
which uses the example String.at() - '0'

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Solution {
public:
    int firstUniqChar(string s) {
        // first is count, second is index
        pair<int, int> arr[26] = {{0, 0}};
        int n = s.size();
        for(int i=0; i<n; ++i) {
            int idx = s[i] - 'a';
            ++arr[idx].first;
            arr[idx].second = i;
        }
        int ans = INT_MAX;
        for(int i=0; i<26; ++i) {
            if(arr[i].first == 1)
                ans = min(ans, arr[i].second);
        }
        return ans == INT_MAX ? -1 : ans;
    }
};
> s[i] - 'a'
> means to subtract 97 so that the char 'a' starts at s[0] and 'b' is at 1, am i right?

Subtract the integer value of 'a' (which may be, quite often is 97), from the integer value of character at s[i].

For many characters, s[i] - 'a' would yield a negative result.

For instance:
1
2
3
4
5
6
7
8
9
#include <iostream>

int main()
{
    const char x = '$' ; // char(36) in US-ASCII
    const char a = 'a' ; // char(97)  in US-ASCII
    const int diff = x - a ;
    std::cout << "diff == " << diff << '\n' ;
}

http://coliru.stacked-crooked.com/a/3d79ecdfb8a52101

Something like this, perhaps:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
#include <iostream>
#include <string>
#include <limits>
#include <iomanip>

std::size_t firstUniqChar( const std::string& str )
{
    if( str.empty() ) return std::string::npos ;
    if( str.size() == 1 ) return 0 ;

    const std::size_t NCHARS = std::numeric_limits<unsigned char>::max() + 1 ; // number of distinct characters
    int counts[NCHARS] {} ; // initialised to all zeroes

    for( unsigned char c : str ) ++counts[c] ; // set the counts

    // try to locate the first unique character and if found, return its position
    for( std::size_t pos = 0 ; pos < str.size() ; ++pos ) if( counts[ unsigned(str[pos]) ] == 1 ) return pos ;

    return std::string::npos ; // no unique characters in this string
}

int main()
{
    for( const std::string str : { "abcd!abcd", "", "abcde!abc!ab!ax", "abcd(bcd)!", "abcd(bcd)!abcd(bcd)!" } )
    {
        std::cout << std::quoted(str) << "  " ;
        const auto pos_unique = firstUniqChar(str) ;
        if( pos_unique == std::string::npos ) std::cout << "there are no unique characters\n" ;
        else std::cout << "first unique character is at " << pos_unique << '\n' ;

        std::cout << ' ' ;
        for( std::size_t i = 0 ; i < str.size() ; ++i ) std::cout << i%10 ;
        std::cout << "\n\n" ;
    }
}

http://coliru.stacked-crooked.com/a/d5d54d99e5b5bed0
thanks JLBorges,

enlightening as always.

this stack-crooked.com online editor and compiler is useful! thanks for showing it to me too
Topic archived. No new replies allowed.