设置循环次数

时间:2016-11-16 11:23:57

标签: c loops for-loop

我有问题。我需要 tool.c 文件中的函数只循环所需的次数。就像它通过整个输入循环后停止。我的老师说我应该通过第二个论点,但课程已经完成,我不知道它应该是什么样的。

的main.c

#include <stdio.h>
#include <stdlib.h>
#include "tools.h"

int main(int argc, char *argv[]) {
    int count[256] = { 0 };
    int c;
    while ( (c=getchar())!=EOF ){
        count[c]++;
    }
    switch (argc > 1 && argv[1][1]) {
    case 'm': case 'M':
        mostOften(count);
        break;
    case 'l': case 'L':
        leastOften(count);
        break;
    default:
        mostOften(count);
        break;
    }
    return 0;
}

tools.c

#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#include "tools.h"

void mostOften(int *s) {
    int j, a = 0;
    int max=0, cha;
    for(j=32; j<126; j++){
        if(s[j]>max) {
                max=s[j];
                cha=j;
        }
    a++;
    }
    printf("char %c: %d times\n", cha, max);
}

void leastOften(int *s) {
    int j, a = 0;
    int min=INT_MAX, cha;
    for(j=32; j<126; j++){
        if(s[j] && s[j]<=min) {
                min=s[j];
                cha=j;
        }
    a++;
    }
    printf("char %c: %d times\n", cha, min);
}

例如,如果我输入

  

段落

我希望它只循环9次,基本上我需要设置一些if statment来停止循环

2 个答案:

答案 0 :(得分:0)

您的主程序首先构造输入中出现的字符的直方图,然后搜索最常用或最不频繁的可打印字符。

如果你想避免这个第二个循环(搜索阶段),你需要在每次读取一个字符时逐步更新最常用字符或最不频繁字符的索引。

以下是一个例子:

#include <ctype.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>

int main ()
{
    int count[256] = { 0 };
    int c;
    int index_min = -1;
    int min = INT_MAX;
    int index_max = -1;
    int max = INT_MIN;

    while ((c = getchar()) != EOF) {
        if (isprint (c)) {
            count[c]++;

            // update min
            if (count[c] < min) {
                min = count[c];
                index_min = c;
            }

            // update max
            if (count[c] > max) {
                max = count[c];
                index_max = c;
            }
        }
    }

    printf ("least common printable char: ");
    if (index_min != -1) {
        printf ("`%c` (%d times)\n", index_min, min);
    }
    else {
        printf ("N/A\n");
    }

    printf ("most common printable char:  ");
    if (index_max != -1) {
        printf ("`%c` (%d times)\n", index_max, max);
    }
    else {
        printf ("N/A\n");
    }

    return 0;
}

答案 1 :(得分:0)

从查看如何设置问题看起来,您看起来很混乱迭代作为输入一部分的字符,以及保存字符读取频率的数组。

首先,要使代码可读,请不要在代码中使用幻数,例如: 32126。而是使用您尝试表示的字符,例如空间)和~代字号)。例如,而不是使用:

for(j=32; j<126; j++){

你可以使用:

for(j = ' '; j < '~'; j++){

这也有它的陷阱。为什么?你不想循环遍历字符,你实际上想要遍历count数组中的元素,这些元素保存输入中每个字符出现的频率。换句话说,您需要一个保持最小95整数的数组,它将保持输入中每个字符出现的频率。既然你知道将会在32126之后隐藏它的角色,只需在{{ARSZ中为你的数组大小(可能称为tools.h)声明一个常量。 1}},例如

#define ARSZ 95

然后在阅读完输入并填充count数组后,只需迭代count数组一次即可获得mostoftenleastoften数字。此外,由于count中的元素数量不变,因此您无需将count的大小传递给mostoftenleastoften - 您已经知道了存在许多元素,95。 (有关仅对输入中存在的字符进行迭代的注释,请参见下文)

(如果数组大小不是常数(并且您没有传递带有像 nul-terminated 字符串这样的标记符的数组),或者您需要迭代的元素数量不知道编译时,然后你需要将数组的大小传递给函数。

(除了另一个快速,C通常使用所有小写的变量名称,保留常量和宏的所有大写。你通常不会看到 MixedCase camelCase C中的变量名,留给C ++)

接下来,虽然您应该使用getopt来处理命令行参数,但您可以使用快速检查相关参数的第二个字符,但是您需要验证您至少有一个参数要检查并且论证不是空字符串。基本上,你要检查:

if (argc > 1 && *argv[1])  /* check argc & not empty-string */
    switch (argv[1][1]) {
        case 'm':
            mostoften (count);
            break;
        case 'M':
            mostoften (count);
            break;
        case 'l':
            leastoften (count);
            break;
        case 'L':
            leastoften (count);
            break;
        default:
            fprintf (stderr, "warning: unrecognized option, using 'mostoften'.\n");
            mostoften (count);
    }
else {
    fprintf (stderr, "warning: no option given using 'mostoften'.\n");
    mostoften (count);
}

note :对于switch的任何一个案例(某些编译器提供非标准扩展),您不能将两个常量条件放在一起。另请注意,break案例中您不需要default,也不会有任何失败。

完全放弃,您可以将tools.h写成类似于:

#include <stdio.h>
#include <limits.h>

#define ARSZ 95

int mostoften (int *a);
int leastoften (int *a);

您的tools.c as:

#include "tools.h"

int mostoften (int *a) {

    int i, max = INT_MIN, cha = '0';

    for (i = 0; i < ARSZ; i++)
        if (a[i] > max) {
            max = a[i];
            cha = i + ' ';
        }

    printf ("char '%c' : %d times\n", cha, max);

    return max;
}

int leastoften (int *a) {

    int i, min = INT_MAX, cha = '0';

    for (i = 0; i < ARSZ; i++)
        if (a[i] < min) {
            min = a[i];
            cha = i + ' ';
        }

    printf ("char '%c' : %d times\n", cha, min);

    return min;
}

你知道如果maxmin对于2个不同的字符是相同的,你将选择第一个,在leastoften的情况下,你将始终选择第一个频率为0的字符。要纠正此问题,您需要保留第二个数组(或2D数组或结构),以跟踪输入中存在哪些字符,并仅考虑这些字符的频率。

最后,您的main.c可以写成:

#include "tools.h"

int main (int argc, char **argv) {

    int c = 0, count[ARSZ] = {0};

    while ((c = getchar ()) != EOF)
        if (' ' <= c && c <= '~')
            count[c - ' ']++;

    if (argc > 1 && *argv[1])  /* check argc & not empty-string */
        switch (argv[1][1]) {
            case 'm':
                mostoften (count);
                break;
            case 'M':
                mostoften (count);
                break;
            case 'l':
                leastoften (count);
                break;
            case 'L':
                leastoften (count);
                break;
            default:
                fprintf (stderr, "warning: unrecognized option, using "
                                 "'mostoften'.\n");
                mostoften (count);
        }
    else {
        fprintf (stderr, "warning: no option given using 'mostoften'.\n");
        mostoften (count);
    }

    return 0;
}

有许多不同的方法可以完成此任务,但鉴于您的初始代码,这与您的意图保持一致。仔细看看,如果您有任何疑问,请告诉我。如果您想要最简单的方法来跟踪输入中存在的字符而不使用结构,那么只需将count声明为count[ARSZ][2]并使用附加元素指示存在哪些字符即可。 (您可以将数组作为int a[][2]int (*a)[2]传递给您的函数。祝您好运。