9
8

More than 5 years have passed since last update.

PHPのstrtr関数っぽいものをC言語で実装してみた

Last updated at Posted at 2015-08-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;
}
9
8
8

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8