这种输出差异的原因可能是什么?

时间:2018-09-20 21:37:00

标签: c arrays

我编写了下面的代码来解决问题。

#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;
}

尽管某些编译器给出了正确的程序输出。在线法官没有给出正确的输出。我稍微修改了代码,现在可以了。

#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;
}

尽管他们俩都应该做同样的事情,但在线法官的输出为何有所不同?

输入: 9 3

ACAABCCAB

正确的输出:6.我的代码输出的错误是9。

P.S如果需要问题陈述,请发表评论。

3 个答案:

答案 0 :(得分:2)

这两个版本都是错误的,因为您从未将count的值初始化为0

在使用动态分配的第一个版本中,可以使用calloc()代替malloc(),因为它会自动将内存清零:

int *count = calloc(26, sizeof(*count));

在第二个版本中,您只需要声明一个数组,就可以提供一个初始化列表:

int count[26] = {0};

您不需要在第二个版本中放入str数组。由于您一次要处理一个字符,因此单个char变量就可以了。

最后也不需要if语句。如果为min == 0,则k * min也是0,因此打印min * k将打印0

答案 1 :(得分:0)

两个版本都递增count元素而未初始化count。一个运而另一个运的事实并非靠运气胜于判断。可耻的是,“法官”没有对代码进行静态分析,只是拒绝接受质量差的代码,而是仅仅接受任何可能产生明显正确结果的东西。

第二个:

int count[26] = {0} ;

在第一个:

int* count = calloc(26, sizeof(int) ) ;

但是动态内存分配在这里没有用,并且无法释放它和其他质量问题。

第二步使用str也没有任何意义。更好的解决方案是将两者结合在一起-初始化数组,以及使用单个char接收输入。

答案 2 :(得分:0)

有一些实际或潜在的问题,具体取决于在线法官的工作以及所使用的编译器(或编译器设置)。

这两种情况都具有不确定的行为,因为count的元素未初始化。访问它们的值(例如,增加它们的值是必需的)会产生不确定的行为。除其他外,这意味着在两个示例中以不同方式(例如malloc()与自动数组)创建数组的行为可能会有所不同。

第一个示例不检查malloc()是否成功。如果malloc()失败(返回NULL),则使用count的后续代码将具有不确定的行为。

scanf()可能会遇到错误。这将由其返回值指示。例如,它可以返回EOF来指示流的结束,或者返回一个值来指示它成功读取的值的数量。例如,如果scanf("%d %d\n",&t,&k)返回1,则仅t的值将被更改,而k可能不会更改。如果k不变,则使用它(因为它未初始化)会产生不确定的行为。

偶然地,由于scanf("%d %d\n",&t,&k)在某些输入上的行为,\n可能会产生某些意外的影响。这里有很多问题,提供问题示例和说明。简而言之:删除“ \ n”。

第一个示例具有语句count[c-'A']++,第二个示例将其替换为count[str[i]-'A']++。除了担心count被统一化之外,这还假设c - 'A'是有效的索引。在两种情况下可能会不存在,因此该操作将在count之外增加一个值。

  • 除大写字母之外的其他输入都会导致c - 'A'的值在025范围之外。
  • [晦涩难懂,但在标准允许的范围内,并且具有此特征的字符集]。大写字母集不能保证是连续的,因此'Z' - 'A'可以是25以外的其他值。

在上述两种情况下,您都需要更严格地检查输入的有效性。

int min = 999999有两个潜在问题。对于仅支持16位int类型的编译器,初始化程序将溢出,并可能提供与您期望的值不同的值。如果编译器支持足够大的int(例如32位或更高),则您的程序将无法正确处理大于999999的输入值。如果所有输入值都超过该值,则min的计算值将不正确。