bufring ved passering input fra standard inngang til en funksjon

stemmer
0

Jeg spurte om dette i går , men jeg har fremdeles problemer. Jeg skrev et program i C som har en funksjon som behandler filer som kan overføres til det ved en fil pekeren.

void process_my_file(FILE *fptr, ...) {
    /* do work */
}

Jeg spurte hvordan å lese innspill fra standard input og gi det til min funksjon, og det ble anbefalt til meg at jeg prøver å kalle funksjonen med standard inn som argument:

my_process_file(stdin, ...);

Dette fungerer, men det jeg virkelig ønsker å gjøre er å lese fra stdin til er oppstått EOF, og før alle innspill på en gang til funksjonen . Problemet med bare passerer standard inn som argumentet er at hver gang brukeren skriver inn en linje av input og presser enter i programmet spytter ut en tilsvarende linje av produksjonen for tidlig.

Jeg hadde håpet på en ren atskillelse av inngang og utgang, slik at produksjonen bare kommer ut etter at brukeren har nevnte EOF (Kontroll-d).

Takk igjen på forhånd. Jeg er en nybegynner å lære å programmere, og dine tips er en stor hjelp. Jeg setter pris på dette nettstedet.

- Larry

Publisert på 27/09/2009 klokken 22:52
kilden bruker
På andre språk...                            


3 svar

stemmer
0

Du må gjøre pre-bufring selv, dvs. lese stdin til EOF er sett og deretter sende en lang streng (sannsynligvis constisting av \ n-separerte linjer) til funksjonen. Eller pre-buffer lese rutine kunne tildele en rekke char * 's som peker til tildelte linjer. Eller pre-buffer rutine ville analysere stdin og returnere preprocessed info. Avhenger av hva du vil gjøre med informasjonen.

Svarte 27/09/2009 kl. 22:59
kilden bruker

stemmer
0

Det du har nå er en ' filter '. Filtre er fantastiske programmer, men selvsagt ikke gjelder for alle situasjoner. Uansett, se om du kan holde programmet fungerer som et filter.

Hvis du virkelig må lese alle innspill før behandling, må du lagre inngangs et sted, og det gir ingen mening å kalle behandlingen funksjon med FILE*(alle dataene i filen * har allerede blitt lest); Du kan lese alle innspill til en char array og passere denne matrisen til funksjonen.

void process_data(char data[], size_t data_len) { /* do work */ }
Svarte 27/09/2009 kl. 23:08
kilden bruker

stemmer
0

Tenk deg at du var å åpne en fil og deretter sende filen håndtaket til funksjonen. Koden i funksjonen ville fortsatt å lese til EOF på at vanlig fil. Videre vil det ha å forholde seg til tildeling nok plass til å lagre filen, og håndtere kort leser.

Alt dette er bare de samme problemer som du må håndtere for stdin - den eneste mulige forskjellen er at stdin kommer fra en terminal vil gi deg kort leser for hver linje av input, mens hver leste fra et rør vil gi deg en kort lese for størrelsen på røret buffer (eller atom skriver mindre enn bufferstørrelse), og en vanlig fil på harddisken vil bare vanligvis gi deg en kort leser på den siste blokken på en fil. Siden funksjonen ikke kan fortelle på forhånd hvor mye plass du trenger (absolutt ikke for røret eller terminal innganger), må du være forberedt på å håndtere dynamisk minne allokering - malloc()og realloc().

Også, hvis funksjon forventer å få data allerede lest om det, hvorfor det blir vedtatt en fil håndtak (FIL pekeren) og ikke et tegn buffer og dens lengde? Du passerer en fil håndtak til en funksjon når du trenger den funksjonen til å bruke det - å lese fra en lesbar håndtak, eller å skrive til en skrivbar håndtak (og bare av og til, både når håndtaket er åpen for lesing og skriving).


Her er en fungerende eksempel program. Jeg måtte jobbe ut noe som er nødvendig for å slurp hele filen inn i minnet, behandle den, og spy ut noen svar - så jeg har valgt å sortere filen ved tegn. Moderat meningsløst, men det viser hva du skal gjøre. Den har også en operasjonell variabel argumenter feilrapportering funksjon i den.

Ha det gøy!

/*
 * Demo code for StackOverflow question 1484693
 */

#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <errno.h>
#include <string.h>

static char *arg0;

static void error(const char *fmt, ...)
{
    va_list args;
    int errnum = errno;  /* Catch errno before it changes */

    fprintf(stderr, "%s: ", arg0);
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);
    if (errnum != 0)
        fprintf(stderr, " (%d: %s)", errnum, strerror(errnum));
    fputc('\n', stderr);
    exit(1);
}

static int char_compare(const void *v1, const void *v2)
{
    char c1 = *(const char *)v1;
    char c2 = *(const char *)v2;
    if (c1 < c2)
        return -1;
    else if (c1 > c2)
        return +1;
    else
        return 0;
}

static void process_my_file(FILE *fp)
{
    char   *buffer;
    size_t  buflen = 1024;
    size_t  in_use = 0;
    ssize_t nbytes;

    if ((buffer = malloc(buflen)) == 0)
        error("out of memory - malloc()");

    while ((nbytes = fread(buffer + in_use, sizeof(char), buflen - in_use, fp)) > 0)
    {
        if (nbytes < 0)
            error("error from fread()");
        in_use += nbytes;
        if (in_use >= buflen)
        {
            char *newbuf;
            buflen += 1024;
            if ((newbuf = realloc(buffer, buflen)) == 0)
                error("out of memory - realloc()");
            buffer = newbuf;
        }
    }

    /* Consistency - number/size vs size/number! */
    qsort(buffer, in_use, sizeof(char), char_compare);
    fwrite(buffer, sizeof(char), in_use, stdout);
    putchar('\n');

    free(buffer);
}

int main(int argc, char **argv)
{
    arg0 = argv[0];

    if (argc > 1)
    {
        for (int i = 1; i < argc; i++)
        {
            FILE *fp;
            if ((fp = fopen(argv[i], "r")) == 0)
                error("failed to open file %s", argv[i]);
            process_my_file(fp);
            fclose(fp);
        }
    }
    else
        process_my_file(stdin);
    return(0);
}

Du kan kalle dette med ett eller flere filnavn som argumenter; hvert filnavn er sortert separat. Du kan pipe noe inn i den; du kan la den lese fra standard input. Jeg velger å se bort fra muligheten for at fwrite()og fclose()kan mislykkes; Jeg velger også å se bort fra muligheten for overløp på bufleni process_my_file(). Du kan sjekke dem hvis du velger. (Legg merke til at utgangssignalet for hver fil inneholder en mer linjeskift enn inngangs gjør.)

Øvelser for leseren:

  • Skriv ut ikke-utskrivbare tegn som '' \ xXX`' escape-sekvenser.
  • Bryt utgangs inn linjer på ikke mer enn 64 tegn hver.
  • Utarbeide eller forskning alternative tildelings strategier, for eksempel å doble plass på hver tildeling (se ' The Practice of Programming ')
Svarte 27/09/2009 kl. 23:08
kilden bruker

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