stdin opakowanie getline

Nov 02 2020

Chciałbym przeczytać wiersz ze standardowego wejścia, z wyłączeniem znaku nowego wiersza. Napisałem funkcję:

/* read in a line from stdin, NULL on failure
 * does not include trailing newline
 */
char*
readStdinLine() {
        char* buffer;
        size_t bufsize = 32;
        size_t characters;

        buffer = (char *) malloc(bufsize * sizeof(char));
        if (buffer == NULL)
                return NULL;

        characters = getline(&buffer, &bufsize, stdin);
        buffer[--characters] = '\0';

        char* text = (char *) malloc(characters);
        for (int i = 0; i < characters + 1; i++) {
                text[i] = buffer[i];
        }

        free(buffer);

        return text;
}

Wydaje się to nieefektywne, zasadniczo czytam ten wiersz dwa razy, raz w getline i raz, aby usunąć końcową nową linię. To nie wydaje się być najbardziej wydajnym algorytmem pamięci i chciałbym usunąć znak nowej linii bez kopiowania, jeśli to w ogóle możliwe.

Jestem bardzo nowy w C (używałem C ++, Javy itp., Ale nigdy nie jest to język systemowy bez obiektów), więc byłbym wdzięczny za nauczenie się wszystkich rzeczy związanych ze stylem kodu, które zrobiłem źle. Dzięki!

Odpowiedzi

7 MartinYork Nov 02 2020 at 01:17

Tę funkcję można zapisać w następujący sposób:

char* readStdinLine()
{
        char*  buffer  = NULL;
        size_t bufsize = 0;
        ssize_t characters = getline(&buffer, &bufsize, stdin);
        if (characters == -1) {
            free(buffer);
            buffer = NULL;
        }
        else if (buffer[characters-1] == '\n') {
            buffer[characters-1] = '\0';
        }
        return buffer;
}

Ta getline()funkcja robi wszystko, czego potrzebujesz. Wystarczy sprawdzić błędy i usunąć znak nowego wiersza)