我试图通过使用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]。
答案 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
的退货。您必须处理三个条件
(return == EOF)
用户通过按 Ctrl + d (或在Windows上为 Ctrl + z )生成手册EOF
来取消输入; < / li>
(return < expected No. of conversions)
发生匹配或 input 失败。对于 matching 失败,您必须考虑输入缓冲区中剩余的每个字符。 (在输入缓冲区中向前扫描以读取和丢弃字符,直到找到'\n'
或EOF
为止);最后(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
仔细检查一下,如果还有其他问题,请告诉我。