gpt4 book ai didi

在 c 中创建字符串列表不起作用?

转载 作者:行者123 更新时间:2023-11-30 19:32:04 25 4
gpt4 key购买 nike

我开始学习 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;
} 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 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;
}

这个结构似乎没有问题,如果您向其中添加不同的字符串,它可以正常工作。问题是当我构建一个字符串并使用相同的变量将其添加到列表中时。

例如:

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);
}

在这里,我尝试通过使用变量标记并将其添加到标记来构建标记列表。问题似乎是,当 token 传递给 add_string_to_vec 时,它在堆栈上始终具有相同的地址。这似乎是正确的,因为当我打印 token 时,它只是一遍又一遍地打印最后一个 token 。所以我尝试更换

sv->data[sv->size] = 字符串;与 memcpy(sv->data + sv->size, &string, sizeof(String));

认为这会将内存从字符串复制到 sv->data ,以便在添加其他标记时它可以工作。这似乎也有同样的问题。我通常使用 C++,它具有 std::vector 和 std::string 这使得这很容易。我可能只是愚蠢,或者也许我只是理解内存是如何运作的,但我一直无法找到一种方法来让它发挥作用。

最佳答案

我按照 Bo Persson 所说的做了,并制作了这些函数。现在它工作得很好。 (我稍微改变了 tokenize 函数的工作方式。)

String next_token(char* text, size_t size, int* start) {
String token; string_init(&token, 4);

char last_char = ' ';
for (int i = *start; i < size; ++i) {
if (last_char == ' ' && text[i] == ' ') { continue; }
if (text[i] == '\t' || text[i] == '\n') { if (last_char != ' ') { add_char(&token, ' '); } continue;}
if (isToken(text[i])) {
*start = i;
if (token.size == 0) { *start += 1; add_char(&token, text[i]); }
return token;
}
add_char(&token, text[i]);
last_char = text[i];
}

return token;
}

StringVec tokenize(char* text) {
StringVec tokens; stringvec_init(&tokens, 32);

size_t textlen = strlen(text);

for (int i = 0; i < textlen;) {
String token = next_token(text, textlen, &i);
add_string_to_vec(&tokens, token);
}

return tokens;
}

我在这里免费 token 。

void free_stringvec(StringVec* sv) { 
for (int i = 0; i < sv->size; ++i) {
free_string(&sv->data[i]);
}
free(sv->data); sv->data = NULL;
}

关于在 c 中创建字符串列表不起作用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47502539/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com