I see some things that may help you improve your code.
Use more whitespace
Lines like this one:
for(i=0;str[i];i=i++)
are harder to read than they should be. Use whitespace to make the code easier to read and understand:
for(i = 0; str[i]; i = i++)
Use C idioms
The for
loop above isn't technically incorect, but it's odd-looking for those who are fluent in C. The issue is that this i = i++
should just be written as i++
.
Eliminate unused variables
This code declares a variable c
but then does nothing with it. Your compiler is smart enough to help you find this kind of problem if you know how to ask it to do so.
Eliminate "magic numbers"
This code has a number of "magic numbers," that is, unnamed constants such as 26, 48, 10000, etc. Generally it's better to avoid that and give such constants meaningful names. That way, if anything ever needs to be changed, you won't have to go hunting through the code for all instances of "3" and then trying to determine if this particular 3 is relevant to the desired change or if it is some other constant that happens to have the same value.
Since you're using 10000 as both the size of the buffer and as part of the format string for scanf
, it's a little bit tricky, but there's a nice way to do it in C:
#define BUFFLEN 10000
#define XSTR(x) STR(x)
#define STR(x) #x
Now when you want to use BUFFLEN
as a number, it can be done like this:
char str[BUFFLEN];
Using it in the format string is a little different:
scanf("%" XSTR(BUFFLEN) "[^\n]", str);
See the gcc
explanation of stringification for details on how and why this works.
Use constants consistently
In one case the code has str[i] >= 'a'
and in another it uses m = str[i] - 97
. It's much more clear if the latter were written instead as m = str[i] - 'a'
.
Use better variable names
The variable name str
is OK, but the names n
, Q
and chint
are not. The first name explains something about what the variable means within the context of the code, but the others provide no hint as to what the variable is storing or why it might be useful.
Consider using a tree structure
Ultimately, what your program needs to do is to take an input number and produce the corresponding number. The current code has the right idea in that it uses a data structure rather than an explicitly uncompressed string, but there are potentially better ways to store the data. Consider using a tree structure instead (or in addition to) the existing structure. Each node could store the cumulative count and the associated letter, so finding the answer would simply be a matter of searching the tree.
For example, the given example string translates to aaaabbbbhhhhh
. That could be represented by the following binary search tree:

If the query is "what character is at position \$n\$`, we simply search the tree. For example, if \$n=9\$, we start at the root node and look for a node with the smallest number \$\ge n\$. In the case that \$n=9\$, we see that \$9 > 8\$, so move the right child node. There we see that \$9 <= 13\$, so the correct answer is the letter stored at that node = 'h'.
Only two comparisons are required instead of 10 that would be required for a linear search of the existing structure.
Check return values for errors
The calls scanf
can fail. You must check the return values to make sure they haven't or your program may crash (or worse) when given malformed input or due to low system resources. Rigorous error handling is the difference between mostly working versus bug-free software. You should strive for the latter.
Eliminate return 0
at the end of main
Since C99, the compiler automatically generates the code corresponding to return 0
at the end of main
so there is no need to explicitly write it.