Нужно реализовать библиотеку функций для построителя строк
Нужно реализовать библиотеку функций для построителя строк, позволяющую «собирать строку» по частям (в динамической памяти, из других строк и символов, соединяя их последовательно). Компилятор выдает ошибку(в функции char*gluestr невозможно преобразовать тип void в char), помогите пожалуйста.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char*topstr(char*str)
{
size_t len = strlen(str);
char*top =(char*) malloc(len + 1);
if (!top)
{
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return NULL;
}
return top;
}
char*gluestr(char*top, char*anystr)
{
size_t len1 = strlen(top);
size_t len2 = strlen(anystr);
topstr(top);
top=realloc(top, sizeof(char)*(len1+len2+1));
if (!top)
{
fprintf(stderr, "malloc() failed: insufficient memory!\n");
return NULL;
}
strcat(top, anystr);
return top;
}
int main()
{
char str1[20];
char str2[20];
puts("Type a string");
fgets(str1,sizeof(str1),stdin);
fgets(str2,sizeof(str2),stdin);
gluestr(str1,str2);
puts(str1);
return 0;
}
Ответы (2 шт):
Компилируйте как С, а не как С++. Установите соответствующие настройки проекта или ключи командной строки.
Или добавьте приведение типа (char*), как вы это делали с malloc:
top = (char*)realloc(top, sizeof(char)*(len1+len2+1));
Ошибки
Не компилируется потому что вы, видимо, компилируете код C++ компилятором. Компилятор C не будет выдавать эту ошибку. В C++
void *не приводится автоматически кchar *, а в C приводится.topstrвыделяет память и забывает скопировать туда строку.gluestrвызываетtopstrи теряет выделенную память.gluestrвызываетreallocна указателеtopкоторый указывает на буфер в стеке, а не на объект в куче. Это ломает всю свободную память и затирает стек.strcatдобавляет новые символы в буфер на стеке, а не в новой памяти. Хотя после предыдущего пункта это уже не важно.
Как поправить
В topstr добавить копирование строки:
char *topstr(const char *s) {
char *s2 = malloc(strlen(s) + 1);
if (s2 == NULL) {
fprintf(stderr, "malloc() failed: insufficient memory\n");
return NULL;
}
strcpy(s2, s);
return s2;
}
gluestr придётся капитально переписать. Теперь она возвращает флаг что строки склеены успешно. Если памяти хватило, то указатель s1 может быть обновлен. Никогда не пишите p = realloc(p, ...) - в случае ошибки вы теряете указатель на старую память:
bool gluestr(char **s1, const char *s2) {
size_t len1 = strlen(*s1);
size_t len2 = strlen(s2);
char *s3 = realloc(*s1, len1 + len2 + 1);
if (s3 == NULL) {
fprintf(stderr, "realloc() failed: insufficient memory\n");
return false;
}
strcat(s3, s2);
*s1 = s3;
return true;
}
Пример использования:
int main() {
char str1[20];
char str2[20];
puts("Type a string");
fgets(str1, sizeof(str1), stdin);
fgets(str2, sizeof(str2), stdin);
char *s = topstr(str1);
if (s != NULL && gluestr(&s, str2)) {
puts(s);
}
}
Бонус
topstr не нужна, если доработать gluestr. Добавим возможность обрабатывать нулевой указатель в gluestr. Изменится первая строчка: если *s1 == NULL то нельзя вызывать strlen. В конце функции strcat(s3 заменён на strcpy(s3 + len1. Это нужно, так как strcat нельзя вызывать если в s3 неинициализированная память:
bool gluestr(char **s1, const char *s2) {
size_t len1 = (*s1 == NULL) ? 0 : strlen(*s1);
size_t len2 = strlen(s2);
char *s3 = realloc(*s1, len1 + len2 + 1);
if (s3 == NULL) {
fprintf(stderr, "realloc() failed: insufficient memory\n");
return false;
}
strcpy(s3 + len1, s2);
*s1 = s3;
return true;
}
Тогда пользоваться ею можно так:
char *s = NULL;
if (gluestr(&s, str1) && gluestr(&s, str2)) {
puts(s);
}
realloc сам выделит память под первую строку если ему дать нулевой указатель.