当您想读取行并将其追加到固定缓冲区时,您需要跟踪缓冲区中的位置以追加新字符,然后每次添加后可用的字符数。当您从输入流中读取行时,您不会以while (!feof (file)) 为条件读取循环。 (见:Why is while ( !feof (file) ) always wrong?)
相反,您可以根据正在使用的输入函数的返回来调节读取循环,或者不断循环,检查输入函数的返回当你的输入函数返回EOF(或者你没有处理的读取错误发生)时你打破循环
对于 256 字符缓冲区的情况,您可以简单地声明 256 字符数组进行存储,然后声明一个指向数组开头的指针,您将使用该指针在缓冲区中写入新字符,推进指针把那些写完,为下一次阅读做准备。读取要添加的字符时,您最多只能读取缓冲区中未使用的可用字符数。无论您是使用strcpy/strcat 还是只是在指针位置将字符读入缓冲区都无关紧要——跟踪剩余的可用字符是相同的。
在计算剩余可用字符数时唯一需要注意的是,您必须为 nul-terminating 字符保留存储空间。您只需要一个用于在缓冲区中构建的字符串,因此它会与您添加到缓冲区的第一个字符串一起添加。
连接字符串时,您还需要考虑如何处理输入文件中的空白(空)行。由于它们不会添加到您要加入的字符串中,您可以直接跳到下一行 - 除非您想将它们保留在缓冲区中。
当使用fgets() 或POSIX getline() 等面向行的读取函数时,您还必须处理'\n' 读取并包含在每次读取中。在连接字符串时处理包含的'\n' 的简单方法是用' '(空格)字符覆盖它,以便在缓冲区中的相邻字符串之间提供一个空格。
最后要考虑的是在退出读取循环时从缓冲区末尾删除最后的' '(空格)。 (用' ' 覆盖'\n' 产生的结果)。只需递减您正在使用的指针,并用 nul-terminating 字符覆盖最后的 ' '。
总而言之,你可以做类似的事情:
#include <stdio.h>
#include <string.h>
#define MAXC 256 /* if you need a constant, #define one (or more) */
int main (void) {
char buf[MAXC], *p = buf; /* buffer and pointer to buffer */
size_t avail = MAXC; /* character avaialble in buffer */
while (fgets (p, avail, stdin)) { /* read up to avail characters */
size_t len = strlen(p); /* get length read */
if (*p == '\n') /* ignore blank lines in input */
continue;
if (len && p[len-1] == '\n') /* overwrite \n with space */
p[len-1] = ' ';
p += len; /* advance len chars in buf */
/* subtract len chars from avail (len + 1 chars 1st iteration) */
avail -= (avail == MAXC) ? len + 1 : len;
}
if (*--p == ' ') /* backup over space at end and nul-terminate */
*p = 0;
puts (buf); /* output combined string */
}
(注意:处理前导空格、多个中间空格或尾随空格留给您)
输入文件示例
$ cat dat/cake.txt
Hi there how are you
do you like cake
I love cake
或有空行的文件:
$ cat dat/cakedbl.txt
Hi there how are you
do you like cake
I love cake
使用/输出示例
附加文件中的所有行,由空格分隔,最多为 MAXC - 1 个字符(为 nul-termianting 字符留出空间)。
$ ./bin/appendstr < dat/cake.txt
Hi there how are you do you like cake I love cake
双倍行距文件。
$ ./bin/appendstr < dat/cakedbl.txt
Hi there how are you do you like cake I love cake
查看一下,如果您还有其他问题,请告诉我。使用strcpy 和strcat 重写程序以连接字符串。 (您会发现使用单个缓冲区时它基本上是一种洗涤)。您可以使用 strcpy/strcat 方法使用单独的缓冲区进行读取和追加以简化操作,但剩余可用字符的计算基本相同。