我的代码在长文本时崩溃?从文件中逐个字符地读取到 C 中的动态字符数组
My code crashes at long texts? Reading from file character by character into a dynamic char array in C
我想从txt文件中读取整篇文章,然后打印出来。
它应该具有动态内存管理和逐个字符。
我的代码适用于短文本(最多 40 个字符),但当我阅读更多字符时崩溃。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *s;
int n, i;
s = (char*) malloc(sizeof(char));
n=0;
FILE *f=fopen("input.txt","r");
while (fscanf(f, "%c", &s[n]) != EOF)
n++;
fclose(f);
free(s);
for (i=0;i<n;i++)
printf("%c",s[i]);
return 0;
}
您只为一个字符 (sizeof(char)
) 分配 space:
s = (char*) malloc(sizeof(char));
如果要存储更多字符,则必须分配更多 space,例如:
s = (char*) malloc(sizeof(char) * 100);
要读取整个文件,您最好先找出文件有多大,这样您就知道需要为 s
.
分配多少 space
请don't cast malloc
.
你分配了错误的字节数,sizeof(char)
return你的大小是
一个 char
,所以你只分配了一个字节。这还不够hold
一个字符串。
你应该像这样使用 malloc
:
int *a = malloc(100 * sizeof *a);
if(a == NULL)
{
// error handling
// do not continue
}
使用sizeof *a
优于sizeof(int)
,因为它总是return
正确的字节数。 sizeof(int)
也会这样做,但问题是
这里是人为因素,很容易写错sizeof(*int)
反而。关于这个问题,这里有成千上万的问题。
请注意,char
被定义为具有 1 的大小,这就是为什么当您
为字符串或 char
数组分配内存,人们通常不会写
* sizeof *a
:
char *s = malloc(100);
// instead of
char *s = malloc(100 * sizeof *s);
就好了。但同样,这仅适用于 char
。对于其他类型
您需要使用 sizeof
运算符。
您应该始终检查 malloc
的 return 值,因为如果它 returns
NULL
,您无法访问该内存。
while (fscanf(f, "%c", &s[n]) != EOF)
n++;
例如,如果您分配了 100 个空间,则必须检查您是否没有
达到了极限。否则你会溢出 s
:
char *s = malloc(100);
if(s == NULL)
{
fprintf(stderr, "not enough memory\n");
return 1;
}
int n = 0;
while ((fscanf(f, "%c", &s[n]) != EOF) && n < 100)
n++;
在这种情况下,您没有使用分配的内存来存储字符串,所以它是
很好,它没有 '[=34=]'
终止字节。但是,如果你想
有一个字符串,你需要写一个:
while ((fscanf(f, "%c", &s[n]) != EOF) && n < 99)
n++;
s[n] = '[=14=]';
你也在做这个
free(s);
for (i=0;i<n;i++)
printf("%c",s[i]);
您正在释放内存,然后尝试访问它。你必须做
反过来,访问然后免费。
正确方法:
for (i=0;i<n;i++)
printf("%c",s[i]);
free(s);
编辑
如果你想将整个文件的内容放在一个字符串中,那么你有 2
选项:
- 预先计算文件的长度,然后使用分配正确的
数据量
- 一次读取一个固定大小的字节块,每次都调整内存大小
你读了一个新的块。
第一个很简单,第二个有点复杂,因为
你必须阅读内容,看看你读了多少,调整内存大小
realloc
,检查调整大小是否成功。这是你可以
当你掌握了简单内存管理的知识时再做。
我会告诉你第一个,因为它更容易。函数 fseek
允许您将文件指针前进到文件末尾,使用
函数 ftell
you can get the size of the file and with rewind
倒回文件指针并将其设置为开头:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if(argc != 2)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
return 0;
}
FILE *fp = fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open %s for reading.\n", argv[1]);
return 1;
}
// calculating the size
// setting file pointer to the end of the file
if(fseek(fp, 0L, SEEK_END) < 0)
{
fprintf(stderr, "Could not set the file pointer to the end\n");
fclose(fp);
return 1;
}
// getting the size
long size = ftell(fp);
if(size < 0)
{
fprintf(stderr, "Could not calculate the size\n");
fclose(fp);
return 1;
}
printf("file size of %s: %ld\n", argv[1], size);
// rewinding the file pointer to the beginning of the file
rewind(fp);
char *s = malloc(size + 1); // +1 for the 0-terminating byte
if(s == NULL)
{
fprintf(stderr, "not enough memory\n");
fclose(fp);
return 1;
}
int n = 0;
// here the check && n < size is not needed
// you allocated enough memory already
while(fscanf(fp, "%c", &s[n]) != EOF)
n++;
s[n] = '[=17=]'; // writing the 0-terminating byte
fclose(fp);
printf("Contents of file %s\n\n", argv[1]);
for(int i=0; i<n; i++)
printf("%c",s[i]);
free(s);
return 0;
}
在 fseek 的帮助下计算文件的大小。
fseek(fp, 0L, SEEK_END); sz = ftell(fp);
然后您可以返回到文件的开头
fseek(fp, 0L, SEEK_SET);
通过 malloc 分配那么多内存。
S= (char*)malloc((sizeof(char)×sz)+1)
现在你可以使用这个内存来复制字节 while lopp
我想从txt文件中读取整篇文章,然后打印出来。 它应该具有动态内存管理和逐个字符。 我的代码适用于短文本(最多 40 个字符),但当我阅读更多字符时崩溃。
#include <stdio.h>
#include <stdlib.h>
int main()
{
char *s;
int n, i;
s = (char*) malloc(sizeof(char));
n=0;
FILE *f=fopen("input.txt","r");
while (fscanf(f, "%c", &s[n]) != EOF)
n++;
fclose(f);
free(s);
for (i=0;i<n;i++)
printf("%c",s[i]);
return 0;
}
您只为一个字符 (sizeof(char)
) 分配 space:
s = (char*) malloc(sizeof(char));
如果要存储更多字符,则必须分配更多 space,例如:
s = (char*) malloc(sizeof(char) * 100);
要读取整个文件,您最好先找出文件有多大,这样您就知道需要为 s
.
请don't cast malloc
.
你分配了错误的字节数,sizeof(char)
return你的大小是
一个 char
,所以你只分配了一个字节。这还不够hold
一个字符串。
你应该像这样使用 malloc
:
int *a = malloc(100 * sizeof *a);
if(a == NULL)
{
// error handling
// do not continue
}
使用sizeof *a
优于sizeof(int)
,因为它总是return
正确的字节数。 sizeof(int)
也会这样做,但问题是
这里是人为因素,很容易写错sizeof(*int)
反而。关于这个问题,这里有成千上万的问题。
请注意,char
被定义为具有 1 的大小,这就是为什么当您
为字符串或 char
数组分配内存,人们通常不会写
* sizeof *a
:
char *s = malloc(100);
// instead of
char *s = malloc(100 * sizeof *s);
就好了。但同样,这仅适用于 char
。对于其他类型
您需要使用 sizeof
运算符。
您应该始终检查 malloc
的 return 值,因为如果它 returns
NULL
,您无法访问该内存。
while (fscanf(f, "%c", &s[n]) != EOF)
n++;
例如,如果您分配了 100 个空间,则必须检查您是否没有
达到了极限。否则你会溢出 s
:
char *s = malloc(100);
if(s == NULL)
{
fprintf(stderr, "not enough memory\n");
return 1;
}
int n = 0;
while ((fscanf(f, "%c", &s[n]) != EOF) && n < 100)
n++;
在这种情况下,您没有使用分配的内存来存储字符串,所以它是
很好,它没有 '[=34=]'
终止字节。但是,如果你想
有一个字符串,你需要写一个:
while ((fscanf(f, "%c", &s[n]) != EOF) && n < 99)
n++;
s[n] = '[=14=]';
你也在做这个
free(s);
for (i=0;i<n;i++)
printf("%c",s[i]);
您正在释放内存,然后尝试访问它。你必须做 反过来,访问然后免费。
正确方法:
for (i=0;i<n;i++)
printf("%c",s[i]);
free(s);
编辑
如果你想将整个文件的内容放在一个字符串中,那么你有 2 选项:
- 预先计算文件的长度,然后使用分配正确的 数据量
- 一次读取一个固定大小的字节块,每次都调整内存大小 你读了一个新的块。
第一个很简单,第二个有点复杂,因为
你必须阅读内容,看看你读了多少,调整内存大小
realloc
,检查调整大小是否成功。这是你可以
当你掌握了简单内存管理的知识时再做。
我会告诉你第一个,因为它更容易。函数 fseek
允许您将文件指针前进到文件末尾,使用
函数 ftell
you can get the size of the file and with rewind
倒回文件指针并将其设置为开头:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
if(argc != 2)
{
fprintf(stderr, "usage: %s file\n", argv[0]);
return 0;
}
FILE *fp = fopen(argv[1], "r");
if(fp == NULL)
{
fprintf(stderr, "Could not open %s for reading.\n", argv[1]);
return 1;
}
// calculating the size
// setting file pointer to the end of the file
if(fseek(fp, 0L, SEEK_END) < 0)
{
fprintf(stderr, "Could not set the file pointer to the end\n");
fclose(fp);
return 1;
}
// getting the size
long size = ftell(fp);
if(size < 0)
{
fprintf(stderr, "Could not calculate the size\n");
fclose(fp);
return 1;
}
printf("file size of %s: %ld\n", argv[1], size);
// rewinding the file pointer to the beginning of the file
rewind(fp);
char *s = malloc(size + 1); // +1 for the 0-terminating byte
if(s == NULL)
{
fprintf(stderr, "not enough memory\n");
fclose(fp);
return 1;
}
int n = 0;
// here the check && n < size is not needed
// you allocated enough memory already
while(fscanf(fp, "%c", &s[n]) != EOF)
n++;
s[n] = '[=17=]'; // writing the 0-terminating byte
fclose(fp);
printf("Contents of file %s\n\n", argv[1]);
for(int i=0; i<n; i++)
printf("%c",s[i]);
free(s);
return 0;
}
在 fseek 的帮助下计算文件的大小。
fseek(fp, 0L, SEEK_END); sz = ftell(fp);
然后您可以返回到文件的开头
fseek(fp, 0L, SEEK_SET); 通过 malloc 分配那么多内存。 S= (char*)malloc((sizeof(char)×sz)+1) 现在你可以使用这个内存来复制字节 while lopp