C: fscanf a charakter / velikost string

hlasů
0

Jsem analýze textový soubor (CSS) pomocí fscanf. Základním cílem je jednoduchý; Chci se vytáhnout něco, který odpovídá tomuto vzoru:

@import some / file / somewhere.css;

Takže jsem pomocí fscanf, to říká přečíst a odhodit všechno až na znak ‚@‘ a uložit vše, až se dosáhne ‚;‘ charakter. Zde je funkce, která dělá toto:

char* readDelimitedSectionAsChar(FILE *file)
{
char buffer[4096];

int charsRead;
do
{
    fscanf(file, %*[^@] %[^;], buffer, &charsRead);

} while(charsRead == 4095);

char *ptr = buffer;
return ptr;
}

Vytvořil jsem vyrovnávací paměť, která by měla být schopna pojmout 4095 znaků, jak jsem pochopil. Nicméně jsem zjistil, že to není tento případ. Když budu mít soubor, který obsahuje odpovídající řetězec, který je dlouhý, jako je tento:

@import some / opravdu / opravdu / opravdu / long / souboru / cesta / k / a / file;

To dostane zkrácena na 31 znaků pomocí vyrovnávací paměti char [4096]. (Pokud jsem použít printf kontrolovat hodnotu vyrovnávací paměti, jsem zjistil, že řetězec je zkrácena.)

Mám-li zvýšit velikost vyrovnávací paměti, větší část řetězce je v ceně. Byl jsem pod dojmem, že jeden znak zabere jeden bajt (i když jsem si vědom, je to ovlivněno kódování). Snažím se pochopit, co se tady děje.

V ideálním případě bych rád, aby bylo možné nastavit vyrovnávací paměti tak velký, jak to musí být „on the fly“ --- to znamená, že mají fscanf stačí vytvořit vyrovnávací paměť dostatečně velký pro uložení řetězce. Toho lze dosáhnout? (Já vím, o% jako příznak pro GNU, ale jedná se o aplikace Mac OS 10.5 / 10.6 a já nejsem jistý, jestli to bude fungovat na této platformě.)

Položena 25/09/2010 v 01:09
zdroj uživatelem
V jiných jazycích...                            


2 odpovědí

hlasů
2

Hlavním problémem je, že máte budete vracet ukazatel na lokální vyrovnávací paměti v zásobníku, který je visící (a tedy přepsány další hovor uděláte). Máte také potenciální přetečení vyrovnávací paměti. Zmínil jste se ‚a‘ volba, která by pomohla hodně, ale jeho bohužel rozšíření GNU, který není obecně k dispozici.

Za druhé, máte tento další možnost scanf, &charsReadkterá nikdy nebude písemnou jako neexistuje %pro něj ve formátu řetězce. Takže charsRead bude vždy náhodně odpadky - což znamená, že smyčka (pravděpodobně) stačí spustit jednou, nebo (zřídka) loop navždy. Zkuste něco podobného

char* readDelimitedSectionAsChar(FILE *file)
{
    char buffer[4096], term[2] = "", *rv = 0;
    int len = 0;

    fscanf(file, "%*[^@]");
    while (term[0] != ';' && !feof(file)) {
        if (fscanf(file, "%4095[^;]%1[;]", buffer, term) > 0) {
            int read = strlen(buffer);
            rv = rv ? realloc(rv, len+read+1) : malloc(read+1);
            strcpy(rv+len, buffer);
            len += read;
        }
    }
    return rv;
}

To je stále rozdělen v tom, že se bude zlobit, pokud vám dojdou paměti (což se může snadno stát, pokud to obrovská chybně soubor s @ na začátku krmení a ne),

Odpovězeno 25/09/2010 v 02:47
zdroj uživatelem

hlasů
1

Vaše paměť je lokální vzhledem k funkci. Přiřadit ukazatel na něj, ale když volající přistupuje ukazatel, vyrovnávací paměť již neexistuje. Může se stát cokoliv.

Takže, nedělejte to.

A scanfasi není ten správný nástroj pro práci. Já bych zkusit getc, nebo fgetsmísto.

char *readDelimitedSectionAsChar(char *buf, size_t n, char firstChar, char lastChar, FILE *f);
Odpovězeno 25/09/2010 v 01:21
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more