“我了解如何打开文件,...”
不,不是真的,编码的一个基本规则是“不要硬编码文件名或使用幻数”。这意味着您不想:
secretMessage = fopen("C://Users/anyah/Fall2019/ECE_114/GreatGatsby.txt", "r");
将参数传递给你的程序就是为什么你有参数给main(),例如
int main (int argc, char **argv)
只需提供要读取的文件名作为程序的参数(或默认从stdin 读取)。为此,您可以执行以下操作:
#include <stdio.h>
...
int main (int argc, char **argv) {
...
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
此时您已完成打开文件(或正在从 stdin 读取)并且您已验证文件流已打开以供读取。 p>
要在不动态分配存储的情况下存储多个单词,您需要使用一个二维数组,其中每一行包含一个单词,并且列足以容纳任何单词加上 nul-terminating 字符,所以该行中的字符数组可以被视为字符串。未删节词典中最长的非医学词是 29 个字符(因此总列数为 30 列即可,但32 的下一个二次幂就可以了)
由于您没有在代码中使用 magic-numbers,因此 #define 根据需要使用一个(或多个)常量。您可以使用全局 enum 来完成同样的事情。要为 31 个字符或更少的 128 个单词提供存储空间,您可以这样做:
/* if you need a constant, #define one (or more) */
#define ROWS 128 /* max no. of words to read */
#define COLS 32 /* max no. of chars per-word */
...
char words[ROWS][COLS] = {""}; /* 2D array to hold words */
打开文件并声明存储可以保存您的单词,您现在只需使用fgetc 读取每个字符(或使用fgets 一次读取一行)并收集字符直到'_'、@987654334找到 @ 或 EOF。为了保护您的words 数组边界,请确保您尝试填写的字数不超过ROWS。对于每个单词,通过确保读取的字符数不超过 COL-1(-1 为 nul-terminating 字符节省空间)来保护列边界
将它们放在一起并使用几个计数器变量,您可以这样做:
while (row < ROWS) { /* while rows left in array */
int c, col = 0; /* character c, column counter */
/* loop over each char in word */
for (c = fgetc(fp); col < COLS - 1; col++, c = fgetc(fp)) {
if (c == EOF) /* if EOF jump out of nested loops */
goto done;
if (c == '_' || c == '\n') /* if char is '_' or '\n', get next */
break;
words[row][col] = c; /* assign char to current word */
}
words[row++][col] = 0; /* nul-terminate, advance word count */
}
done:; /* goto label to jump to */
(注意:跳出嵌套循环的唯一直接方法是使用旧的goto 语句。唯一的限制是您不要尝试跳出函数,破坏嵌套循环很好)
一个完整的例子可以是:
#include <stdio.h>
/* if you need a constant, #define one (or more) */
#define ROWS 128 /* max no. of words to read */
#define COLS 32 /* max no. of chars per-word */
int main (int argc, char **argv) {
char words[ROWS][COLS] = {""}; /* 2D array to hold words */
int row = 0, i; /* row (word) and loop counter */
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
while (row < ROWS) { /* while rows left in array */
int c, col = 0; /* character c, column counter */
/* loop over each char in word */
for (c = fgetc(fp); col < COLS - 1; col++, c = fgetc(fp)) {
if (c == EOF) /* if EOF jump out of nested loops */
goto done;
if (c == '_' || c == '\n') /* if char is '_' or '\n', get next */
break;
words[row][col] = c; /* assign char to current word */
}
words[row++][col] = 0; /* nul-terminate, advance word count */
}
done:; /* goto label to jump to */
if (fp != stdin) /* close file if not stdin */
fclose (fp);
for (i = row-1; i >= 0; i--)
printf ((i != row - 1) > 0 ? " %s" : "%s", words[i]);
putchar ('\n');
}
最后的循环只是以相反的顺序输出单词,printf 语句中的 三元 只是确保您不会在第一个单词输出之前打印空格。
输入文件示例
$ cat dat/backwardsfleas.txt
cat_lucky_none_has_cat_my_fleas_has_dog_my
使用/输出示例
$ ./bin/arrayrevwords dat/backwardsfleas.txt
my dog has fleas my cat has none lucky cat
查看一下,如果您还有其他问题,请告诉我。