因此,我被设置为创建一个人造字符串结构并在我的人造字符串结构上实现所有常用的字符串函数的任务。我被困在我的strcat实现的测试中,这个测试称为append,第一个测试失败(segfault)是第5行。我创建新结构的功能应该可以,因为它通过了所有测试,但是我只是以防万一。
我已经能够成功地为我的伪字符串结构实现length,get,set和copy函数。
结构:
struct text {
int capacity;
char *content;
};
typedef struct text text;
我用于创建新结构的功能:
text *newText(char *s) {
printf("new Text from %s\n", s);
int sizeNeeded = (strlen(s)+1);
int sizeGot = 24;
while (sizeNeeded > sizeGot) {
sizeGot = sizeGot * 2;
}
text *out = malloc(sizeGot);
char *c = malloc(sizeGot);
strcpy(c, s);
out->content = c;
out->capacity = (sizeGot);
printf("the capacity is %d\n", sizeGot);
return out;
free(c);
}
我的附加函数:
void append(text *t1, text *t2) {
printf("t1 content is %s, t2 content is %d\n", t1->content, *t2->content);
int sizeNeeded = (t1->capacity + t2->capacity);
int sizeGot = 24;
while (sizeNeeded > sizeGot) {
sizeGot = sizeGot * 2;
}
char *stringy = calloc(sizeGot, 32);
stringy = strcat(t1->content, t2->content);
free(t1);
t1 = newText(stringy);
}
最后是测试:
void testAppend() {
text *t = newText("car");
text *t2 = newText("pet");
append(t, t2);
assert(like(t, "carpet"));
assert(t->capacity == 24);
text *t3 = newText("789012345678901234");
append(t, t3);
assert(like(t, "carpet789012345678901234"));
assert(t->capacity == 48);
freeText(t);
freeText(t2);
freeText(t3);
}
答案 0 :(得分:0)
您以错误的方式分配内存。您可以像这样使用 flexible数组成员来解决此问题:
typedef struct {
int capacity;
char content[];
} text;
text *out = malloc(sizeof(text) + sizeof(something));
strcpy(out->content, str);
...
显然,这样的代码是胡说八道:
return out;
free(c);
}
启用编译器警告并听取它们。
答案 1 :(得分:0)
Och,您遇到了一些错误:
text_new
内,如果text *out
为常数,则使用text *out = malloc(sizeGot);
为sizeGot = 24
分配内存。您应该为此分配sizeof(*out)
或sizeof(text)
字节的内存。int sizeGot = 24; while (sizeNeeded > sizeGot)
和text_new
内的循环是干什么的。我猜想这样做的目的是用24的幂进行分配。而且看起来两个函数中的代码似乎都一样,看起来确实像代码重复,这是一件坏事。append
内部,您传递了一个指向append
的指针,而不是双指针,因此,如果您修改t1指针本身,则该修改在函数范围之外是不可见的。 t1
毫无意义,并且会泄漏内存。您可以先t1 = newText(stringy);
,然后再void append(text **t1, text *t2)
。但是,您可以使用*t1 = newText(stringy)
使用更好的方法-我希望将append添加到“追加”字符串,而不是创建新对象。因此,首先使用realloc
,然后使用realloc
调整缓冲区的大小。strcat(&t1->content[oldcapacity - 1], string_to_copy_into_t1)
已关闭。您分配的容量为24的幂,它实际上不会与字符串长度发生交互。两个字符串和空终止符都需要有int sizeNeeded = (t1->capacity + t2->capacity);
个字节。尝试一下:
strlen(t1->content) + strlen(t2->content) + 1
这:
size_t text_newsize(size_t sizeNeeded)
{
// I think this is just `return 24 << (sizeNeeded / 24);`, but not sure
int sizeGot = 24;
while (sizeNeeded > sizeGot) {
sizeGot *= 2;
}
return sizeGot;
}
text *newText(char *s) {
printf("new Text from %s\n", s);
if (s == NULL) return NULL;
int sizeNeeded = strlen(s) + 1;
int sizeGot = text_newsize(sizeNeeded);
text *out = malloc(sizeof(*out));
if (out == NULL) {
return NULL;
}
out->content = malloc(sizeGot);
if (out->content == NULL) {
free(out);
return NULL;
}
strcpy(out->content, s);
out->capacity = sizeGot;
printf("the capacity is %d\n", sizeGot);
return out;
}
一些评论:
int append(text *t1, text *t2) {
printf("t1 content is %s, t2 content is %s\n", t1->content, t2->content);
int sizeNeeded = strlen(t1->content) + strlen(t2->content) + 1;
if (t1->capacity < sizeNeeded) {
// this could a text_resize(text*, size_t) function
int sizeGot = text_newsize(sizeNeeded);
void *tmp = realloc(t1->content, sizeGot);
if (tmp == NULL) return -ENOMEM;
t1->content = tmp;
t1->capacity = sizeGot;
}
strcat(t1->content, t2->content);
return 0;
}
这样的函数,则将其设为void append(text *t1, text *t2)
,并在成功时返回0,并在int append(text *t1, text *t2)
错误时返回负数。*alloc
类型存储所有内容的大小。它在size_t
中定义,应用于表示对象的大小。 stddef.h
返回strlen
,而size_t
也返回sizeof
。size_t
这样的字符串来实现。text_
对象的代码,我使用text
幻数作为分配块大小。
24