
上QQ阅读APP看书,第一时间看更新
2.5.4 动态分配函数
ISO/IEC TR 24731-2描述了来自POSIX的getline()函数。getline()函数的行为与fgets()类似,但提供了一些额外的功能。首先,如果输入行过长,那么该函数使用realloc()调整缓冲区的大小,而不是截断输入。其次,如果它执行成功,则返回读取的字符数,这对于确定在输入的换行符之前是否有任何空字符是非常有用的。getline()函数仅适用于使用malloc()分配的缓冲区。如果传入一个空指针,则函数getline()会分配一个大小足够容纳输入的缓冲区。因此,随后用户必须明确地用free()释放该缓冲区。当分隔符等于换行符时,getline()函数相当于getdelim()函数(getdelim()函数也在ISO/IEC TR 24731-2中定义)。例2.12中所示的程序片段使用getline()函数从stdin中读取一行文本。
例2.12 使用函数getline()从stdin中读入
01 int ch; 02 char *p; 03 size_t buffer_size = 10; 04 char *buffer = malloc(buffer_size); 05 ssize_t size; 06 07 if ((size = getline(&buffer, &buffer_size, stdin)) == -1) { 08 /* 处理错误 */ 09 } else { 10 p = strchr(buffer, '\n'); 11 if (p) { 12 *p = '\0'; 13 } else { 14 /* 未找到换行符, 刷新标准输入至行尾 */ 15 while (((ch = getchar()) != '\n') 16 && !feof(stdin) 17 && !ferror(stdin) 18 ); 19 } 20 } 21 22 /* ... 对缓冲区进行处理 ... */ 23 24 free(buffer);
getline()函数返回写入缓冲区的字符数目,包括换行符,如果在文件结束前遇到它。如果发生读取错误,流中的错误标记就被设置,函数getline()返回–1。因此,此函数的设计违反《C安全编码标准》[Seacord 2008],“ERR 02-C.避免带内错误标志”,因为ssize_t类型是以提供带内错误标志为目的而被创建的。
注意,此代码也没有检查malloc()是否执行成功。然而,如果malloc()失败,它返回NULL,这被传递给getline()函数,getline()函数将及时地分配它自己的一个缓冲区。
表2.4总结了本节中描述的gets()的一些替代函数。所有这些函数都可以安全地使用。
表2.4 gets()的替代函数