我立即注意到了一件事情。您的do while 循环正在检查val 中的"X",而该值实际上在menu 中。
除了这种可能性(val 可能是 "X" 开头,这可能导致退出循环,无论输入的值如何),没有任何东西跳出显然会导致函数或循环过早退出。我认为你最好发布你的完整代码库,这样我们就不用猜测太多了。
更新:
不要在作业中使用以下内容 - 你几乎肯定会因为剽窃而失败(因为你的教育工作者,假设他们不是完全的傻瓜,会寻找从这些网站上获取的工作)。
我只是想让您了解可以使用哪些用户 I/O 来使您的程序更加健壮。正如一位乐于助人的人指出的那样,您永远不应该使用没有缓冲区溢出保护的输入例程作为选项,因为这几乎肯定会允许恶意输入使您的代码崩溃(这是最好的情况,最坏的情况是它们将接管您的计算机)。
这意味着没有gets,您需要改用fgets,因为它可以限制实际输入的信息量。此外,我倾向于避免使用scanf 和fscanf,因为这些函数中的任何故障实际上都会使输入文件指针处于不确定的位置。
我发现使用fgets 获得整行要好得多,检查您是否确实获得整行,然后在该行上使用sscanf。这样一来,您就可以确定您在一条线的边界上,您已经拥有一整条线,然后您可以sscanf 那条线随心所欲,直到您将它与某些东西相匹配。
为此,您可能需要查看以下代码:
#include <stdio.h>
#define FSPEC "file.txt"
// Skip to the end of the line. This is used in some
// places to ensure there's no characters left in the
// input buffer. It basically discards characters
// from that buffer until it reaches the end of a line.
static void skipLine (void) {
char ch = ' ';
while ((ch != '\n') && (ch != EOF))
ch = getchar();
}
// Get a line of input from the user (with length checking).
static char *getLine (char *prompt, char *line, int sz) {
// Output prompt, get line if available.
// If no line available (EOF/error), output newline.
printf ("%s", prompt);
if (fgets (line, sz, stdin) == NULL) {
printf ("\n");
return NULL;
}
// If line was too long (no '\n' at end), throw away
// rest of line and flag error.
if (line[strlen (line) - 1] != '\n') {
skipLine();
return NULL;
}
// Otherwise line was complete, return it.
return line;
}
// Output the menu and get a choice from the user.
static char doMenu (void) {
char cmd[1+2]; // need space for char, '\n' and '\0'.
// Output the menu.
printf ("\n");
printf ("\n");
printf ("Main menu\n");
printf ("---------\n");
printf ("1. Input a line\n");
printf ("2. Output the file\n");
printf ("3. Clear the file\n");
printf ("\n");
printf ("x. Exit\n");
printf ("\n");
// Get the user input and return it.
if (getLine ("Enter choice (1,2,3,x): ", cmd, sizeof(cmd)) == NULL)
return '\n';
printf ("\n");
return cmd[0];
}
static void doOption1 (void) {
FILE *fh;
char *ln;
char buff[15+2]; // need space for line, '\n' and '\0'.
// Get and check line, add to file if okay.
if ((ln = getLine ("Enter line: ", buff, sizeof(buff))) == NULL) {
printf ("Bad input line\n");
} else {
fh = fopen (FSPEC, "a");
if (fh != NULL) {
fputs (ln, fh);
fclose (fh);
}
}
}
static void doOption2 (void) {
FILE *fh;
int intch;
// Output the file contents.
printf ("=====\n");
fh = fopen (FSPEC, "r");
if (fh != NULL) {
while ((intch = fgetc (fh)) != EOF)
putchar (intch);
fclose (fh);
}
printf ("=====\n");
}
static void doOption3 (void) {
FILE *fh;
// Clear the file.
fh = fopen (FSPEC, "w");
if (fh != NULL)
fclose (fh);
}
// Main program basically just keeps asking the user for input
// until they indicate they're finished.
int main (void) {
char menuItem;
// Get asking for user input until exit is chosen.
while ((menuItem = doMenu()) != 'x') {
switch (menuItem) {
case '1': doOption1(); break;
case '2': doOption2(); break;
case '3': doOption3(); break;
default: printf ("Invalid choice\n"); break;
}
}
return 0;
}