Массив символов динамической длины C

Я хотел написать программу на C, которая будет принимать строку любой длины из stdin и отображать ее или применять любую функцию к этой строке. Чтобы это работало, мне понадобится строка (char []) с динамической длиной.

Вот как я это сделал:

#include <stdio.h>
#include <unistd.h> 
#include <stdlib.h>
#include <string.h>

int main(int argc, char **argv){


    char *line;
    line = malloc(10);
    line[0] = '\0';

    char *str = malloc(10);

    fprintf(stdout, "Please enter your line:\n");

    while(fgets(str, 10, stdin)){

        //check for line break
        if (str[strlen(str)-1] == '\n'){
            str[strlen(str) - 1] = '\0';
            strcat(line, str);
            break;
        }

        strcat(line, str);

        line = realloc(line, strlen(line) + 10);
        str = realloc(str, strlen(str) + 10);
    }

    fprintf(stderr, "you entered %s\n", line);

    //just for testing
    /*
    fprintf(stderr, "\n str= %s \n", str );
    fprintf(stderr, "\n line= %s \n", line);
    */

    free(line);
    free(str);
    exit(EXIT_SUCCESS);
}

Однако это выглядит ужасно. Мне нужно два массива символов. В char *str я буду записывать ввод со стандартного ввода и объединять его с char *line. str будет содержать только до 10 байтов символов, и поэтому мне нужно объединить все в line.

Есть ли более чистый способ сохранить вывод из stdin в этом случае и применить к нему какую-то функцию? Я делаю это неправильно? Можно ли обойтись без malloc и realloc?

Вам не нужно realloc(str), вы никогда не читаете более 10 байт за раз, вы можете просто определить str как char str[10].

yyny 07.04.2019 23:54

И затем вы создали довольно типичную функцию C. Обычно вы делаете str степенью двойки, например 1024, или BUFSIZE, потому что ЦП такой.

yyny 07.04.2019 23:56

"примет строку любой длины из стандартного ввода" --> как насчет чего-то более устойчивого к хакерским атакам, например, "примет строку любой длины из стандартного ввода до 1 Мбайта"?

chux - Reinstate Monica 08.04.2019 00:01

@chux Реализация библиотеки C и / или ядро ​​уже справятся с этим за вас. Если кто-то попытается ввести очень длинную строку, процесс будет остановлен из-за ошибки нехватки памяти (realloc вернет NULL).

yyny 08.04.2019 00:03

Ничего ужасного в этом нет. В C вы должны управлять своей собственной памятью. Если вы не знаете, сколько вам нужно до времени выполнения, вам придется динамически распределять его, как есть. Вы также должны проверить возвращаемые значения malloc и realloc на случай, если они не сработают.

yano 08.04.2019 00:04

@YoYoYonnY Эксплойт, которого следует избегать, — это переполнение ресурсов, включая ресурсы памяти. Ждать NULL на *alloc() уже поздно.

chux - Reinstate Monica 08.04.2019 00:14

@chux Определенно не верно для Linux, и я не эксперт по другим ядрам, но я полагаю, что они убьют процесс, бесполезно потребляющий ресурсы, как это делает Linux.

yyny 08.04.2019 00:19
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
7
904
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это пример. Вам нужно добавить проверку результатов malloc и realloc (я не делал этого для простоты)

#include <stdio.h>
#include <stdlib.h>

#define CHUNK   32 

char *readline(void)
{
    size_t csize = CHUNK;
    size_t cpos = 0;
    char *str = malloc(CHUNK);
    int ch;
    while((ch = fgetc(stdin)) != '\n' && ch != '\r')
    {
        str[cpos++] = ch;
        if (cpos == csize)
        {
            csize += CHUNK;
            str = realloc(str, csize);
        }
    }
    str[cpos] = 0;
    return str;
}

int main()
{
    printf("\n%s\n", readline());

    return 0;
}

рабочий пример: https://onlinegdb.com/Sk9r4gOYV

Вы также должны освобождать выделенную память, когда она больше не нужна.

Другие вопросы по теме