遍历数组以供用户输入,以打印用户输出为目标

时间:2019-04-20 14:29:31

标签: c

Screen shot showing problem

我试图通过使用C编程语言遍历数组来打印用户的输出。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
//my global variables
char day[15];
int dailyTrainCount[5];     // variable for daily train count
int trainTimeFrame[5], i;   // variable to daily train time frames and loop control

//begin program
int main()
{   
    printf("Welcome to TMS(TRAIN MANAGEMENT SYSTEM)\n");
    printf("Enter day of Operation\n");
    scanf("%s", day);//user input for day 
    printf("How many trains to operate on %s?(Trains shall not exceed 5)\n", 
     day);
    scanf("%d", &dailyTrainCount[5]);//daily train count variable

    //loop to ensure user enters no more than 5 trains per day
    while(dailyTrainCount[5] > 5){
          printf("Daily train count shall not exceed 5\n");
          printf("enter train count\n");
          scanf("%d", &dailyTrainCount[5]);
        }
    //show train menu to user
    printf("%d Train(s) will operate on %s\n",dailyTrainCount[5], day);
    printf("Available time frames\n");
    printf("(1):7AM-10PM\n");
    printf("(2):10AM-1PM\n");
    printf("(3):1PM-4PM\n");
    printf("(4):4PM-7PM\n");

    for(i=0; i<dailyTrainCount[5]; i++)
    {
        printf("Enter time frame for train #%d: \n",i+1);
        scanf("%d", &trainTimeFrame[5]);

    }

    //This loop is not traversing through the entire array, it only shows the last two input
    for(i=0; i<dailyTrainCount[5]; i++)
    {
        printf("Train #%d is set to time frame #%d\n",   // This is the print statement that
                                                         // is not producing the output as I intended
               dailyTrainCount[5], 
               trainTimeFrame[5]);
    }

    return 0;
}

如何正确生成最后一个for循环的输出?我正在使用代码块。我还尝试将所有数组更改为[i],而不是[5]。

1 个答案:

答案 0 :(得分:1)

您对在C中使用数组有基本的误解:

int dailyTrainCount[5];     // variable for daily train count
...
    scanf("%d", &dailyTrainCount[5]);

int dailyTrainCout[5];声明一个包含5个元素的整数数组。这些元素的有效索引为[0-4],C / C ++使用基于 zero 的数组。通过分配给dailyTrainCount[5],您可以将输入分配给存储位置,即在dailyTrainCount数组的最后1位,调用 Undefined Behavior 。 (此时,已定义的程序执行将停止,并且从正常运行到出现SegFaulting的任何事情都可能发生)。更根本的是,只有1 dailyTrainCount,因此不需要以数组开头。

接下来,尽管没有错误,但请避免使用全局变量。很少需要它们。而是在需要变量的范围内声明变量,并将变量作为参数传递给需要对其数据进行操作的任何函数。

使用scanf作为新的C程序员的输入,占了该网站上很大比例的问题。滥用scanf很常见。最常见的误用是无法检查退货。第二种最常见的情况是在匹配失败之后,无法说明输入缓冲区中还有哪些字符未被读取。

如果正确使用,可以使用

scanf。这意味着负责每次检查scanf 退货。您必须处理三个条件

  1. (return == EOF)用户通过按 Ctrl + d (或在Windows上为 Ctrl + z )生成手册EOF来取消输入; < / li>
  2. (return < expected No. of conversions)发生匹配 input 失败。对于 matching 失败,您必须考虑输入缓冲区中剩余的每个字符。 (在输入缓冲区中向前扫描以读取和丢弃字符,直到找到'\n'EOF为止);最后
  3. (return == expected No. of conversions)表示读取成功-然后由您检查输入是否满足任何其他条件(例如,正整数,正浮点,在所需范围内,等等。)。 / li>

注意:在匹配失败或成功读取之后,您应该清空输入缓冲区,以确保为下一次用户输入做好准备,无论使用什么功能用于获取输入。例如,如果您成功使用scanf进行整数输入,但将尾随'\n'留在输入缓冲区中,然后稍后尝试使用fgets输入,则输入将失败并且缓冲区将无论用户键入多少字符,都包含空字符串

为便于正确使用scanf,可以使用简短的辅助函数在每次输入后清空stdin中的字符。每次输入后,您只需调用getchar()进行读取,直到找到'\n'EOF,例如

/* simple function to empty stdin */
void empty_stdin (void)
{
    int c = getchar();

    while (c != '\n' && c != EOF)
        c = getchar();
}

然后,至少 ,您必须验证scanf的返回值是否与您在格式字符串中指定的转换次数匹配,例如

    char day[MAXDAY];
    int /* dailyTrainCount[5],*/ trainsperday,
        trainTimeFrame[MAXTRAIN], i = 0;

    fputs ("Welcome to TMS (TRAIN MANAGEMENT SYSTEM)\n\n"
            "  Enter day of Operation: ", stdout);
    if (scanf ("%14s", day) != 1) { /* VALIDATE EVERY INPUT - check return */
        fputs ("(user canceled day input.)\n", stderr);
        return 1;
    }
    empty_stdin();  /* empty remaining characters in stdin */

