Reputation: 31
I made the follwoing piece of code for a problem.
#include <stdio.h>
#include <stdlib.h>
int main() {
//code
int t; int k;
/*t= length of string and k=character upto which should be counted*/
int *count = (int*)malloc(26*sizeof(int));
//Dynamic Array of count.
scanf("%d %d\n",&t,&k);
char c;
for(int i =0;i<t;i++){
scanf("%c",&c);
count[c-'A']++;
}
int min = 999999;
for(int i=0;i<k;i++){
if(min>count[i]) min=count[i]; //Calculating minimum
}
if(min==0) printf("0");
else printf("%d",min*k);
return 0;
}
Though some of the compilers were giving correct output of the program. The online judge wasn't giving correct output to it. I changed the code a bit and now it works.
#include <stdio.h>
int main() {
//code
int t; int k;
scanf("%d %d\n",&t,&k);
int count[26];
char str[100020];
for(int i=0;i<t;i++)
scanf("%c",str+i);
for(int i =0;i<t;i++){
count[str[i]-'A']++;
}
//Rest from here is unchanged.
int min = 999999;
for(int i=0;i<k;i++){
if(min>count[i]) min=count[i]; //Finding the minimum of count.
}
if(min==0) printf("0");
else printf("%d",min*k);
return 0;
}
Though both of them is supposed to do the same thing why is the output different by the online judge?
INPUT : 9 3
ACAABCCAB
Correct Output : 6. Wrong output by my code was 9.
P.S Do comment if problem statement is required.
Upvotes: 1
Views: 94
Reputation: 36597
There are a few actual or potential problems, depending on what the online judge does and what compiler (or compiler settings) it uses.
Both cases have undefined behaviour, since elements of count
are not initialised. Accessing their values (e.g. which is necessary to increment them) gives undefined behaviour. Among other things, that means the behaviour can vary for creating the arrays in different ways (e.g. malloc()
versus an automatic array) in both samples.
The first sample does not check that malloc()
succeeds. If malloc()
fails (returns NULL
) subsequent code that uses count
has undefined behaviour.
scanf()
can encounter errors. This will be indicated by its return value. For example, it can return EOF
to indicate end of stream, or a value indicating the number of values it successfully read. For example, if scanf("%d %d\n",&t,&k)
return 1
, only the value of t
will be changed, and k
may not. If k
is unchanged, using it (since it is uninitialised) gives undefined behaviour.
Incidentally, scanf("%d %d\n",&t,&k)
can have some unexpected effects due to behaviour of the \n
on some input. There are plenty of questions here providing examples of problems, and explanations. In short: remove the `\n'.
The first sample has a statement count[c-'A']++
and the second replaces it with count[str[i]-'A']++
. Apart from the concern with count
being unitialised, this assumes c - 'A'
is a valid index. There are two circumstances it will not be, so the operation will increment a value outside count
.
c - 'A'
to have a value outside the range 0
to 25
.'Z' - 'A'
may be a value other than 25
.In both cases above, you need to more rigorously check the input for validity.
int min = 999999
has two potential problems. With a compiler that only supports a 16-bit int
type, the initialiser overflows, and may give a value different than you expect. If the compiler supports a large enough int
(e.g. 32 bit or better) then your program will not correctly handle input values more than 999999
. If all input values exceed that value, the calculated value of min
will be incorrect.
Upvotes: 0
Reputation: 93456
Both versions increment count
elements without count
being initialised. The fact that one works and the other does not is more by luck than judgement. It is a shame that the "judge" does not apply static analysis to the code and just reject it for poor quality rather then simply accepting anything that happens to produce an apparently correct result.
In the second:
int count[26] = {0} ;
In the first:
int* count = calloc(26, sizeof(int) ) ;
but dynamic memory allocation serves no purpose here, and failing to release it is and additional quality issue.
The use of str
in the second also serves no purpose. A better solution will be a combination of both - the initialised array, and the use of a single char to receive input.
Upvotes: 0
Reputation: 780714
Both versions are wrong, because you never initialize the values in count
to 0
.
In the first version, where you use dynamic allocation, you can use calloc()
instead of malloc()
, as it automatically zeroes the memory:
int *count = calloc(26, sizeof(*count));
In the second version, where you just declare an array, you can provide an initialization list:
int count[26] = {0};
There's no need for the str
array that you put in your second version. Since you're processing the input one character at a time, a single char
variable is fine.
There's also no need for the if
statement at the end. If min == 0
, then k * min
is also 0
, so printing min * k
will print 0
.
Upvotes: 2