[英]Using statically allocated buffers in getline(3) / getdelim(3)
根据手册, getline()
及其姐妹 function getdelim()
realloc()
缓冲区不够大,无法在分隔符之间进行下一次输入运行,则将重新分配传递给它们的缓冲区。
有什么办法可以防止这种行为? 或者让这些函数与静态分配的缓冲区一起工作,并发出缓冲区满的信号而不是尝试重新分配?
fgets()
适用于 static 缓冲区,但它不支持任意分隔符。
getline()
的 POSIX 规范规定:
ssize_t getline(char **restrict lineptr, size_t *restrict n, FILE *restrict stream);`
…
应用程序应确保
*lineptr
是可以传递给free()
function 的有效参数。 如果*n
不为零,则应用程序应确保*lineptr
指向大小至少为*n
字节的 object,或者是 null 指针。
该要求排除了使用未分配的缓冲区的可能性,就像调用malloc()
或 null 指针一样。
如果你想要一个 function 是getdelim()
(指定行尾字符)和fgets()
的混合体,它不执行 memory (重新)分配,那么你必须自己编写它。
#include <stdio.h>
/* Add this declaration to an appropriate header and include it */
extern char *fgets_delim(char *buffer, int n, int delim, FILE *fp);
char *fgets_delim(char *buffer, int n, int delim, FILE *fp)
{
if (buffer == 0 || fp == 0 || n == 0)
return 0;
char *end = buffer + n - 1;
char *nxt = buffer;
int c;
while (nxt < end && (c = fgetc(fp)) != EOF)
{
*nxt++ = c;
if (c == delim)
break;
}
*nxt = '\0';
if (c == EOF && nxt == buffer)
return 0;
return buffer;
}
#include <string.h>
int main(void)
{
char data[1024];
int fieldnum = 0;
while (fgets_delim(data, sizeof(data), ',', stdin) != 0)
printf("%d (%zu): [[%s]]\n", ++fieldnum, strlen(data), data);
return 0;
}
给定一个自制的随机字符串生成器和一些换行符/空字节,我得到了一些示例 output:
$ random -T '%12:2048l,' -n 3 -z | tr -d '\0' | fgets_delim67
1 (597): [[ohoEDGRxuefdpMLKaYHfFYpzJNVVfLpUMCzyyppKGAQJVdPnWbwvegYuBmdKqIKmZgsscFpLqdNzJFmYeHPbthVrhFlqzkRcWkfPtslhzXaNyGejBhqFzrbydDlMKljGzBSNTfklSjEmLCnOnipaiGrUkvAoIqWPLQIPJNRqfaZcBzYPGjuCdgcGNFnxbCWDTgKkWJZSeCkeuYiTZrPJlzPeQipMhHIdMBCOtZDdzxzLTounfGsEiLzOplcOyskuaHtMiwxlEZJkgkIawpnTjNnICojDwdfBStjfSrFMvcvkcvOukFPuuzXGpCBgbHkhDxnmuphIbCInCiHGFTIcREMCmcxePAHJtwuWMSJYjOlgoGaYFTlSxLvKcUDKBVBgrnqGgRxybiLeyBqRQqrUdJGyVgaUtIRexrigaNZuxcpsyCNvecqwoNTEEVXNLKeMNnTARZzAjIZmdVGyicnlmfwLVnGUtomRPVIzmQBZEtNwJKUwejBGyqdrVZLtIjkKQvIasqIVvZefuATJATNgDfIoouoCIrKqFitlmjvtbmxhIJtlSxQKRcDmBXPrysQrXbpOHrekGHjdeUIzztvu,]]
2 (1023): [[xajwWYzDPMmKxFCQwQychmpJzjHEkHQuvcKmVJpjglnzFOuHkGwyxuYsZWQayjcbRNfdnDoTvqPaTnMUONvKZuaLrFXZjsiuLSFiAJnVTOkgSqVEGSUwCvWlyxFNrTqoAAjqEaxgTMnmcJrPHzMbHATKAOuZcEBNANFbkafqgcgNbzHrVBKnAumanupiEMPKvaedTOQlgTJNcayTwUOCPqIlzxALhkeLdeaFeBIjJeHDzFpfAgatWdFZrpytBvLzkwwMlDZhZIUQADNmxolWhgkpAWkQyjtIrWFHIAQwHdGoCjnyBMfWgfLxNhQQVeKbPMneukjZeKMbhEbVspiYDjuBexyPYXCrWOXKeIUkgebLAWlzJigLbOSVeMrGNRGmhrbtCSpqUqFWxmMhzmiPTwJvfGgXZYWgAmSEDyvsRmfIaLXjypIDBOXAMyJJyuIWadDPqyhHgLhaENmVQzIuHHEaSlWkgwMPrfbPZNTagWHSDdtnzKUYRwPUabaDmXRNtnwfdycnqxnSEYGQOoGjkAAKAmQxethqjJeqQAgFlAMrtEWXjATSpYBbUIKeKvAcNsGBxHFnNevDTcEgLGBgemZuRcAafSxansOHsVBXLcDXvVftGzXLpluAGFMNMLsjZrpUlwNPDlbzRuGepItRHnWOebosqFKUMpwccKUMswBmNQrRNvKXCzFeaCbNMBxcgRRakncJcFqdSVDBqamgPnoahpfhFMuviFJekKjeUKHuhxYFMMRuAJNnvNgbOhLQLmsvGnkhoLofyzjGKEQFjvRAaJTvAOzluCvvRGOEyHgHOeJQFtymfFiuIZiGzKzVlefjHoUUcsRiOIjbQErNEUsdzcZgFaKtJhaQXiWsdDrOsPbKiQQbOKIRwcapKxwtKQvciWPsWHAjmHtjWJPesEZncOjUUVYKWVOvQqrCiwPYAMmbhCLeFTCzQtNAPEMlRFPWOkUoHjZCzBlReCpFxjOYbDDWFcnvraLoLUgVSiJOnorOBEVcTESxbVurVZv]]
3 (955): [[qdEmxjYaxIFmfGKtVXCJBurEoewWsmYDblvyeStbSZnqARPvfswgKLpQcCoIcIBZufoNWEeFRfkMNDIOGoPAlJijDQVqINGiygExpxZMvLAhNQunBvfLdicBcugrCYssiFlszFxQNPTWbTWOIoqfytdDRPKSygRgychwomXITjmRlubjtDzwPoqfhISHtnFYahXbwmBMCMuZaCmFVzCeVYLIvGrNyadekjdnYbhMoDADLZUaAabuIKnJJrvVLPsiHvfgWgacmEOREofejNfXKymcHumJMUxmiHPJBMPMunOQDYXAmaBtysTgEryzVoIQfLXVWkMGHGetRXwCqxNVCJOkfxYnjlhJpBaKxyJDXwGcaQQVzNmvgxTDJRSaVPeofFVznsWQJQnaLmDdAgHlUXnMZjNXqZOOtslaNVpXULZYivRMrBqAYFtBgPiMlVpyvVGPeAECRjzpaFxURgOvrTpfDqmdkwmdJDVIFcBwmkrRcExUGdqIqxgcdNFsdbXnMUcazWiXcxxfxxiihLMbwzDsinBbOdPiRtTebexyRJqgNZOZWmgjvmPnNYkMJfWfINUevNDhHTmJmGESetNAEDlqlRwdmVngVTInXArTDhGpkcyUQWdltVKcJClqXtKZUpoIROpqLsirIdtWwjRtmlIXIjZTUcGSVrykyHZyTBZfPvOEjhmxHnGdchIvqJUyRVLfgvUXHSYbaMkUHKpDxPFVwUmPdsNYqQgLsjubmIGNDxUkZBfoAvXXENrVSJukpOkSJhHtQVuwSSmuMZAizWjxxDmdvyAMbYvpUhtwoDHKudGvqRxWYFbRuIToHCruApJaSTAFOGNjrpSlpPUmRVFyIrpstdVswhGtQfPeMVcwIQgWsYtfPdRapRiHuTESuTNkgSpuwIXuXrCzQjecvnQXrSDGVvQzRNtOIyPGeMMDYhdvceJLXrNZmx,]]
4 (1023): [[qqMsddOBIyGfxGJJtzBlgqmAvbDByPBKkAcDcfOEymotMazQrnbZwIWEVaIUJeKXuojiCFwRCZudbXYUEfYIzedcseKyigRYbwSfeBIRzxYlyxjkdeOQVPEvskMmWzRDQcLYDbQIESzjNLlwaUIkvPhedEaRMvgzllmnmXrVjoKMALaxjkcOFBoTMpNvilxHveqBWFjNRwhGGqLezwoLrRNKZmZiSavMXuLkfiIDFdHvYVXSlplAbWDoGgBCyGfZvowjkqdHSJHcoLJMHQdVPSSgndhkOgIpxAFqaCSGscIslETMphYpwLLovcasKpanfezDdHwOZRxwHpUOKPbGgEYDsZdkjNjVrqchhUzkyhodgHJdIPbPiivFFOYDghifRaxaWBiTYlUSFQBWUjwMrWCgZROzoNnMispMIIxsGWNCtESlCpoQosCnuFfxaAKDeaLJULLJQARSgPqdQFtaxqAcmFqgighSlFjlqnqOGZFHoOiivqhupIvTvCdSJLoLYEmAOlkVQcOJAXSApsUsQiWkbRIUwKjdHCUvhJWVfthBCpLJjpZjsrhmMfeiLSbBVNVREaxpYBggZfmxpGarTPgSLtLKbYqRGsVdCyokEuzDEJgbWPfcxBpqlaHPxEDeGAkPjjDjAVLxygZHlUnOhATDZsNTsjHGgvvazNAMzHIvQjaLOXKSfyPiYowOLCnSjqbDbcEaPAHxDmdtvJsUpSZDdqZdIJwvAeFKdKoURpblvjOGWplGgVbwiIGFOLRyCfUfzNyutyleXGnKSufsOjcfeQsjEBpwNHGckguAQGZqiREoiWWSIRnXbhovHlgBmtnbfbpmprrZUgUPkCHTrDxlLZMIbsDhIEvwMsDjNKOWLXCArKJfFtpBiNfqvkhMoxiOqfJiNdYzXsDPZkUQgPHQgEkYrybGxcdYGwBJvDOpUmojqMeSgdvheQxckjusongcneDhXbXRiYrGlGiqOLJOdlIrBhPYDGrcBtuWutRaxJHtgwMGzjslWdzSVww]]
5 (1022): [[PbcosXvfycCaCmhcoallrXOYztMJNbtBfOqpfwYiVTYUyYiIHmqOmhEXqCtNDGNHzdGLeMFVWKwfjiyapGMtnYUpGyZHpwASQuPzLSzJcBHbQawREpvQBbBCXODNcaxogJHhCPpBkyZWkWWNtOKYAPBfexOZAIEbaWTcOXXDLRkxXCoEOUTTeiXbKVAdOeCPXanPtgybCReHmHkptZbcHlWbmdfWmoARiQomffyKbyjePFUaLNJNuzSYFFvyKhmvvEaxnJZjMeDZyNirCBbswsPGtoClFiLSlDFomGSIWbveYmETmfNHjVdWKLwywcKThWUXQKsvjTVCrKNaXkCxxlcwCPcpopcNyYEnuSBKwaPPyIHScmmUaIglXNBbDKYBYBMMMvJzuHknxEYGiOxkLTVkvaTGWURgWNGxQsGJncoZSHFaFyecfQBKrsCzqMkGwcUOiRZcKAfnTohWoumyJwmxFjNmcOmpPsvPnywCzrkhzmzBhiSnykfYlZBRuCmSqIaIwcMIdxxRvKBsaoYbyGdlfQwJTYRzlVdHRbYRPsNkfIKMalJNmuSOVepiiAihHTibVvAbrzPQwwaHoSBPsyzgcqscKBDupKpOYuWyDUPwHyKrqENLldJGFnttYuxNMsqgjsetGvqYMsnONSZnxmGDJVCqtKKIwFWJLNMWDiTHqZrQHkLqPEPLwTXlQmeDGgSNvkGndAXVPTVabVpfHEenGNXZZmpYMXEasEZDLryBWVnqnfDfZSbcSOpxjkdCLevtforvEOSheclrDpjqXhtfpvSYWaNgUCOsawcgfoDsutwBoNFwQqFQlsrqjQhKKDfyUsaemibkUoJYsUxiPbUdNwACjUJAedcnUVZFowsWEYlYyLUvVrbgKQxoYBQaGvSlOlltBjjtmanqBuoQVYRBCnlTKRYPrABztbIvSgsHumyxQCKXqMrNsJHcpvzMqbXryIzYfPUqYOEerWWYluGPdzyymlkPYcKyLFhFoWFZcrXTSRpYDKzyAFNKx,]]
$
请注意,条目 2 读取了 1023 个字节,但没有以逗号(指定的分隔符)结尾; 条目 3 用 955 个字节完成了输入。 类似地,条目 4 读取了 1023 个字节而没有找到逗号,条目 5 又读取了 1022 个以逗号结尾的字节。 这与您在fgets()
和换行符之间看到的长线完全相同。
修改 function 以将字符串而不是单个字符作为分隔符 ( const char *delim
) 并修改if (c == delim)
测试以读取if (strchr(delim, c) != 0)
. 当然,您需要在 function 之前包含<string.h>
。 这将允许您将逗号或换行符指定为字段分隔符,这可能更有用。
另一个有用的替代方法是从getline()
/ getdelim()
书中取出一片叶子并返回读取的数据的长度,以便可以管理嵌入的 null 字节。 我不清楚为什么getline()
和getdelim()
返回-1
而不是EOF
(即使两者通常相同)。 如果我返回长度,我会返回EOF
而不是-1
作为指示符。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.