注意:,您的dailyTrainCount[]数组已替换为单个整数变量trainsperday,以与数组 {{1} }清除为单个整数。int可以防止输入任何多余的字符,例如用户输入empty_stdin()。如果尝试不清空"Monday April 22, 2019" ...,那么会发生什么情况

要完全验证每个必需的输入,您必须检查并充分处理上述所有三个条件,例如

stdin

这样,您就可以完成火车时刻表,同时处理所有输入故障或值超出范围,同时仍然允许用户在任何时候取消输入并提供正常的退出程序。重做您的代码可能是:

    for (;;) {  /* loop continually until valid input received */
        printf ("\n  How many trains to operate on %s?"
                " [1-5]: ", day);
        int rtn = scanf ("%d", &trainsperday);  /* save scanf return */
        if (rtn == EOF) {   /* handle EOF */
            fputs ("(user canceled day input.)\n", stderr);
            return 1;
        }
        empty_stdin();  /* empty remaining characters in stdin */
        if (rtn < 1)    /* if matching failure */
            fputs ("  (error: invalid integer input.)\n", stderr);
        else if (trainsperday < 0 || 5 < trainsperday)  /* out of range */
            fputs ("  (error: trainsperday exceeds 5.)\n", stderr);
        else            /* good input, break input loop */
            break;
    }

注意:在填充每列火车的时间范围时,使用#include <stdio.h> /* my global variables - don't use them, declare in scope needed, but * do #define any constants needed to avoid magic-numbers in your code */ #define MAXTRAIN 5 #define MAXDAY 15 /* simple function to empty stdin */ void empty_stdin (void) { int c = getchar(); while (c != '\n' && c != EOF) c = getchar(); } int main (void) { char day[MAXDAY]; int /* dailyTrainCount[5],*/ trainsperday, trainTimeFrame[MAXTRAIN], i = 0; fputs ("Welcome to TMS (TRAIN MANAGEMENT SYSTEM)\n\n" " Enter day of Operation: ", stdout); if (scanf ("%14s", day) != 1) { /* VALIDATE EVERY INPUT - check return */ fputs ("(user canceled day input.)\n", stderr); return 1; } empty_stdin(); /* empty remaining characters in stdin */ for (;;) { /* loop continually until valid input received */ printf ("\n How many trains to operate on %s?" " [1-5]: ", day); int rtn = scanf ("%d", &trainsperday); /* save scanf return */ if (rtn == EOF) { /* handle EOF */ fputs ("(user canceled day input.)\n", stderr); return 1; } empty_stdin(); /* empty remaining characters in stdin */ if (rtn < 1) /* if matching failure */ fputs (" (error: invalid integer input.)\n", stderr); else if (trainsperday < 0 || 5 < trainsperday) /* out of range */ fputs (" (error: trainsperday exceeds 5.)\n", stderr); else /* good input, break input loop */ break; } /* show train menu to user */ printf ("\n%d Train(s) will operate on %s\n\n" " Available time frames\n" " (1) - 7AM-10PM\n" " (2) - 10AM-1PM\n" " (3) - 1PM-4PM\n" " (4) - 4PM-7PM\n\n", trainsperday, day); while (i < trainsperday) { /* use while, not for, to handle errors */ printf (" Enter time frame for train #%d: ", i + 1); int rtn = scanf ("%d", &trainTimeFrame[i]); /* save scanf return */ if (rtn == EOF) { /* handle EOF */ fputs ("(user canceled day input.)\n", stderr); return 1; } empty_stdin(); /* empty remaining characters in stdin */ if (rtn < 1) /* if matching failure */ fputs (" (error: invalid integer input, valid input [1-4].)\n", stderr); else if (trainTimeFrame[i] < 0 || 4 < trainTimeFrame[i]) /* valid? */ fputs (" (error: invalid time frame, valid input [1-4].)\n", stderr); else /* good input, now increment i */ i++; } /* output train schedule */ printf ("\nTrain Schedule:\n\n"); for (i = 0; i < trainsperday; i++) printf (" Train #%d is set to time frame #%d\n", i + 1, trainTimeFrame[i]); return 0; } 循环而不是while循环。如果使用了for且发生故障,您将无法恢复。使用for并且仅在有效输入上增加计数器即可提供解决方案)

现在,只要您编写一个需要输入的程序,就可以尝试将其破坏。故意输入无效的输入以执行代码的错误处理。如果损坏,请修复并重试。在尝试了所有可以想到的无效输入之后,请在键盘上踩一下猫脚。如果通过所有测试,则可以合理地确定您已经涵盖了用户将提供的最可能的滥用情况。

使用/输出示例

为此目的故意输入了无效的信息。

while

仔细检查一下,如果还有其他问题,请告诉我。