繁体   English   中英

在 getline(3) / getdelim(3) 中使用静态分配的缓冲区

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

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM