C 中的 getline() 创建一个无限循环并跳过第一个单词?
getline() in C creating an infinite loop and skipping first word?
我是 C 的初学者,我正在尝试创建一个简单的待办事项列表程序。我正在尝试在 while 循环中使用 getline,正如我在另一个堆栈溢出答案中看到的那样,我认为我理解它,但它只是在创建一个无限循环。此外,由于某种原因,它似乎跳过了第一个词。到目前为止,这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *list;
int i = 0;
int item = 0;
char items[10];
char chars[1000];
char * line = NULL;
size_t len = 0;
ssize_t read;
int main() {
list = fopen("/Users/bendavies/Documents/C/list.txt", "r");
int letterCount = fscanf(list,"%s",chars);
printf("Welcome to the to-do list. It can hold up to 10 items.\n");
printf("%d\n", letterCount);
if (letterCount == -1) {
printf("The list currently has no items!\n");
} else {
while ((read = getline(&line, &len, list)) != 1) {
item += 1;
printf("%d. %s", item, line);
}
}
fclose(list);
return 0;
}
我目前使用以下 list.txt 获得的输出:
Eat food
Drink water
Breath air
是:
1. food
2. Drink water
3. Breath air
4. 18446744073709551615
5. 18446744073709551615
等等等等。
提前致谢! :)
but it's just creating an infinite loop.
你的这行代码:while ((read = getline(&line, &len, list)) != 1)
除非一行包含1
个字符(只是一个换行符),否则它将是一个无限循环。 POSIX getline()
函数将 return -1
(不是 EOF
,尽管 EOF
通常是 -1) 当文件被完全读取时。所以将该行更改为:
while ((read = getline(&line, &len, list)) != -1)
但是,我没有看到你在那个循环中使用 read
的值,所以这样会更好:
- 修复 1:
while (getline(&line, &len, list) != -1)
在那个循环中,我看到:printf("%d. %s", item, line);
您可能会发现 getline()
的非常旧的实现不包含换行符,在这种情况下,如果您希望在单独的行中输出,则需要放置一个 \n
:
- 修复 2:
printf("%d. %s\n", item, line);
但是,如果您使用更现代的实现,它将根据 POSIX 规范保留换行符。
此外,如果文件中的最后一个 'line' 没有以换行符结束,您可能仍想添加一个。在这种情况下,您可以保留读取长度并使用它来检测行尾是否有换行符。
Also it seems to be skipping the first word for some reason
因为int letterCount = fscanf(list,"%s",chars);
fscanf
读取文件的第一个单词。现在文件指针位于该位置(第一个单词的末尾),将从该位置进一步读取文件。
因此,从文件中读取第一个单词后,将文件指针重新定位到文件开头:
修复 3:
int letterCount = fscanf(list,"%s",chars);
fseek(list, 0, SEEK_SET); // <-- this will reposition the file pointer as required
我是 C 的初学者,我正在尝试创建一个简单的待办事项列表程序。我正在尝试在 while 循环中使用 getline,正如我在另一个堆栈溢出答案中看到的那样,我认为我理解它,但它只是在创建一个无限循环。此外,由于某种原因,它似乎跳过了第一个词。到目前为止,这是我的代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
FILE *list;
int i = 0;
int item = 0;
char items[10];
char chars[1000];
char * line = NULL;
size_t len = 0;
ssize_t read;
int main() {
list = fopen("/Users/bendavies/Documents/C/list.txt", "r");
int letterCount = fscanf(list,"%s",chars);
printf("Welcome to the to-do list. It can hold up to 10 items.\n");
printf("%d\n", letterCount);
if (letterCount == -1) {
printf("The list currently has no items!\n");
} else {
while ((read = getline(&line, &len, list)) != 1) {
item += 1;
printf("%d. %s", item, line);
}
}
fclose(list);
return 0;
}
我目前使用以下 list.txt 获得的输出:
Eat food
Drink water
Breath air
是:
1. food
2. Drink water
3. Breath air
4. 18446744073709551615
5. 18446744073709551615
等等等等。
提前致谢! :)
but it's just creating an infinite loop.
你的这行代码:while ((read = getline(&line, &len, list)) != 1)
除非一行包含1
个字符(只是一个换行符),否则它将是一个无限循环。 POSIX getline()
函数将 return -1
(不是 EOF
,尽管 EOF
通常是 -1) 当文件被完全读取时。所以将该行更改为:
while ((read = getline(&line, &len, list)) != -1)
但是,我没有看到你在那个循环中使用 read
的值,所以这样会更好:
- 修复 1:
while (getline(&line, &len, list) != -1)
在那个循环中,我看到:printf("%d. %s", item, line);
您可能会发现 getline()
的非常旧的实现不包含换行符,在这种情况下,如果您希望在单独的行中输出,则需要放置一个 \n
:
- 修复 2:
printf("%d. %s\n", item, line);
但是,如果您使用更现代的实现,它将根据 POSIX 规范保留换行符。
此外,如果文件中的最后一个 'line' 没有以换行符结束,您可能仍想添加一个。在这种情况下,您可以保留读取长度并使用它来检测行尾是否有换行符。
Also it seems to be skipping the first word for some reason
因为int letterCount = fscanf(list,"%s",chars);
fscanf
读取文件的第一个单词。现在文件指针位于该位置(第一个单词的末尾),将从该位置进一步读取文件。
因此,从文件中读取第一个单词后,将文件指针重新定位到文件开头:
修复 3:
int letterCount = fscanf(list,"%s",chars); fseek(list, 0, SEEK_SET); // <-- this will reposition the file pointer as required