簡體   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