您试图从文件中读取的内容并不简单,但可以通过设置一个标志来处理,该标志告诉您是否已经看到
'a'
或
'b'
,跳过所有空白和
':'
字符,将所有其他字符存储在缓冲区中,根据需要重新分配,然后在第二个
“A”
或
“B”
找到了,把那个角色放回
FILE*
流与
ungetc
,nul终止并返回缓冲区。
听起来很简单——对吧?好吧,差不多了。让我们看看你需要什么
readword()
功能。
首先,因为你分配给
buffer
在里面
Read Word()
,不需要通过
char **buffer
作为参数。你已经声明了
readword
作为
char *readword(...)
所以只要通过
文件*
将指针作为参数,并返回指向
NUL终止
缓冲器。
您可以按自己喜欢的任何方式处理重新分配方案,可以从分配的合理字符数开始,然后将当前大小加倍(或添加一些倍数),或者每次用完时添加一个固定的数量。下面的示例只是从一个32个字符的缓冲区开始,然后在每次需要重新分配时再添加32个字符。(如果数据大小真的未知,我可能会从32个字符开始,然后每次用完都加倍——完全取决于您)。
使用
isspace()
函数位于
ctype.h
确保正确处理所有空白。
最后几个问题只是确保您返回
NUL终止
缓冲区中的字符串,并确保在以下情况下重新初始化指向每个新内存块中缓冲区结尾的指针
realloc
被称为。
总而言之,你可以做一些类似的事情。在
Read Word()
函数读取示例文件并输出从文件中读取的组合字符串,
#include
#include
#include
#define NCHR 32
char *readword (FILE *fp)
{
int c, /* current character */
firstline = 0; /* flag for 'a' or 'b' found at 1st char */
size_t n = 0, nchr = NCHR; /* chars read, number of chars allocated */
char *buffer = NULL, *p; /* buffer to fill, pointer to buffer */
buffer = malloc (nchr); /* allocate initial NCHR */
if (!buffer) { /* validate */
perror ("malloc-buffer");
return NULL;
}
p = buffer; /* set pointer to buffer */
while ((c = fgetc (fp)) != EOF) { /* read each char */
if (isspace (c) || c == ':') /* skip all whitespace and ':' */
continue;
if (c == 'a' || c == 'b') { /* begins with 'a' or 'b' */
if (firstline) { /* already had a/b line */
ungetc (c, fp); /* put the char back */
*p = 0; /* nul-terminate */
return buffer; /* return filled buffer */
}
firstline = 1; /* set firstline flag */
continue;
}
else {
if (n == nchr - 2) { /* check if realloc needed */
void *tmp = realloc (buffer, nchr + NCHR);
if (!tmp) /* validate */
exit (EXIT_FAILURE);
buffer = tmp; /* assign new block to buffer */
p = buffer + n; /* set p at buffer end */
nchr += NCHR; /* update no. chars allocated */
}
*p++ = c; /* assign the current char and advance p */
n++; /* increment your character count */
}
}
*p = 0; /* nul-terminate */
return buffer;
}
int main (int argc, char **argv) {
char buf[NCHR], *word;
int nwords, toggle = 0;
/* use filename provided as 1st argument (stdin by default) */
FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin;
if (!fp) { /* validate file open for reading */
perror ("file open failed");
return 1;
}
if (!fgets (buf, NCHR, fp)) {
fputs ("error: read of line 1 failed.\n", stderr);
return 1;
}
if (sscanf (buf, "%d", &nwords) != 1) {
fputs ("error: invalid file format.\n", stderr);
return 1;
}
nwords *= 2; /* actual number of words is twice the number of pairs */
while (nwords-- && (word = readword (fp))) {
printf ("%c: %s\n", toggle ? 'b' : 'a', word);
free (word);
if (toggle) {
putchar ('\n');
toggle = 0;
}
else
toggle = 1;
}
if (fp != stdin) fclose (fp); /* close file if not stdin */
return 0;
}
(
音符:
在上面
toggle
仅仅是一个
1
或
0
用于输出的标志
"a:"
或
"b:"
在适当行的开头添加
'\n'
两行之间。)
示例使用/输出
$ ./bin/read_multiline_pairs dat/pairsbinline.txt
a: 010101000001010111110100101010000000111100000000000011110000
b: 0000011111000001000110101010100111110001
a: 0000001111111111110000111111111111000
b: 00000001111001010101
内存使用/错误检查
在动态分配存储空间时,请始终验证内存使用情况,并确保已释放所有分配的内存。
$ valgrind ./bin/read_multiline_pairs dat/pairsbinline.txt
==14257== Memcheck, a memory error detector
==14257== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==14257== Using Valgrind-3.12.0 and LibVEX; rerun with -h for copyright info
==14257== Command: ./bin/read_multiline_pairs dat/pairsbinline.txt
==14257==
a: 010101000001010111110100101010000000111100000000000011110000
b: 0000011111000001000110101010100111110001
a: 0000001111111111110000111111111111000
b: 00000001111001010101
==14257==
==14257== HEAP SUMMARY:
==14257== in use at exit: 0 bytes in 0 blocks
==14257== total heap usage: 8 allocs, 8 frees, 872 bytes allocated
==14257==
==14257== All heap blocks were freed -- no leaks are possible
==14257==
==14257== For counts of detected and suppressed errors, rerun with: -v
==14257== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
仔细看一下,如果有问题请告诉我。问题的最大部分是处理每对的所有行的读取和连接。剩下的代码就留给你了。