C 伸長する文字列
2008/03/11
C言語で、ある文字列処理をして、その結果を別のバッファに格納するような場合、バッファ溢れしないように気をつけなければなりません。cgiでは、それ程複雑な処理を行なう必要がないので、appendできて、結果の文字列が取得できれば事足ります。そこで、足りなくなったら伸びる文字列を作成しました。
使い方
#include <stdio.h> #include "simple_string.h" int main(int argc, char** argv) { String* s = string_new(10); //この時点で、バッファの長さは10 string_append(s, "1234567890"); //20に拡張される。 string_append(s, "123"); string_append(s, "45678901234567890"); //40に拡張される。 string_append(s, "123"); string_append(s, "456"); string_append(s, "789"); string_append(s, "012"); //50に拡張される。 printf("%s\n", string_rawstr(s)); string_free(s); return 0; }
string_new の引数でブロックサイズを指定します。最初に指定したブロックサイズが確保され、string_appendで文字列を連結できます。バッファの長さが足りなくなったら内部でバッファの長さが伸長されます。最後に連結した結果のchar配列をstring_rawstrで取得できます。不要になったら、string_freeで開放します。
かなり機能を限定してるので、実装はシンプルです。
simple_string.h
#ifndef SIMPLE_STRING_H #define SIMPLE_STRING_H #include <string.h> typedef struct _String { char* raw_chars; size_t block_size; size_t buf_size; size_t current_size; } String; String* string_new(size_t); void string_append(String*, char*); char* string_rawstr(String*); void string_free(String*); #endif /* vim: set ts=4 sw=4 sts=4 expandtab fenc=utf-8: */
simple_string.c
#include <stdio.h> #include <stdlib.h> #include "simple_string.h" #define STRING_DEFAULT_SIZE 10 static void* xalloc(size_t size) { void* p = calloc(1, size); if (!p) { fprintf(stderr, "memory error."); exit(-1); } return p; } static void xfree(void* p) { free(p); } String* string_new(size_t block_size) { String* str = xalloc(sizeof(String)); if (block_size == 0) { str->block_size = STRING_DEFAULT_SIZE; } else { str->block_size = block_size; } str->raw_chars = xalloc(sizeof(char) * str->block_size); str->buf_size = str->block_size; strcpy(str->raw_chars, ""); return str; } void string_append(String* str, char* addstr) { size_t len = strlen(addstr); int size_needed = str->current_size + len + 1; if (size_needed > str->buf_size) { int new_size = str->block_size * (size_needed / str->block_size + 1); str->raw_chars = realloc(str->raw_chars, sizeof(char) * new_size); if (!str->raw_chars) { fprintf(stderr, "memory error."); exit(-1); } str->buf_size = new_size; } strcat(str->raw_chars, addstr); str->current_size += len; /* printf("%d (size: %d)\n", str->current_size, str->buf_size); */ } char* string_rawstr(String* str) { return str->raw_chars; } void string_free(String* str) { if (str->raw_chars) xfree(str->raw_chars); xfree(str); } size_t string_len(String* str) { return str->current_size; } /* vim: set ts=4 sw=4 sts=4 expandtab fenc=utf-8: */
追記20080312:simple_string.c の中の処理(string_append)を修正しました。
追記20080319:環境によっては害はないかもしれませんが、reallocする時のサイズ指定が間違ってました。「sizeof(char) * 」を追加