Как защитить динамический символ от перезаписи вторым динамическим символом?

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

char print_two(char *reg, char *s)
{
    int i, l_s = (int) strlen(s), l_reg = (int) strlen(reg);
    for(i = 0; i < l_reg; i++)
    {
        printf("\n %c \n", reg[i]);
    }
    return 0;
}

int main(void)
{
    char reg;
    printf("Give a rule: ");
    scanf("%s", &reg);

    char s;
    printf("Give a string: ");
    scanf("%s", &s);

    print_two(&reg, &s);
    return 0;
} 

Старт программы:

Give a rule: qwert
Give a string: asdf
result:
d
q
a
s
d
f

Как избежать перезаписи reg на s?

Пробовал с realloc, malloc - 0 эффекта.

Две переменные должны быть динамическими.

Возможно ли это сделать?


пользователь дает 55 символов -> массив 55

пользователь дает 100 символов -> массив 100


person Jan Czarny    schedule 28.01.2013    source источник
comment
Просто примечание рядом: я надеюсь, вы знаете, что scanf("%s, ...) читает ввод только до первого символа пробела!?   -  person Werner Henze    schedule 28.01.2013
comment
Я знаю об этом, но спасибо за подсказку :)   -  person Jan Czarny    schedule 28.01.2013
comment
Связанный ответ для чтения полной строки динамической длины: stackoverflow.com/a/11917634/1717300   -  person hyde    schedule 28.01.2013


Ответы (3)


Основываясь на ваших комментариях к другим ответам, если вы согласны с использованием расширений библиотеки GNU (в основном в Linux или в Windows MinGW), вы можете использовать %ms в строке формата scanf, например:

char *reg = NULL; // set to NULL to get segfault on uninitialized use
printf("Give a rule: ");
scanf("%ms", &reg); // scanf will malloc enough space to reg

// check for null in case scanf failed to read anything for some reason
// could also check return value of scanf, which is number of items it got
if (reg != NULL) {
  // process reg
}

free(reg); // free(NULL) is not an error, it just does nothing
reg = NULL; // set to NULL to get segfault on uninitialized use

Другие ответы показывают, как использовать буфер с фиксированным размером, который является стандартным C. Хотя согласно man scanf раздел примечаний, %ms может появиться в будущем стандарте POSIX. У GNU также есть старая версия %as, но %ms следует отдавать предпочтение, если она поддерживается (т. е. в любой современной системе GNU).

person hyde    schedule 28.01.2013
comment
Нет проблем, это дало мне возможность обновить свои знания (отредактированный ответ только что, если вы не заметили). - person hyde; 28.01.2013

scanf("%s", ...) читает строку со стандартного ввода. Ваши переменные reg и s выделяют память для одного символа, а не для полной строки. Вам нужно изменить это на char reg[128], например, если длина входной строки может составлять не более 128 символов. Чтобы предотвратить переполнение буфера, вам также следует рассмотреть возможность ограничения длины входных данных, сканируемых scanf, с помощью scanf("%127s", ...).

person Werner Henze    schedule 28.01.2013
comment
Но когда вы не знаете объем данных, введенных пользователем? - person Jan Czarny; 28.01.2013
comment
@Jan Czarny: Тогда это усложняется, и вам нужно написать свою собственную функцию, которая считывает вводимый символ за символом и сохраняет строку в динамически выделяемом и расширяемом блоке памяти. В C++ это было бы намного проще, вы могли бы использовать std::string. Если вы используете GCC, вы можете попробовать подход Хайда. - person Werner Henze; 28.01.2013

Вы не можете прочитать строку (несколько символов) в один символ, например char s.

Вам нужно зарезервировать больше места:

char reg[128], s[128];

В противном случае случайные вещи в памяти перезаписываются, и вы получаете неопределенное поведение.

person unwind    schedule 28.01.2013
comment
как принять неизвестное количество символов в две переменные данных? Массив создает проблему с неизвестным. - person Jan Czarny; 28.01.2013