0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

C言語 不完全なreplace関数, split関数自作(自分用メモ)

0
Last updated at Posted at 2020-01-11

C言語を使う仕事が終わりかけなので自作関数備忘録。

split

配列ではなく、区切り文字までを元の文字列から取り除き、取得する。

これがしたい
char token[4] = {0};
char str[] = "a,,c";
getFirstToken(token, ",", str);  // token[0] = "a", str = ",c"
getFirstToken(token, ",", str);  // token[1] = "",  str = "c"
getFirstToken(token, ",", str);  // token[2] = "c",  str = ""
getFirstToken(token, ",", str);  // token[2] = "",  str = ""

標準ライブラリのstrtok_sを使っていたが、空白を飛ばしてしまうのが不都合だった(上の例でいえば、token[1]="c"になる)。

GetFirstToken

//最初のトークンを取得し、元の文字列からは消去
//Shift_JIS未対応
VOID GetFirstToken(CHAR* token, CHAR* delimiter, CHAR* string)
{
if (string[0] == '\0') {
token[0] = '\0';
return;
}
CHAR* p = strstr(string, delimiter);
if (p == string) {
    strcpy_s(string, strnlen_s(string, DATA_LINE_MAX_LENGTH), string + DELIMITER_LENGTH);
    token[0] = '\0';
    return;
}
// If Last token, make the original string empty and return.
if (p == NULL) {
    for (int i = 0; i <= strnlen_s(string, DATA_LINE_MAX_LENGTH); i++) {
        if (string[i] == '\0') {
            token[i] = '\0';
            string[0] = '\0';
            return;
        }
        token[i] = string[i];
    }
}

for (int i = 0; i < p - string; i++) {
    token[i] = string[i];
}
token[p - string] = '\0';

strcpy_s(string, strnlen_s(string, DATA_LINE_MAX_LENGTH), p + 1);
}

欠点

  • 1バイトずつチェックしているので、Shift_JISのダメ文字が含まれていると文字化けする。
    例えば、delimiterが"|"(文字コード7c)だった場合、「ポ」(83 7c), 「弓」(8b 7c), 「竹」(92 7c)などは2バイト目が区切り文字と同じになり、1バイト目と2バイト目を別々のascii文字として読むため文字化けする。ダメ。
  • strtok_sの挙動をまねようとしている割にはポインタを返していない。
  • 文字列の最後が空文字だった場合に、tokenの数が未知だと空文字なのか全トークン取得済みなのか判別できない

replace

ほとんどこの記事のまんま。http://urin.github.io/posts/2018/replace-string-by-c-lang
変数名からすべてめちゃくちゃ読みやすかった。
"\" → "\\"のように、、置換後の文字が置換前の文字を含んでいると変な感じになったので、最後にポインタをずらす処理を追加している。

replace
//2文字まで→3文字までの置換しか対応していない。数字は変えられる
CHAR* replace(CHAR str, CHAR replaced, CHAR* substitution) {
CHAR* replacedPos = str;
size_t lenReplaced = strnlen_s(replaced, 2);
size_t lenSub = strnlen_s(substitution, 3);

while ((replacedPos = strstr(replacedPos, replaced)) != NULL) {
    CHAR *lastPart = replacedPos + lenReplaced;
    memmove(replacedPos + lenSub, lastPart, strlen(lastPart) + 1);
    memcpy(replacedPos, substitution, lenSub);
    replacedPos += lenSub;
}
return str;
}
0
0
1

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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?