フリーランスのためのネットビジネス専門学校 ネットで独立開業を目指す人を応援
フリーランスのためのネットビジネス専門学校 ネットで独立開業を目指す人を応援

C言語でPHPとかのexplode関数を実装してみる

PHPでお馴染みexplode関数をC言語で実装する。

PHPのexplode関数は、第一引数に渡した文字列にマッチする箇所で第二引数に渡した被分割対象文字列を分割し、配列にする
関数です。

それをC言語で実装するならどのようになるか自前でトレーニングを兼ねて実装してみました。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>


/**
 * 指定した文字列に任意の文字列が現れた最初のメモリアドレスを返却する
 * @param char* str
 * @param char* needle
 * @return char*
 */
char* checkByteSequence(char* str, char* needle) {
    char *res = NULL;
    int l = strlen(str);
    int ll = strlen(needle);
    int match_count = 0;
    if (l >= ll) {
    } else {
        return NULL;
    }
    int i;
    for (i = 0; i < l; i++)
    {
        if (str[i] == needle[match_count]) {
            if (res == NULL) {
                res = str + i;
            }
            if (match_count == ll - 1)
            {
                return res;
            }
            match_count++;
        } else {
            // 1byteでもマッチしなかったら戻り値をNULLにもどす
            res = NULL;
            match_count = 0;
        }
    }
    return res;
}

/**
 * 指定した文字列で任意の文字列を区切って配列に置換する。かつ第三引数のint型参照に
 * 配列のサイズを保持させる。
 * @param char* target
 * @param char* needle
 * @param int* count
 * @return char**
 */
char** explode(char* target, char* needle, int* count) {
    *count = 0;
    char **response = NULL;
    char *temp = NULL;
    while (1)
    {
        temp = checkByteSequence(target, needle);
        if (temp == NULL) {
            if (strlen(target) > 0) {
                (*count)++;
                response = (char**)realloc(response, *count * sizeof(char *));
                if (response == NULL) {
                    printf("メモリアロケーションに失敗");
                    return NULL;
                }
                response[*count - 1] = target;
            }
            break;
        }
        (*count)++;
        response = (char**)realloc(response, *count * sizeof(char *));
        if (response == NULL) {
            printf("メモリアロケーションに失敗");
            return NULL;
        }
        *temp = 0;
        response[*count - 1] = target;
        target = temp +  strlen(needle);
    }
    return response;
}
int main() {

    // 被分割文字列
    char str[] = "あいうえお<区切り文字列>かきくけこ<区切り文字列>さしすせそ<区切り文字列>たちつてと<区切り文字列>なにぬねの<区切り文字列>はまやらわ<区切り文字列>やいゆえよ<区切り文字列>";
    char** str_list = NULL;
    int length_ptr = NULL;
    str_list = explode(str, "<区切り文字列>", &length_ptr);
    int i;
    for( i =0; i < length_ptr ; i++) {
        printf("%srn", str_list[i]);
    }
    return 0;
}

上記をコンパイルし実行すると以下のようになりました。

[root@1ef475d5fd40 tmp]# gcc ./explode.c
[root@1ef475d5fd40 tmp]# ./a.out
あいうえお
かきくけこ
さしすせそ
たちつてと
なにぬねの
はまやらわ
やいゆえよ
[root@1ef475d5fd40 tmp]#

今回は、もとの文字列に該当する文字列の先頭アドレスにNULLバイトを埋めて
分割していくという方法をとりました。
本当は無駄のない文字配列の配置にしたかったのですが、骨が折れそうだったのであきらめました。

[紹介元] PHPタグが付けられた新着投稿 – Qiita C言語でPHPとかのexplode関数を実装してみる

コメント

記事に戻る

コメントを残す