c - fgets 正在返回一个空白屏幕
问题描述
我是 C 新手,这是我的第一个项目,并且一直在自学。在我的程序中,我的一个函数需要从文件中读取一行,并将其存储在一个 char 数组中。当我使用 gdb 跟踪程序时,数组 (line[]) 只是零。这导致我的程序返回错误“错误:资产文件中的一行缺少':'分隔符\ n”这是我的代码:
//return the line number (0 based) that the cmd is on, -1 if absent
int locateCmd(char cmd[]) {
int lineIndex = -1; //-1, because lineIndex is incramented before the posible return
char cmdTemp[10] = "\0";
//create a compareable cmd with correct cmd that has its remaining values zeroed out
char cmdCmp[10] = "\0";
memset(cmdCmp, 0, sizeof(cmdCmp));
for (int i = 0; i < strlen(cmd); i++) {
cmdCmp[i] = cmd[i];
}
FILE *file = fopen(ASSET_FILE, "r");
//loop until target line is reached
while (strcmp(cmdTemp, cmdCmp) != 0) {
//check if last line is read
if (lineIndex == lineCounter(file)-1) {
return -1;
}
memset(cmdTemp, 0, sizeof(cmdTemp));
char line[61];
fgets(line, 61, file);
//set cmdTemp to the command on current line
lineIndex++;
for (int i = 0; line[i] != ':'; i++) {
cmdTemp[i] = line[i];
//return error if line doesn't contain a ':'
if (line[i] = '\n') {
printf("Error: a line in the asset file lacks a ':' separator\n");
exit(1);
}
}
}
return lineIndex;
}
在某些情况下,这个函数被传递了一个命令,它的工作是读取一个看起来像这样的文档:
command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
并选择存储传递的命令 (cmd[]) 的行。
问题出在第 24 行的 fgets 上。我已将此代码的相关部分分离到一个较小的测试程序中,它工作正常。有效的测试程序是:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]) {
FILE *file = fopen("tutorInfo.txt", "r");
char line[61];
fgets(line, 61, file);
printf("%s\n", line);
}
我的测试程序的正确执行让我相信我的函数中的其他代码导致了这个问题,但我不确定是什么。需要注意的是,有问题的代码与我的示例程序具有相同的导入。任何帮助将非常感激。
解决方案
由于 OP 没有提供最小、完整和可验证的示例,我必须根据问题中提供的功能描述来回答。
我已经介绍了一些错误和极端情况,但我确定我错过了一些。该方法也效率低下,因为文件被一遍又一遍地读取,而不是解析一次并返回哈希/映射/目录以便于查找。在现实生活中的代码中,我会使用GLib之类的东西,而不是浪费时间尝试重新发明轮子……
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define LINE_BUFFER_LENGTH 200
unsigned int locateCmd(FILE *fh, const char *key, const char **cmd_line) {
unsigned int found = 0;
size_t key_length = strlen(key);
*cmd_line = NULL;
/* make sure to start read from start of file */
rewind(fh);
unsigned int line_no = 0;
static char buffer[LINE_BUFFER_LENGTH];
while (!feof(fh) && (found == 0)) {
// NOTE: EOF condition will be checked on the next iteration
fgets(buffer, sizeof(buffer), fh);
size_t length = strlen(buffer);
line_no++;
if (buffer[length - 1] != '\n') {
printf("line %u is too long, aborting!\n", line_no);
return(0);
}
if ((strncmp(key, buffer, key_length) == 0) &&
(buffer[key_length] == ':')) {
found = line_no;
buffer[length - 1] = '\0'; // strip line ending
*cmd_line = &buffer[key_length + 1];
}
}
return(found);
}
int main(int argc, char *argv[]) {
FILE *fh = fopen("dummy.txt", "r");
if (!fh) {
perror("file open");
return(1);
}
int ret = 0;
while (--argc > 0) {
const char *cmd;
const char *key = *++argv;
unsigned line_no = locateCmd(fh, key, &cmd);
if (line_no != 0) {
printf("key '%s' found on line %u: %s\n", key, line_no, cmd);
ret = 0;
} else {
printf("key '%s' not found!\n", key);
};
}
if (fclose(fh) != 0) {
perror("file close");
return(1);
}
return(ret);
}
测试输入dummy.txt
:
command:aBunchOfInfoOnTheComand
anotherCommand:aBunchOfInfoOnTheComand
brokenline
foo:bar
toolong:sadflkjaLKFJASDJFLKASJDFLKSAJ DLFKJ SLDKJFLKASDFASDFKJASKLDJFLKASJDFLKJASDLKFJASLKDFJLKASDJFLKASJDLFKJASDKLFJKLASDJFLKSAJDFLKJASDLKFJKLASDJFLKASJDFKLJASDLKFJLKASDJFLKASJDFLKJSADLKFJASLKDJFLKC
一些测试运行:
$ gcc -Wall -o dummy dummy.c
$ ./dummy command foo bar
key 'command' found on line 1: aBunchOfInfoOnTheComand
key 'foo' found on line 5: bar
line 6 is too long, aborting!
key 'bar' not found!
推荐阅读
- vba - 如何从 VBA 调用 ScCreateConversationIndex?
- arrays - C中的 int* p 和 (int*) p 有什么区别
- javascript - 使用 javascript 删除 li 元素的 ul 类
- c# - 如何在 Xamarin Android 中的 UserInterface 线程上实现 Timer Elapsed Event
- java - 从字符串中删除连续的重复字符
- python - 如何使用 BeautifulSoup 在 span h5 a href 链接中提取标题
- excel - 对应单元格的Excel循环
- firebase - Flutter:方法[]在null上被调用
- python - 在 Python 中引用另一个枚举作为枚举值?
- c# - 每个用户只允许一个应用程序实例