在c中创建字符串列表不起作用?
我开始学习c编程,我试图将一个字符串拆分成一系列子字符串。我创建了一个名为String的用于创建字符串的结构在c中创建字符串列表不起作用?,c,string,memory,C,String,Memory,我开始学习c编程,我试图将一个字符串拆分成一系列子字符串。我创建了一个名为String的用于创建字符串的结构 #include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdbool.h> typedef struct dynamic_string { char* data; size_t capacity; size_t size; } St
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
typedef struct dynamic_string {
char* data;
size_t capacity;
size_t size;
} String;
void free_string(String* s) { free(s->data); s->data = NULL; }
void print_string(String* s) { for (int i = 0; i < s->size; ++i) { printf("%c", s->data[i]); } printf("\n"); }
void clear_string(String* s) { s->size = 0; s->data[0] = '\0'; }
int string_init(String* s, size_t init_capacity) {
s->data = malloc(init_capacity);
if (!s->data) { return -1; };
s->size = 0; s->capacity = init_capacity;
return 0;
}
void add_char(String* s, char element) {
size_t new_size = s->size + 1;
if (new_size > s->capacity) { s->capacity = s->capacity << 1; s->data = realloc(s->data, s->capacity); }
s->data[s->size] = element;
s->size = new_size;
}
void add_charp(String* s, char* string) {
size_t stringlen = strlen(string);
size_t new_size = s->size + stringlen;
if (new_size > s->capacity) { s->capacity = new_size << 1; s->data = realloc(s->data, s->capacity); }
strcpy(s->data + s->size, string);
s->size = new_size;
}
void add_string(String* s, String* string) {
size_t stringlen = string->size;
size_t new_size = s->size + stringlen;
if (new_size > s->capacity) { s->capacity = new_size << 1; s->data = realloc(s->data, s->capacity); }
strcpy(s->data + s->size, string->data);
s->size = new_size;
}
#包括
#包括
#包括
#包括
typedef结构动态_字符串{
字符*数据;
容量大小;
大小;
}弦;
void free_string(string*s){free(s->data);s->data=NULL;}
无效打印字符串(string*s){for(inti=0;isize;++i){printf(“%c”,s->data[i])}printf(“\n”)}
无效清除字符串(字符串*s){s->size=0;s->data[0]='\0';}
int字符串初始化(字符串*s,大小初始化容量){
s->data=malloc(初始容量);
如果(!s->data){return-1;};
s->size=0;s->capacity=init_capacity;
返回0;
}
void add_char(字符串*s,char元素){
大小\u t新大小=s->size+1;
如果(新大小>容量){s->capacity=s->capacity data=realloc(s->data,s->capacity);}
s->数据[s->大小]=元素;
s->size=新尺寸;
}
void add_charp(字符串*s,字符*String){
尺寸\u t stringlen=strlen(字符串);
尺寸\u t新尺寸=s->尺寸+细线;
如果(新大小>容量){s->capacity=new大小数据=realloc(s->data,s->capacity);}
strcpy(s->data+s->size,string);
s->size=新尺寸;
}
void add_字符串(string*s,string*string){
大小\u t字符串长度=字符串->大小;
尺寸\u t新尺寸=s->尺寸+细线;
如果(新大小>容量){s->capacity=new大小数据=realloc(s->data,s->capacity);}
strcpy(s->data+s->size,string->data);
s->size=新尺寸;
}
现在这不是问题所在。当我尝试创建这些字符串的列表时,就会出现问题。我也做了一个这样做的结构
typedef struct dynamic_string_pointer {
String* data;
size_t capacity;
size_t size;
} StringVec;
void free_stringvec(StringVec* sv) { free(sv->data); sv->data = NULL; }
void print_stringvec(StringVec* sv) { for (int i = 0; i < sv->size; ++i) { print_string(&sv->data[i]); } }
int stringvec_init(StringVec* sv, size_t init_capacity) {
sv->data = malloc(init_capacity * sizeof(String));
if (!sv->data) { return -1; }
sv->size = 0; sv->capacity = init_capacity;
return 0;
}
void add_string_to_vec(StringVec* sv, String string) {
size_t new_size = sv->size + 1;
if (new_size > sv->capacity) { sv->capacity = sv->capacity << 1; sv->data = realloc(sv->data, sv->capacity * sizeof(String)); }
sv->data[sv->size] = string;
sv->size = new_size;
}
typedef结构动态字符串指针{
字符串*数据;
容量大小;
大小;
}StringVec;
void free_stringvec(stringvec*sv){free(sv->data);sv->data=NULL;}
void print_stringvec(stringvec*sv){for(inti=0;isize;++i){print_string(&sv->data[i]);}
int stringvec_init(stringvec*sv,大小_t init_容量){
sv->data=malloc(初始容量*sizeof(字符串));
如果(!sv->data){return-1;}
sv->size=0;sv->capacity=init_capacity;
返回0;
}
void将字符串添加到向量(StringVec*sv,字符串){
大小\u t新大小=sv->大小+1;
如果(新建大小>sv->容量){sv->capacity=sv->capacity data=realloc(sv->data,sv->capacity*sizeof(String));}
sv->数据[sv->大小]=字符串;
sv->size=新尺寸;
}
这个结构似乎没有问题,如果向其中添加不同的字符串,它就可以正常工作。问题是当我构建一个字符串并使用相同的变量将其添加到列表中时
例如:
void tokenize(char* text) {
StringVec tokens; stringvec_init(&tokens, 32);
String token; string_init(&token, 8);
bool first_char = false;
for (int i = 0; i < strlen(text); ++i) {
if (isToken(text[i])) {
if (!equals_charp(&token, "")) { add_string_to_vec(&tokens, token); }
clear_string(&token); add_char(&token, text[i]);
add_string_to_vec(&tokens, token);
clear_string(&token); first_char = false; continue;
}
if (text[i] != ' ' && text[i] != '\t' && text[i] != '\n'){ add_char(&token, text[i]); first_char = true; }
else if (first_char) { add_char(&token, text[i]); }
}
print_stringvec(&tokens);
free_string(&token);
free_stringvec(&tokens);
}
void标记化(char*text){
StringVec令牌;StringVec_init(&tokens,32);
字符串标记;字符串初始化(&token,8);
bool first_char=false;
对于(int i=0;i
在这里,我试图通过使用变量token并将其添加到tokens来构建令牌列表。问题似乎在于,当传递令牌将_string_添加到_vec时,它在堆栈上始终具有相同的地址。这似乎是对的,因为当我打印代币时,它只是一遍又一遍地打印最后一个代币。所以我试着换了
sv->data[sv->size]=字符串;使用memcpy(sv->data+sv->size,&string,sizeof(string))代码>
认为这会将内存从string复制到sv->data,以便在添加其他令牌时可以工作。这似乎也有同样的问题。我通常使用C++,它有STD::vector和STD::string,这使得这很容易。我可能很愚蠢,或者我只是理解内存是如何工作的,但是我还没有找到一种方法来让它工作。我按照Bo Persson说的做了,并实现了这些功能。现在它工作得非常好。(我稍微改变了tokenize函数的工作方式。)
String next\u标记(char*text,size\t size,int*start){
字符串标记;字符串初始化(&token,4);
char last_char='';
对于(int i=*start;i
我这里有免费代币
void free_stringvec(StringVec* sv) {
for (int i = 0; i < sv->size; ++i) {
free_string(&sv->data[i]);
}
free(sv->data); sv->data = NULL;
}
void free_stringvec(stringvec*sv){
对于(int i=0;isize;++i){
自由字符串(&sv->data[i]);
}
自由(sv->data);sv->data=NULL;
}
sv->data=malloc(初始容量*sizeof(字符串))代码>奇怪。。。另外if(!equals_charp(&token,”)
非常奇怪…顺便说一句,在add_charp()
中,如果new_size==s->capacity
则strcpy()
将最后的\0
写入无主内存。您只调用string\u init
一次。分配一个缓冲区,然后在所有拷贝之间共享
void free_stringvec(StringVec* sv) {
for (int i = 0; i < sv->size; ++i) {
free_string(&sv->data[i]);
}
free(sv->data); sv->data = NULL;
}