我正在处理我希望在处理它们时读入缓冲区的小文本文件,所以我想出了以下代码:
...
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
...
Run Code Online (Sandbox Code Playgroud)
这是将文件内容放入缓冲区还是滥用的正确方法strcat()?
然后我遍历缓冲区:
for(int x = 0; (c = source[x]) != '\0'; x++)
{
//Process chars
}
Run Code Online (Sandbox Code Playgroud)
Mic*_*ael 70
char source[1000000];
FILE *fp = fopen("TheFile.txt", "r");
if(fp != NULL)
{
while((symbol = getc(fp)) != EOF)
{
strcat(source, &symbol);
}
fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)
这段代码有很多问题:
sizeof(source),则容易发生缓冲区溢出.该
strcat()函数将以null结尾的字符串s2的副本附加到以null结尾的字符串s1的末尾,然后添加一个终止的"\ 0".
您正在将字符(不是以NUL结尾的字符串!)附加到可能或可能不是NUL终止的字符串.的唯一一次我能想象这个根据手册页描述的工作是,如果该文件中的每个字符是NULL结尾的,在这种情况下,这将是毫无意义.所以,是的,这绝对是一种可怕的滥用strcat().
以下是考虑使用的两种替代方案.
如果您提前知道最大缓冲区大小:
#include <stdio.h>
#define MAXBUFLEN 1000000
char source[MAXBUFLEN + 1];
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
size_t newLen = fread(source, sizeof(char), MAXBUFLEN, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
fclose(fp);
}
Run Code Online (Sandbox Code Playgroud)
或者,如果您不这样做:
#include <stdio.h>
#include <stdlib.h>
char *source = NULL;
FILE *fp = fopen("foo.txt", "r");
if (fp != NULL) {
/* Go to the end of the file. */
if (fseek(fp, 0L, SEEK_END) == 0) {
/* Get the size of the file. */
long bufsize = ftell(fp);
if (bufsize == -1) { /* Error */ }
/* Allocate our buffer to that size. */
source = malloc(sizeof(char) * (bufsize + 1));
/* Go back to the start of the file. */
if (fseek(fp, 0L, SEEK_SET) != 0) { /* Error */ }
/* Read the entire file into memory. */
size_t newLen = fread(source, sizeof(char), bufsize, fp);
if ( ferror( fp ) != 0 ) {
fputs("Error reading file", stderr);
} else {
source[newLen++] = '\0'; /* Just to be safe. */
}
}
fclose(fp);
}
free(source); /* Don't forget to call free() later! */
Run Code Online (Sandbox Code Playgroud)
如果您使用的是 Linux 系统,一旦获得文件描述符,您就可以使用 fstat() 获取有关该文件的大量信息
http://linux.die.net/man/2/stat
所以你可能有
#include <unistd.h>
void main()
{
struct stat stat;
int fd;
//get file descriptor
fstat(fd, &stat);
//the size of the file is now in stat.st_size
}
Run Code Online (Sandbox Code Playgroud)
这可以避免查找文件的开头和结尾。
是的-您可能会因对strcat的严重滥用而被捕!
看一下getline(),它一次读取一行数据,但重要的是它可以限制读取的字符数,因此不会溢出缓冲区。
Strcat相对较慢,因为它每次插入字符时都必须搜索整个字符串的结尾。通常,您将保留一个指向字符串存储区当前结尾的指针,并将其传递给getline作为读取下一行的位置。