当我从 C 中的文件中读取单词时出现 while 循环问题
Problem with while loop when I read words from a file in C
我正在尝试创建一个程序:
- 从文件中找到最大长度的单词
- 创建一个动态分配的二维数组
- 将文件中的单词存储到数组
https://gist.github.com/up1047388/363854cbe703a6f297ebb644c50d307f(整个程序)
文件:https://gist.github.com/up1047388/758574c484d916c4aeba106f293f185a
问题出在这个循环中(我使用printf
作为找到问题的提示,但程序没有打印出问题内部的任何内容):
我正在尝试在循环中执行以下操作:
- 将包含文件每一行的字符传递到一个字符串中
- 当程序从文件中读取
'\n'
时存储单词
它存储在字符串中到数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
fp = fopen("C:\Users\Docs\lol.txt", "r");
if (fp == NULL)
{
printf("the file is empty");
exit(8);
}
int length[4];
int ch1;
int counter1 = 0, i = 0;
while ((ch1 = getc(fp)) != EOF)
{
if (ch1 == '\n')
{
length[i] = counter1;
i++;
counter1 = 0;
continue;
}
counter1++;
}
length[i] = counter1;
fseek(fp, 0, SEEK_SET);
int thelongest = length[0];
for (i = 0; i < counter; i++)
{
if (length[i] >= thelongest)
{
thelongest = length[i];
}
}
printf("\n the longest number is %d", thelongest);
char **arr;
**arr = (char **)malloc(sizeof(char *) * 4);
int j = 0 i = 0;
char str[thelongest];
int ch2;
while ((ch2 = getc(fp)) != EOF)
{ // printf("fvfdvdfvd");
if (ch2 == '\n')
{
arr[j] = (char *)malloc(thelongest * sizeof(char));
strcpy(arr[j], str);
// printf("\n%c",str[i]);
j++;
continue;
}
str[i] = ch2;
i++;
}
str[i] = ch2;
strcpy(arr[j], str);
return 0;
}
getc 的 return 值是 int 而不是 char。如果您使用 char(就像您使用的那样),那么 EOF 测试将永远无法运行,因此您将永远循环。
见https://linux.die.net/man/3/getc
你需要
int ch1; <<<<====
int counter1 = 0, i = 0;
while ((ch1 = getc(fp)) != EOF)
{
另外 counter
未在任何地方声明
这一行错得很厉害
**arr = (char**)malloc(sizeof(char*) * counter);
你是说
arr = (char**)malloc(sizeof(char*) * counter);
此行缺少一个“,”
int j = 0 i = 0;
但是你之前已经声明了一个 i
在你的阅读循环中你永远不会 0 终止 'str'
正在阅读逻辑。
您似乎拿不定主意,counter1 是文件中的行数还是当前行的长度。在第一个读取循环中,它肯定是行长度。
但是你用它来遍历数组'length'。其大小为行数。实际上不是,它的大小为 4 - 这也是错误的。
如果你有 'numberOfLines' 和 'currentLineLength'
,你的生活会更轻松
对于初学者而不是这些声明
char ch1;
和
char ch2;
你应该使用
int ch1;
和
int ch2;
否则,如果类型 char
的行为与类型 unsigned char
相同,程序将无法正常运行。
在此声明中重新声明了变量 i。
int j = 0 i = 0;
之前在此声明中声明过
int counter1 = 0, i = 0;
所以编译器会报错。
还有一个错字
for (i = 0; i < counter; i++)
未声明变量counter
。
如果文件的最后一行也以换行符 '\n' 结尾,那么
之后的语句
while( (ch1 = getc(fp))!= EOF )
{
if (ch1 == '\n')
{
length[i]=counter1;
i++;
counter1=0;
continue;
}
counter1++;
}
length[i]=counter1;
可以调用未定义的行为,因为访问数组之外的内存 length
。
这条语句中的左操作数
**arr = (char **)malloc(sizeof(char *) * counter);
具有类型 char
。看来你的意思是
arr = (char **)malloc(sizeof(char *) * counter);
您需要将此数组的大小加 1 以保留 space 作为终止零字符 '[=32=]'
。
char str[thelongest + 1];
对于这个内存分配同样有效
arr[j] = (char *)malloc( ( thelongest + 1 ) * sizeof(char));
在这个 if 语句中
if (ch2 == '\n')
{
arr[j] = (char *)malloc(thelongest * sizeof(char));
strcpy(arr[j], str);
// printf("\n%c",str[i]);
j++;
continue;
}
您忘记附加终止零字符
str[i] = '[=23=]';
并将 i
设置为 0
。
在循环后再次出现这些语句
str[i] = ch2;
strcpy(arr[j], str);
如果文件中的最后一个单词以换行符结束 '\n'
,则可以调用未定义的行为 '\n'
。
此外,由于循环的条件,循环后 ch2 的值等于 -1(如果 char 类型的行为与 signed char 类型相同)
while ((ch2 = getc(fp)) != EOF)
所以这个作业
str[i] = ch2;
没有意义。
存在多个问题:
如果 fopen
失败,则诊断消息不正确
如果文件超过 4 行,你有未定义的行为
**arr = (char **)malloc(sizeof(char *) * 4);
不正确!你应该写:
arr = malloc(sizeof(*aff) * count);
char str[thelongest];
的长度不足以存储长度为 thelongest
的字符串:空终止符需要一个额外的字节。
arr[j] = (char *)malloc(thelongest * sizeof(char));
对于最长的行来说太短,对于其他行来说太大了。您应该使用 strdup()
或分配 i + 1
字节。
您必须在 s[i]
处设置一个空字节才能使用 strcpy(arr[j], str);
你在将单词存储到数组后将 i
重置为 0
。
str[i] = ch2;
最终循环后不正确:ch2
的值为 EOF
,这不是一个字符。如果 i != 0
.
,您应该设置 str[i] = '[=26=]'
并复制最后一行
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char *filename = "C:\Users\Docs\lol.txt";
FILE *fp = fopen(, "r");
if (fp == NULL) {
fprintf(stderr, "cannot open file %s: %s\n", filename, strerror(errno));
exit(8);
}
// compute the number of lines and the maximum length
int len = 0, longest = 0, count = 0;
for (;;) {
int c = getc(fp);
if (c == EOF || c == '\n') {
if (longest < len)
longest = len;
if (len > 0)
count++;
len = 0;
if (c == EOF)
break;
} else {
len++;
}
}
printf("the longest line has %d bytes\n", longest);
printf("%d non empty lines\n", count);
// allocate the array with an extra entry for a NULL terminator
char **arr = calloc(sizeof(**arr), count + 1);
if (arr == NULL) {
fprintf(stderr, "cannot allocate memory\n");
fclose(fp);
return 1;
}
// read the file contents
char str[thelongest + 1];
int i = 0, j = 0;
rewind(fp);
for (;;) {
int c = getc(fp);
if (c == '\n' || c == EOF) {
// store a new word
if (j != 0) {
str[j] = '[=11=]';
arr[i++] = strdup(str);
j = 0;
}
if (c == EOF)
break;
} else {
str[j++] = c;
}
}
arr[i] = NULL;
fclose(fp);
// do something with the array
[...]
// free the array
for (i = 0; i < count; i++)
free(arr[i]);
free(arr);
return 0;
}
我正在尝试创建一个程序:
- 从文件中找到最大长度的单词
- 创建一个动态分配的二维数组
- 将文件中的单词存储到数组
https://gist.github.com/up1047388/363854cbe703a6f297ebb644c50d307f(整个程序)
文件:https://gist.github.com/up1047388/758574c484d916c4aeba106f293f185a
问题出在这个循环中(我使用printf
作为找到问题的提示,但程序没有打印出问题内部的任何内容):
我正在尝试在循环中执行以下操作:
- 将包含文件每一行的字符传递到一个字符串中
- 当程序从文件中读取
'\n'
时存储单词 它存储在字符串中到数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
FILE *fp;
fp = fopen("C:\Users\Docs\lol.txt", "r");
if (fp == NULL)
{
printf("the file is empty");
exit(8);
}
int length[4];
int ch1;
int counter1 = 0, i = 0;
while ((ch1 = getc(fp)) != EOF)
{
if (ch1 == '\n')
{
length[i] = counter1;
i++;
counter1 = 0;
continue;
}
counter1++;
}
length[i] = counter1;
fseek(fp, 0, SEEK_SET);
int thelongest = length[0];
for (i = 0; i < counter; i++)
{
if (length[i] >= thelongest)
{
thelongest = length[i];
}
}
printf("\n the longest number is %d", thelongest);
char **arr;
**arr = (char **)malloc(sizeof(char *) * 4);
int j = 0 i = 0;
char str[thelongest];
int ch2;
while ((ch2 = getc(fp)) != EOF)
{ // printf("fvfdvdfvd");
if (ch2 == '\n')
{
arr[j] = (char *)malloc(thelongest * sizeof(char));
strcpy(arr[j], str);
// printf("\n%c",str[i]);
j++;
continue;
}
str[i] = ch2;
i++;
}
str[i] = ch2;
strcpy(arr[j], str);
return 0;
}
getc 的 return 值是 int 而不是 char。如果您使用 char(就像您使用的那样),那么 EOF 测试将永远无法运行,因此您将永远循环。
见https://linux.die.net/man/3/getc
你需要
int ch1; <<<<====
int counter1 = 0, i = 0;
while ((ch1 = getc(fp)) != EOF)
{
另外 counter
未在任何地方声明
这一行错得很厉害
**arr = (char**)malloc(sizeof(char*) * counter);
你是说
arr = (char**)malloc(sizeof(char*) * counter);
此行缺少一个“,”
int j = 0 i = 0;
但是你之前已经声明了一个 i
在你的阅读循环中你永远不会 0 终止 'str'
正在阅读逻辑。
您似乎拿不定主意,counter1 是文件中的行数还是当前行的长度。在第一个读取循环中,它肯定是行长度。
但是你用它来遍历数组'length'。其大小为行数。实际上不是,它的大小为 4 - 这也是错误的。
如果你有 'numberOfLines' 和 'currentLineLength'
,你的生活会更轻松对于初学者而不是这些声明
char ch1;
和
char ch2;
你应该使用
int ch1;
和
int ch2;
否则,如果类型 char
的行为与类型 unsigned char
相同,程序将无法正常运行。
在此声明中重新声明了变量 i。
int j = 0 i = 0;
之前在此声明中声明过
int counter1 = 0, i = 0;
所以编译器会报错。
还有一个错字
for (i = 0; i < counter; i++)
未声明变量counter
。
如果文件的最后一行也以换行符 '\n' 结尾,那么
之后的语句while( (ch1 = getc(fp))!= EOF )
{
if (ch1 == '\n')
{
length[i]=counter1;
i++;
counter1=0;
continue;
}
counter1++;
}
length[i]=counter1;
可以调用未定义的行为,因为访问数组之外的内存 length
。
这条语句中的左操作数
**arr = (char **)malloc(sizeof(char *) * counter);
具有类型 char
。看来你的意思是
arr = (char **)malloc(sizeof(char *) * counter);
您需要将此数组的大小加 1 以保留 space 作为终止零字符 '[=32=]'
。
char str[thelongest + 1];
对于这个内存分配同样有效
arr[j] = (char *)malloc( ( thelongest + 1 ) * sizeof(char));
在这个 if 语句中
if (ch2 == '\n')
{
arr[j] = (char *)malloc(thelongest * sizeof(char));
strcpy(arr[j], str);
// printf("\n%c",str[i]);
j++;
continue;
}
您忘记附加终止零字符
str[i] = '[=23=]';
并将 i
设置为 0
。
在循环后再次出现这些语句
str[i] = ch2;
strcpy(arr[j], str);
如果文件中的最后一个单词以换行符结束 '\n'
,则可以调用未定义的行为 '\n'
。
此外,由于循环的条件,循环后 ch2 的值等于 -1(如果 char 类型的行为与 signed char 类型相同)
while ((ch2 = getc(fp)) != EOF)
所以这个作业
str[i] = ch2;
没有意义。
存在多个问题:
如果
fopen
失败,则诊断消息不正确如果文件超过 4 行,你有未定义的行为
**arr = (char **)malloc(sizeof(char *) * 4);
不正确!你应该写:arr = malloc(sizeof(*aff) * count);
char str[thelongest];
的长度不足以存储长度为thelongest
的字符串:空终止符需要一个额外的字节。arr[j] = (char *)malloc(thelongest * sizeof(char));
对于最长的行来说太短,对于其他行来说太大了。您应该使用strdup()
或分配i + 1
字节。您必须在
s[i]
处设置一个空字节才能使用strcpy(arr[j], str);
你在将单词存储到数组后将
i
重置为0
。
,您应该设置str[i] = ch2;
最终循环后不正确:ch2
的值为EOF
,这不是一个字符。如果i != 0
.str[i] = '[=26=]'
并复制最后一行
这是修改后的版本:
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
const char *filename = "C:\Users\Docs\lol.txt";
FILE *fp = fopen(, "r");
if (fp == NULL) {
fprintf(stderr, "cannot open file %s: %s\n", filename, strerror(errno));
exit(8);
}
// compute the number of lines and the maximum length
int len = 0, longest = 0, count = 0;
for (;;) {
int c = getc(fp);
if (c == EOF || c == '\n') {
if (longest < len)
longest = len;
if (len > 0)
count++;
len = 0;
if (c == EOF)
break;
} else {
len++;
}
}
printf("the longest line has %d bytes\n", longest);
printf("%d non empty lines\n", count);
// allocate the array with an extra entry for a NULL terminator
char **arr = calloc(sizeof(**arr), count + 1);
if (arr == NULL) {
fprintf(stderr, "cannot allocate memory\n");
fclose(fp);
return 1;
}
// read the file contents
char str[thelongest + 1];
int i = 0, j = 0;
rewind(fp);
for (;;) {
int c = getc(fp);
if (c == '\n' || c == EOF) {
// store a new word
if (j != 0) {
str[j] = '[=11=]';
arr[i++] = strdup(str);
j = 0;
}
if (c == EOF)
break;
} else {
str[j++] = c;
}
}
arr[i] = NULL;
fclose(fp);
// do something with the array
[...]
// free the array
for (i = 0; i < count; i++)
free(arr[i]);
free(arr);
return 0;
}