【问题标题】:How to properly make a counting algorithm to count from file?如何正确地使计数算法从文件中计数?
【发布时间】:2018-12-24 19:41:17
【问题描述】:

这是一个从输入文件中找出最大偶数及其出现次数并将其输出到输出文件的程序。我的输出有问题,似乎有一个额外的迭代把事情搞砸了。

int main(int argc, char const *argv[])
{
    int n, num, i, even, count;

    FILE * fptr;
    FILE * fptro;

    fptr =fopen("maximpar.in", "r");
    fptro=fopen("maximpar.out", "w");

   /*scanning the first line from the file to get n for for()*/

    fscanf(fptr, "%d", &n); 

    count = 0;
    even = INT_MIN;
    for(i = 0; i < n; i++)
{
    fscanf(fptr, "%d", &num);

    if( (num % 2 == 0 && num > even) || (even == num) ) 

    /*checking  for largest even number, 
    not sure about the ..||(even == num) part of the condition*/

    {
        even = num;
        count++;
    }

}

    fprintf(fptro, "%d %d", even, count);


    fclose(fptr);
    fclose(fptro);

    return 0;
}

输入文件

 6
 9 6 9 8 9 8

输出文件

8 3 

为什么输出文件不是这样?我不明白

8 2

【问题讨论】:

    标签: c file count


    【解决方案1】:

    每当您获得一个更大的新数字时,您都需要重置您的计数。

    我没有对此进行测试,但它应该可以工作:

    cate = 0;
    par = INT_MIN;
    
    for (i = 0; i < n; i++) {
        fscanf(fptr, "%d", &b);
    
        // skip odd numbers
        if ((b % 2) != 0)
            continue;
    
        // get new larger number
        if (b > par) {
            par = b;
            cate = 1;
            continue;
        }
    
        // increment count on existing largest number
        if (b == par)
            ++cate;
    }
    

    更新:

    我不明白为什么要明确跳过迭代而不是只挑选重要的迭代?有什么优势吗?

    是的,这是更好的风格。它允许简单的单级缩进 if 语句,这些语句可以有自己的 cmets。

    它避免了混乱的复合if 或三层级if/else 阶梯。

    IMO,一个常见的误解 [特别是在 C 初学者中] 认为一个复杂的 if 会比几个简单的执行得更快[或者在某种程度上“更好”]。

    第一个if 可以被认为是“跳过此迭代”测试。在这里,只有一个。但是,对于更复杂的代码,可能有几个。

    多个条件转义可以在单个ifif (c1 || c2 || c2 || ... || c10) continue; 中处理,但这很快就会变得混乱。

    在这里,对于正确缩进的if/else 梯形逻辑,我们需要:

    if (cond1)
        do_stuff1;
    else
        if (cond2)
            do_stuff2;
        else
            if (cond3)
                do_stuff3;
    

    如果我们不在循环中,这里有一个“技巧”来避免if/else 梯形逻辑,使用do { ... } while (0);

    do {
        if (cond1) {
            do_stuff1;
            break;
        }
    
        if (cond2) {
            do_stuff2;
            break;
        }
    
        if (cond3) {
            do_stuff3;
            break;
        }
    } while (0);
    

    【讨论】:

    • 我不明白为什么要明确跳过迭代而不是只挑选重要的迭代?有什么优势吗?
    • 我明白了,我们的教授在作业中确实坚持“编码风格”。这很有帮助。但为什么我的输出显示为 3?哪个迭代有一个额外的计数++;?
    • 我可以再问一次为什么跳过赔率而不是直接获得赔率?
    【解决方案2】:

    附上条件

       if(  ( ...&&...) ||(....) )
    

    【讨论】:

    • 虽然它可能看起来更整洁,或者在某些情况下可能很重要,但这对我的问题没有任何帮助
    • 直接从 6 (6%2==0 && 6>-1) p=6,cnt=1 next 8 (8%2==0 && 8>6) p= 开始8,cnt=2 next 8 again ..||(8==8) cnt=3 不像你的情况 6%2 && 6>-1 || 6==-1 cnt1,p=6 , 8%2 && 8>6 || 8==6 cnt=2,p=8 最后, 8%2 && 8>8 || 8==8 cnt 将保持 2
    【解决方案3】:

    答案是因为当 b = 6 时 count 从 0 增加到 1。2 次迭代之后,b = 8 现在 count = 2,然后再进行 2 次迭代,b = 8 和 count = 3。

    我还建议您将 if 语句嵌套在括号中以提高可读性。评论也会有所帮助:) 我是一个统计员,根据变量的名称,我不知道你在做什么。

    如果 b > par,您需要在 if 块中重置计数器。

    喜欢:

    if(num % 2 == 0 && num >= 偶数) {

    if (num > even){ 
    
        even = num; 
        count = 1; 
    
    } else { 
    
        count++; 
    
    }
    

    }

    谢谢。

    JK

    【讨论】:

    • 但理论上我的 if() 只有在找到一个大数字时才会执行,也许是我的 || 之后的所有内容运营商搞砸了?
    • 如果 b > par,您需要在 if 块中重置您的计数器。 if(num % 2 == 0 && num >= even) { if (num > even){ even = b;计数 = 1; } 其他 { 计数++; }
    猜你喜欢
    • 1970-01-01
    • 2021-12-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-17
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多