Необходимо раскритиковать код и дать советы по исправлению

Помогите исправить мой недо-код, пожалуйста. Даны две строки равной длины. Объединить их в одну строку и записать на место первой так, чтобы на нечётных местах шли буквы первой строки, а на чётных - второй.

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int output(char* s);
int st_len(char* st);
int main()
{
    char* st1, * st2, * st;
    int i = 0;
    st1 = (char*)calloc(1, 1);
    fgets(st1, 255, stdin);
    output(st1);
    st2 = (char*)calloc(1, 1);
    fgets(st2, 255, stdin);
    output(st2);
    st_len(st1);
    st = 0;
    do
    {   
        st += st1[i];
        st += st2[i];
        i++;
    } 
    while (i<=2*st_len(st1));
    st1 = st;
    output(st1);
}
int output(char* s)
{
    int i = 0;
    printf("\n");
    while (s[i] != '\0')
    {
        printf("%c", s[i]);
        i++;
    }
    printf("\n");
    return 0;
}
int st_len(char* st)
{
    int n = 0;
    for (; st[n] != '\0'; n++);
    return n;
}

Ответы (2 шт):

Автор решения: AlexGlebe

Массиву букв нужно выделить память по больше. И обнуление не нужно вообще.

st1 = (char*)malloc(510);
st2 = (char*)malloc(255);
st  = (char*)malloc(510);

Функция fgets считывает строку вместе с символом конца строки \n. Желательно его убрать, а то будет лишние переносы строк. Проверять надо его наличие потому-что заведённая строка могла быть очень большой.

fgets(st1, 255, stdin);
if(st1[strlen(st1)-1] == '\n')
  st1[strlen(st1)-1] = '\00' ;
fgets(st2, 255, stdin);
if(st2[strlen(st2)-1] == '\n')
  st2[strlen(st2)-1] = '\00' ;

Проверять надо условие задачи : что строки одинаковой длины. Иначе может быть ошибка доступа к памяти.

if(strlen(st1) != strlen(st2)) {
  fputs("String lengths is different\n",stderr);
  goto Exit ; }

Циклом заполняем буквы этих строк и команда += изменяет указатель а не строку. Так как строка это массив букв нужно работать как с массивом. Индексы массива длины Length это 0 .. Length-1. И доступ к элементу [Length] будет неправильным. Цикл i<=2*st_len(st1) нужно заменить на i<st_len(st1). Попроще можно так :

size_t sl = strlen(st1); 
while ( i < sl )
{   
    st [i * 2] = st1[i];
    st [i * 2 + 1] = st2[i];      
    ++ i ;
} 
st [i * 2] = '\00' ;

После копирования букв в конце нужно добавить нулевой символ, так как функция печати ориентируется именно на него.

После создания результата нужно строку st записать в первую строку st1 как было сказано в задаче. Ваше присвоение st=st1; это присвоение указателя, а не строки. Копировать можно циклом :

for(int j=i * 2;j>=0;--j)
  st1[j] = st[j];

Или если кто-то неправильно понял задачу, то так :

size_t sl = strlen(st1); 
while ( i < sl )
{   
    if ( i % 2 == 0 )
      st [i] = st1[i];
    else
      st [i] = st2[i];      
    ++ i ;
} 
st [i] = '\00' ;
for(int j=i;j>=0;--j)
  st1[j] = st[j];

Освобождать память нужно всегда, чтобы не забывать. Забывание приведёт к утечке памяти.

Exit :
 free(st);
 free(st2);
 free(st1);
→ Ссылка
Автор решения: Harry

По-моему, вы делаете ошибку - не смо'трите на это: записать на место первой так... - т.е. если строки abcdef и ghijkl, то вместо первой должно быть ahcjel... Далее, я не вижу условия, что нельзя выводить строку как строку или что нельзя использовать ту же strlen().

Поэтому - я бы делал так:

int main()
{
#define len 300
    char st1[len], st2[len];
    printf("1st string: ");
    fgets(st1, len, stdin);
    printf("2nd string: ");
    fgets(st2, len, stdin);
    if (strlen(st1) != strlen(st2))
    {
        fprintf(stderr,"strlen(st1) != strlen(st2)\n");
        return 1;
    }
    
    printf("\n\n1st string: %s",st1);
    printf("2nd string: %s",st2);
    
    for(int i = 1; i < strlen(st2); i+=2)
        st1[i] = st2[i];
    printf("Res string: %s",st1);
}

См. https://ideone.com/Icjqbt

→ Ссылка