c - 如何从 Txt(C) 读取和返回随机行
问题描述
文本每行包含 100 个单词,代码下方最多 20 个字符的 1 个单词打印相同的内容,我想要这个随机的,如何编辑我的代码?两个 printf 函数打印同一个单词。我浏览了所有相关的主题,但我没有开悟,因为我是一个新学习者。
int main(){
char *str;
char *str_2;
printf("%s",word("words.txt",str));
printf("%s",word("words.txt",str_2));
}
char *word(char *file, char *str0) {
int end, loop, line;
int i;
str0 = (char *)malloc(20);
FILE *fd = fopen(file, "r");
if (fd == NULL) {
printf("Failed to open file\n");
return (NULL);
}
srand(time(NULL));
line = rand() % 100 + 1;
for (end = loop = 0; loop < line; ++loop) {
if (NULL == fgets(str0, 20, fd)) {
end = 1;
break;
}
}
if (!end){
fclose(fd);
return str0;
free(str0);
}
}
解决方案
有许多错误和一些改进。
这是您的代码的注释版本,其中显示了错误以及潜在的更改和修复:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
char *
word(char *file, char *str0)
{
int end, loop, line;
#if 0
int i;
#endif
// NOTE/BUG: don't cast the return of malloc
#if 0
str0 = (char *) malloc(20);
#else
str0 = malloc(20);
#endif
FILE *fd = fopen(file, "r");
// NOTE/BUG: opening and closing the file on _each_ call is wasteful -- having
// main open the file and passing the file descriptor is faster
if (fd == NULL) {
printf("Failed to open file\n");
return (NULL);
}
// NOTE/BUG: put this in main
#if 0
srand(time(NULL));
#endif
line = rand() % 100 + 1;
for (end = loop = 0; loop < line; ++loop) {
if (NULL == fgets(str0, 20, fd)) {
end = 1;
break;
}
}
#if 1
fclose(fd);
#endif
if (!end) {
// NOTE/BUG: the fclose should _always_ be done (even on EOF) -- put it above
#if 0
fclose(fd);
#endif
return str0;
// NOTE/BUG: this will _never_ be executed -- so the return will leak this
// memory -- put free in main
#if 0
free(str0);
#endif
}
// NOTE/BUG: on EOF, we fall through to here -- we have no return statement
// for this case
#if 1
return str0;
#endif
}
int
main(void)
{
char *str;
char *str_2;
#if 1
srand(time(NULL));
#endif
// NOTE/BUG: passing the 2nd argument does nothing because word will toss any
// value
// NOTE/BUG: str and str_2 are _uninitialized
printf("%s", word("words.txt", str));
printf("%s", word("words.txt", str_2));
// NOTE/BUG: no return for main
#if 1
return 0;
#endif
}
这是一个清理后的工作版本:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
char *
word(FILE *fd)
{
char *str0;
int end, loop, line;
int len;
len = 20;
str0 = malloc(len);
line = rand() % 100 + 1;
rewind(fd);
end = 0;
for (loop = 0; loop < line; ++loop) {
if (NULL == fgets(str0, len, fd)) {
end = 1;
break;
}
}
if (end) {
free(str0);
str0 = NULL;
}
return str0;
}
int
main(void)
{
char *str;
srand(time(NULL));
char *file = "words.txt";
FILE *fd = fopen(file, "r");
if (fd == NULL) {
printf("Failed to open file\n");
return 1;
}
for (int i = 1; i <= 20; ++i) {
str = word(fd);
if (str == NULL)
continue;
printf("%d: %s", i, str);
free(str);
}
fclose(fd);
return 0;
}
参与可能是浪费malloc
。word
如果您打算让调用者将所有字符串保存在一个数组中,这并不是绝对错误的。
很多时候,对于诸如 的函数word
,调用者可以将缓冲区指针及其最大长度作为参数传递下来。这使得word
更类似于fgets
这是一个这样做的版本,以说明另一种方法:
#include <stdio.h>
#include <time.h>
#include <stdlib.h>
int
word(FILE *fd,char *str0,int len)
{
int found, loop, line;
line = rand() % 100 + 1;
rewind(fd);
found = 1;
for (loop = 0; loop < line; ++loop) {
if (NULL == fgets(str0, len, fd)) {
found = 0;
break;
}
}
return found;
}
int
main(void)
{
char *str;
int len = 20;
srand(time(NULL));
char *file = "words.txt";
FILE *fd = fopen(file, "r");
if (fd == NULL) {
printf("Failed to open file\n");
return 1;
}
str = malloc(len);
for (int i = 1; i <= 20; ++i) {
if (! word(fd,str,len))
continue;
printf("%d: %s", i, str);
}
fclose(fd);
free(str);
return 0;
}
推荐阅读
- android-layout - ExoPlayer2 可缩放视图?
- python - 带有 Python 输入的 TypeError 不支持的操作数
- python - TypeError:只有整数标量数组可以转换为标量索引——Python 3.6.5
- php - PHP函数在do while
- python - 使用pyparsing查找关键字的前缀和后缀
- c - 最大行长程序在c中打印不可读的字符
- android - 无法从嵌套的 Hashmap 访问值
- assembly - 为什么 Mi TI-83 Premium CE 上没有 Asm83CEPgrm 命令
- python - 带有 GPU 支持的 XGBoost 安装错误:无法复制“xgboost\lib”:不存在或不是常规文件
- javascript - 使用 Gulp Watch 时 CSS 的 $ 变量在 Git 中不起作用