Подтвердить что ты не робот

Как динамически распределять пространство памяти для строки и получать эту строку от пользователя?

Я хочу читать данные от пользователя, используя программу C. Я не хочу использовать массив, например,

char names[50];

потому что если пользователь задает строку длиной 10, остальные пробелы теряются.

Если я использую указатель символа, например,

char *names;

тогда мне нужно выделить память для этого таким образом,

names = (char *)malloc(20 * sizeof(char));

В этом случае также существует возможность потери памяти.

Итак, мне нужно динамически выделять память для строки, которая точно такая же, как длина строки.

Предположим, что

Если пользовательский ввод "stackoverflow", то выделенная память должна быть 14 (т.е. Длина строки = 13 и 1 дополнительное пространство для '\ 0').

Как я мог достичь этого?

4b9b3361

Ответ 1

Прочитайте по одному символу за раз (используя getc(stdin)) и увеличивайте строку (realloc) по ходу.

Вот функция, которую я написал некоторое время назад. Обратите внимание, что он предназначен только для ввода текста.

char *getln()
{
    char *line = NULL, *tmp = NULL;
    size_t size = 0, index = 0;
    int ch = EOF;

    while (ch) {
        ch = getc(stdin);

        /* Check if we need to stop. */
        if (ch == EOF || ch == '\n')
            ch = 0;

        /* Check if we need to expand. */
        if (size <= index) {
            size += CHUNK;
            tmp = realloc(line, size);
            if (!tmp) {
                free(line);
                line = NULL;
                break;
            }
            line = tmp;
        }

        /* Actually store the thing. */
        line[index++] = ch;
    }

    return line;
}

Ответ 2

У вас может быть массив, который начинается с 10 элементов. Прочитать входной символ по символу. Если это произойдет, перераспределите еще 5. Не самое лучшее, но потом вы можете освободить другое пространство позже.

Ответ 3

Если вам нужно освободить память, прочитайте char на char и перераспределите каждый раз. Производительность умрет, но вы пощадите это 10 байт.

Другим хорошим компромиссом является чтение в функции (с использованием локальной переменной), а затем копирование. Таким образом, большой буфер будет обладать функциями.

Ответ 4

Вы также можете использовать регулярное выражение, например следующий фрагмент кода:

char *names
scanf("%m[^\n]", &names)

получит всю строку из stdin, динамически распределяя объем пространства, который он занимает. После этого, конечно, вам нужно освободить names.

Ответ 5

Ниже приведен код для создания динамической строки:

void main()
{
  char *str, c;
  int i = 0, j = 1;

  str = (char*)malloc(sizeof(char));

  printf("Enter String : ");

  while (c != '\n') {
    // read the input from keyboard standard input
    c = getc(stdin);

    // re-allocate (resize) memory for character read to be stored
    str = (char*)realloc(str, j * sizeof(char));

    // store read character by making pointer point to c
    str[i] = c;

    i++;
    j++;
  }

  str[i] = '\0'; // at the end append null character to mark end of string

  printf("\nThe entered string is : %s", str);

  free(str); // important step the pointer declared must be made free
}

Ответ 6

char* load_string()
 {

char* string = (char*) malloc(sizeof(char));
*string = '\0';

int key;
int sizer = 2;

char sup[2] = {'\0'};

while( (key = getc(stdin)) != '\n')
{
    string = realloc(string,sizer * sizeof(char));
    sup[0] = (char) key;
    strcat(string,sup);
    sizer++

}
return string;

}

int main()
  {
char* str;
str = load_string();

return 0;
  }

Ответ 7

Это более простой подход

char *in_str;
in_str=(char *)malloc(512000 * sizeof(char));
scanf("\n%[^\n]",in_str);

Ответ 8

Вот фрагмент, который я написал, который выполняет те же функции.

Этот код похож на тот, который написал Кунал Вадхва.

char *dynamicCharString()
{
char *str, c;
int i;
str = (char*)malloc(1*sizeof(char));

while(c = getc(stdin),c!='\n')
{
    str[i] = c;
    i++;
    realloc(str,i*sizeof(char));
}
str[i] = '\0';
return str;
}

Ответ 9

Сначала определите новую функцию для чтения ввода (в соответствии со структурой вашего ввода) и сохранения строки, что означает использование памяти в стеке. Установите длину строки, достаточную для ввода.

Во-вторых, используйте strlen для измерения точной используемой длины строки, сохраненной ранее, и malloc для выделения памяти в куче, длина которой определяется strlen. Код показан ниже.

int strLength = strlen(strInStack);
if (strLength == 0) {
    printf("\"strInStack\" is empty.\n");
}
else {
    char *strInHeap = (char *)malloc((strLength+1) * sizeof(char));
    strcpy(strInHeap, strInStack);
}
return strInHeap;

Наконец, скопируйте значение strInStack в strInHeap используя strcpy, и верните указатель на strInHeap. strInStack будет освобожден автоматически, потому что он выходит только из этой strInStack.

Ответ 10

Это фрагмент функции, который я написал, чтобы отсканировать пользовательский ввод на наличие строки и затем сохранить эту строку в массиве того же размера, что и пользовательский ввод. Обратите внимание, что я инициализирую j значением 2, чтобы иметь возможность хранить символ '\ 0'.

char* dynamicstring() {
    char *str = NULL;
    int i = 0, j = 2, c;
    str = (char*)malloc(sizeof(char));
    //error checking
    if (str == NULL) {
        printf("Error allocating memory\n");
        exit(EXIT_FAILURE);
    }

    while((c = getc(stdin)) && c != '\n')
    {
        str[i] = c;
        str = realloc(str,j*sizeof(char));
        //error checking
        if (str == NULL) {
            printf("Error allocating memory\n");
            free(str);
            exit(EXIT_FAILURE);
        }

        i++;
        j++;
    }
    str[i] = '\0';
    return str;
}

В main() вы можете объявить другую переменную char * для хранения возвращаемого значения dynamicstring(), а затем освободить эту переменную char *, когда вы закончите ее использовать.

Ответ 11

realloc - довольно дорогое действие... вот мой способ получения строки, соотношение realloc не 1:1:

char* getAString()
{    
    //define two indexes, one for logical size, other for physical
    int logSize = 0, phySize = 1;  
    char *res, c;

    res = (char *)malloc(sizeof(char));

    //get a char from user, first time outside the loop
    c = getchar();

    //define the condition to stop receiving data
    while(c != '\n')
    {
        if(logSize == phySize)
        {
            phySize *= 2;
            res = (char *)realloc(res, sizeof(char) * phySize);
        }
        res[logSize++] = c;
        c = getchar();
    }
    //here we diminish string to actual logical size, plus one for \0
    res = (char *)realloc(res, sizeof(char *) * (logSize + 1));
    res[logSize] = '\0';
    return res;
}