%s
с scanf
ничего не выделяет. Вызывающий должен выделить. Даже если вы выделяли что-то, поскольку вы не знаете, какой будет длина строки во входном потоке, это похоже на выполнение gets
, что плохо по соображениям безопасности и стабильности.
Одна из самых простых вещей, которые вы можете сделать, - это предварительно установить постоянное количество символов и использовать fgets:
char string[256];
if (!fgets(string, sizeof(string), stdin))
{
// TODO: handle error
}
Это накладывает искусственное ограничение на максимальный размер строки. Другой подход заключается в использовании динамической памяти. Вот лишь краткий пример, который увеличивает буфер по мере необходимости.
char *buf = NULL;
size_t current_len = 0, current_alloc = 0;
int c = 0;
int should_continue = 1;
while (should_continue)
{
// Read a character...
c = fgetc(stdin);
// If c is EOF or a newline, let's zero-terminate the buffer and terminate
// the loop...
if (c == EOF || c == '\n')
{
c = 0;
should_continue = 0;
}
if (current_len + 1 > current_alloc)
{
// Need to grow the buffer.
void *newbuf;
size_t newsize;
newsize = current_alloc ? current_alloc * 2 : 256;
newbuf = realloc(buf, newsize);
if (!newbuf) { /* TODO: handle error */ }
current_alloc = newsize;
buf = newbuf;
}
// We've ensured capacity, now add the character.
buf[current_len++] = c;
}
// TODO: use buf as string...
// Now free since we're done
free(buf);
Что касается обращения строки, то это всего лишь пример типичного способа работы со строками в стиле C:
// Reverse the string in-place...
void reverse(char *s)
{
if (*s)
{
char *t = s + strlen(s) - 1;
while (s < t)
{
char u = *s;
*s++ = *t;
*t-- = u;
}
}
}
С этим после прочтения вы можете сделать:
reverse(string);
puts(string);