[英]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.