発端
— 又横顔 (@tadsan) 2015, 8月 27
経緯
編集リクエスト (改竄) http://t.co/A7u4QRgMiV
— 進捗 (@mpyw) 2015, 8月 27
原形がない…
— 又横顔 (@tadsan) 2015, 8月 27
str_replaceだけ触れてstrtrを説明していない記事って腐るほどあるけどそれを見るたびstrtrが気の毒になる
— 進捗 (@mpyw) 2015, 8月 27
“一度置換した文字列はもう置換の対象にならないことを確認しましょう”のあたりが実装めんどくさそう (まっぴー氏の実装まだちゃんと読んでない)
— 又横顔 (@tadsan) 2015, 8月 27
@tadsan PHPの関数使ってるのでまだラクですけどこれCでいちから実装するのかなりエグいですww
— 進捗 (@mpyw) 2015, 8月 27
Cでstrtr実装してみたさあるぞ
— 進捗 (@mpyw) 2015, 8月 27
— 又横顔 (@tadsan) 2015, 8月 27
全ての元凶 https://t.co/Y43lyhmxj8
— 進捗 (@mpyw) 2015, 8月 27
寝れない💢
— 進捗 (@mpyw) 2015, 8月 27
コード
strtr_strings
の方に不具合があります。C言語詳しい人おしえてください。
-
修正完了malloc
してるはずなのにfree
出来ないって言われる -
文字列の末尾付近の置換結果がおかしい修正完了
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct memo_t {
size_t pos;
size_t len;
} Memo;
int compare_memo(const void *a, const void *b) {
return (ssize_t)((const Memo*)b)->len - (ssize_t)((const Memo*)a)->len;
}
char *strtr_chars(char *str, const char *from, const char *to) {
char *s = str;
while (*s) {
const char *f = from;
const char *t = to;
while (*f && *t) {
if (*s == *f) {
*s = *t;
break;
}
++f;
++t;
}
++s;
}
return str;
}
char *strtr_strings(const char *str, size_t size, const char *from[size], const char *to[size], char **buffer) {
Memo memo[size];
for (size_t i = 0; i < size; ++i) {
memo[i].pos = i;
memo[i].len = strlen(from[i]);
}
qsort(memo, size, sizeof(Memo), compare_memo);
size_t capacity = strlen(str) + 1;
size_t filled = 0;
if (!(*buffer = (char *)malloc(capacity))) {
perror("malloc");
exit(EXIT_FAILURE);
}
char *ptr = *buffer;
while (*str) {
for (size_t i = 0; i < size; ++i) {
size_t pos = memo[i].pos;
const char *haystack = str;
const char *needle = from[pos];
while (*haystack && *needle && *haystack == *needle) {
++haystack;
++needle;
}
if (!*needle) {
needle = from[pos];
const char *replace = to[pos];
while (*needle++) {
++str;
}
while (*replace) {
if (capacity - filled < 1) {
size_t pos = ptr - *buffer;
*buffer = realloc(*buffer, capacity += 1024);
if (!*buffer) {
perror("realloc");
exit(EXIT_FAILURE);
}
ptr = *buffer + pos;
}
++filled;
*ptr++ = *replace++;
}
break;
} else if (i == size - 1) {
if (capacity - filled < 1) {
size_t pos = ptr - *buffer;
*buffer = realloc(*buffer, capacity += 1024);
if (!*buffer) {
perror("realloc");
exit(EXIT_FAILURE);
}
ptr = *buffer + pos;
}
++filled;
*ptr++ = *str++;
}
}
}
*ptr = '\0';
return *buffer;
}
int main(void) {
char str[] = "abaabbabcababcabbabc";
char *ptr;
const char *from_strings[] = {"a", "ab", "abc"};
const char *to_strings[] = {"<a>", "<ab>", "<abc>"};
printf("%s\n", strtr_strings(
str, sizeof(from_strings) / sizeof(char *), from_strings, to_strings, &ptr
));
printf("%s\n", strtr_chars(str, "abc", "cab"));
free(ptr);
return 0;
}