Для начала нужно понимание, что памятью на стеке управляет компилятор, и для каждой функции эта память имеет фиксированный размер. А все потому, что в ассемблере, в который скомпилится наш C код нет переменных, вместо них компилятор просто проставит смещения от указателя на конец стека на старте функции. Именно по этому компилятору важно знать размеры всех сущностей на стеке.
Изменить этот размер в рантайме нельзя, поэтому единственный способ решить эту задачу с массивом символов на стеке - выделить массив с достаточным запасом памяти, чтоб хватило и на исходную строку и на вставляемую подстроку.
А вот память в куче динамическая. И все аллокации работают именно с ней. И главное мы ее можем выделять в рантайме по мере надобности.
Учитывая, что массивы в C - это по сути сахар над указателями, то смело можете заявлять своему преподу, что указатель на несколько подряд идущих char в куче и массив char - это одно и то же.
Вообще, по нормальному я бы объявил структуру вроде такой:
typedef struct {
char* buffer;
size_t capacity;
size_t length;
} string;
и дальше бы работал с ней, заодно разбив код на небольшие функции. Но преподы программирования народ от разработки далекий, и кроме своих лабараторок в программировании не бум-бум в большинстве своем. А в комментах к вопросу было про то, что структуры нельзя...
Поэтому решение в лоб и в стиле универских лаб:
#include <stdio.h>
#include <stdlib.h>
int main() {
size_t capacity = 1 << 4; // на старте буду выделять 16 байт
size_t length = 0; // строка пока пустая, поэтому 0
char* str = malloc(capacity);
if (str == NULL) { // с памятью в куче может и облом быть
return 1; // вернем код ошибки
}
printf("Write string and press ENTER to continue:\n");
while(1) { // читать символы будем до скончания веков ))
char c = getchar();
if(c == 13 || c == 10) break; // ну или пока юзер не нажмет ентер
length++; // увеличим счетчик символов
if(length > capacity) { // если новый символ не влазит в выделеную память
capacity <<= 1; // то удвоим ее
char* new_str = realloc(str, capacity); // и перевыделим
if (new_str == NULL) { // опять чекнем, вдруг облом
free(str); // ресурсы надо освобождать
return 1; // вернем код ошибки
}
str = new_str; // в str теперь невалидный указатель, можем его заменить
}
str[length - 1] = c; // запомним считанный символ
}
// Здесь решение с вставкой подстроки
// с учетом того, что у нас строка str
// с длиной length и выделеной памятью под нее capacity
free(str); // ресурсы надо освобождать
return 0; // вернем код успешного завершения
}
с самой вставкой подстроки надеюсь справитесь?