C言語 文字列操作 チートシート

cheatsheet

目的別のC言語文字列操作関数のクイックリファレンス

文字列(文字の配列)を宣言し、初期化する基本的な方法です。

基本形


// 方法1: 文字配列として宣言し、文字列リテラルで初期化 (サイズは自動決定)
char str1[] = "Hello"; // {'H', 'e', 'l', 'l', 'o', '\0'} が確保される

// 方法2: サイズを指定して文字配列として宣言し、文字列リテラルで初期化
char str2[10] = "World"; // {'W', 'o', 'r', 'l', 'd', '\0', ?, ?, ?, ?} が確保される (残りは不定)

// 方法3: サイズを指定し、個々の文字で初期化 (ヌル終端を忘れずに)
char str3[6] = {'N', 'i', 'c', 'e', '!', '\0'};

// 方法4: ポインタとして宣言し、文字列リテラルを指す (リテラルは変更不可!) ⚠️
const char *str4 = "Read Only";
// str4[0] = 'W'; // これは未定義動作を引き起こすか、セグメンテーション違反になる可能性が高い
                        

注意点:

  • C言語の文字列はヌル文字 ('\0') で終端されている必要があります。
  • const char * で文字列リテラルを指す場合、その内容は変更できません。変更が必要な場合は文字配列を使用してください。
  • 配列サイズは、格納する文字列の長さ + ヌル文字(1バイト) 以上のサイズが必要です。

文字列のヌル文字 ('\0') を除く文字数を取得します。

関数 ヘッダ 説明 使用例
strlen <string.h> 与えられたC文字列の長さを計算します。ヌル文字はカウントされません。

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

int main() {
    char myString[] = "Example";
    size_t len = strlen(myString);
    printf("Length: %zu\n", len); // 出力: Length: 7
    return 0;
}
                                    
strnlen_s (C11 Annex K) / strnlen (POSIX, GNU) <string.h> 最大長の制限付きで文字列の長さを計算します。バッファオーバーランを防ぐのに役立ちます。strnlen_s は Bounds-checking interface の一部です。

#define __STDC_WANT_LIB_EXT1__ 1 // C11 Annex K を使う場合 (処理系による)
#include <string.h>
#include <stdio.h>

int main() {
    char buffer[5] = {'T', 'e', 's', 't', 'X'}; // ヌル終端されていない可能性
    size_t max_len = sizeof(buffer);
    size_t len;

#ifdef __STDC_LIB_EXT1__ // C11 Annex K が利用可能な場合
    len = strnlen_s(buffer, max_len);
    printf("Length (strnlen_s): %zu\n", len); // 出力: 5 (もしヌルがなければ最大長)
#else // POSIX/GNU strnlen を使う場合 (利用可能なら)
    len = strnlen(buffer, max_len);
    printf("Length (strnlen): %zu\n", len); // 出力: 5
#endif

    char short_str[] = "Hi";
    len = strnlen(short_str, 10); // 最大長より短い
    printf("Length (short_str): %zu\n", len); // 出力: 2

    return 0;
}
                                    

注意点: strlen はヌル文字を探して文字列を走査します。ヌル終端されていない文字列を渡すと、バッファオーバーランを引き起こし、未定義動作となります 💥。strnlenstrnlen_s は最大チェック長を指定できるため、より安全です。

ある文字列の内容を別の文字配列にコピーします。

関数 ヘッダ 説明 使用例 注意点 ⚠️
strcpy <string.h> src 文字列(ヌル文字含む)を dest にコピーします。

char source[] = "Copy me";
char destination[20];
strcpy(destination, source);
// destination は "Copy me" になる
                                    
非常に危険! dest のバッファサイズをチェックしません。srcdest より大きい場合、バッファオーバーフローが発生します。使用は避けるべきです。
strncpy <string.h> 最大 n 文字を src から dest にコピーします。

char source[] = "Long source string";
char destination[10];
strncpy(destination, source, sizeof(destination) - 1);
destination[sizeof(destination) - 1] = '\0'; // 手動でヌル終端!
// destination は "Long sour" になる
                                    
src の長さが n 以上の場合、コピー結果がヌル終端されません!手動でのヌル終端が必要です。n 文字未満の場合はヌル文字でパディングされます。扱いにくい場合があります。
strcpy_s (C11 Annex K) <string.h> strcpy の安全なバージョン。コピー先のバッファサイズ (destsz) を指定します。

#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stdio.h>

int main() {
    char source[] = "Safe copy";
    char destination[20];
    errno_t err = strcpy_s(destination, sizeof(destination), source);
    if (err == 0) {
        printf("Copied: %s\n", destination);
    } else {
        printf("strcpy_s failed: %d\n", err);
    }
    return 0;
}
                                    
C11 Annex K 準拠の処理系(例: MSVC)でのみ利用可能です。エラー処理が必要です。成功時に 0 を返します。
snprintf <stdio.h> 書式指定文字列を使って安全に文字列をコピー(生成)します。実質的なコピーにもよく使われます。

#include <stdio.h>

char source[] = "Format copy";
char destination[20];
int result = snprintf(destination, sizeof(destination), "%s", source);
// result は書き込もうとした文字数 (ヌル文字除く)
if (result >= 0 && result < sizeof(destination)) {
    printf("Copied: %s\n", destination);
} else {
    printf("snprintf failed or truncated.\n");
}
                                    
推奨される安全な方法の一つです。戻り値で書き込みが成功したか、切り詰められたかを確認できます。

推奨: 可能な限り snprintfstrcpy_s (利用可能なら) を使用し、strcpy の使用は避けてください。

ある文字列の末尾に別の文字列を追加します。

関数 ヘッダ 説明 使用例 注意点 ⚠️
strcat <string.h> src 文字列を dest 文字列の末尾に追加します。dest の元のヌル文字は上書きされます。

char destination[50] = "Hello, "; // 十分なサイズが必要
char source[] = "World!";
strcat(destination, source);
// destination は "Hello, World!" になる
                                    
非常に危険! strcpy 同様、dest のバッファサイズをチェックしません。連結後の文字列が dest の容量を超えるとバッファオーバーフローが発生します。使用は避けるべきです。
strncat <string.h> 最大 n 文字を src から dest の末尾に追加します。常にヌル終端されます。

char destination[20] = "First: ";
char source[] = "Second part is long";
// 残りスペースを計算: sizeof(destination) - strlen(destination) - 1
size_t remaining_space = sizeof(destination) - strlen(destination) - 1;
strncat(destination, source, remaining_space);
// destination は "First: Second part " になる (切り詰められる)
                                    
n は追加する最大文字数であり、dest の合計サイズではありません。残りのバッファサイズを正確に計算する必要があります。計算ミスがあると危険です。
strcat_s (C11 Annex K) <string.h> strcat の安全なバージョン。連結先のバッファサイズ (destsz) を指定します。

#define __STDC_WANT_LIB_EXT1__ 1
#include <string.h>
#include <stdio.h>

int main() {
    char destination[20] = "Combine ";
    char source[] = "Strings";
    errno_t err = strcat_s(destination, sizeof(destination), source);
    if (err == 0) {
        printf("Concatenated: %s\n", destination);
    } else {
        printf("strcat_s failed: %d\n", err);
    }
    return 0;
}
                                    
C11 Annex K 準拠の処理系でのみ利用可能です。エラー処理が必要です。
snprintf (応用) <stdio.h> 既存の文字列の末尾に追記する形でも利用できます。追記開始位置と残りサイズを管理する必要があります。

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

char destination[50] = "Initial ";
char part1[] = "part 1, ";
char part2[] = "part 2.";

size_t current_len = strlen(destination);
// part1 を追記
int result1 = snprintf(destination + current_len, sizeof(destination) - current_len, "%s", part1);

if (result1 >= 0 && (current_len + result1) < sizeof(destination)) {
    current_len += result1;
    // part2 を追記
    int result2 = snprintf(destination + current_len, sizeof(destination) - current_len, "%s", part2);
    if (result2 >= 0 && (current_len + result2) < sizeof(destination)) {
         printf("Final: %s\n", destination); // Final: Initial part 1, part 2.
    } else {
         printf("snprintf (part2) failed or truncated.\n");
    }
} else {
    printf("snprintf (part1) failed or truncated.\n");
}
                                    
書き込み開始位置と残りサイズの計算がやや複雑ですが、非常に安全で柔軟な方法です。

推奨: snprintf を応用するか、利用可能であれば strcat_s を使用してください。strcat は避けるべきです。

2つの文字列が等しいか、辞書順でどちらが先かを比較します。

関数 ヘッダ 説明 戻り値 使用例
strcmp <string.h> s1s2 を辞書順で比較します。
  • s1 < s2 の場合: 負の値
  • s1 == s2 の場合: 0
  • s1 > s2 の場合: 正の値

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

int main() {
    char strA[] = "apple";
    char strB[] = "banana";
    char strC[] = "apple";

    if (strcmp(strA, strB) < 0) {
        printf("%s comes before %s\n", strA, strB);
    }
    if (strcmp(strA, strC) == 0) {
        printf("%s and %s are equal\n", strA, strC);
    }
    if (strcmp(strB, strA) > 0) {
        printf("%s comes after %s\n", strB, strA);
    }
    return 0;
}
                                    
strncmp <string.h> 最大 n 文字まで、s1s2 を辞書順で比較します。 strcmp と同様。

char str1[] = "test123";
char str2[] = "test456";
if (strncmp(str1, str2, 4) == 0) {
    // 先頭4文字 ("test") が一致するので、ここが実行される
    printf("First 4 characters are equal.\n");
}
                                    
strcasecmp (POSIX, GNU) / _stricmp (Windows) <strings.h> (POSIX) / <string.h> (Windows) strcmp と同様ですが、大文字と小文字を区別せずに比較します。 strcmp と同様。

// POSIX の場合
#include <strings.h>
#include <stdio.h>

int main() {
    char s1[] = "Apple";
    char s2[] = "apple";
    if (strcasecmp(s1, s2) == 0) {
        printf("'%s' and '%s' are equal (case-insensitive).\n", s1, s2);
    }
    return 0;
}
// Windows の場合 _stricmp を使用
                                    
strncasecmp (POSIX, GNU) / _strnicmp (Windows) <strings.h> (POSIX) / <string.h> (Windows) strncmp と同様ですが、大文字と小文字を区別せずに比較します。 strcmp と同様。

// POSIX の場合
#include <strings.h>
#include <stdio.h>
int main() {
    char s1[] = "PREFIX_Value1";
    char s2[] = "prefix_Value2";
    if (strncasecmp(s1, s2, 7) == 0) { // "PREFIX_" と "prefix_" を比較
         printf("First 7 chars are equal (case-insensitive).\n");
    }
    return 0;
}
// Windows の場合 _strnicmp を使用
                                    

注意点: 比較関数は文字列の内容が等しいかどうかをチェックします。ポインタの値 (アドレス) が等しいかどうかを比較するには == を使用しますが、これは通常、文字列比較の目的ではありません。

文字列内から特定の文字または部分文字列を探します。

関数 ヘッダ 説明 戻り値 使用例
strchr <string.h> 文字列 s 内で文字 c が最初に現れる位置へのポインタを返します。 見つかった場合はその文字へのポインタ。見つからない場合は NULL

char str[] = "Find the first 'f'";
char *found = strchr(str, 'f');
if (found != NULL) {
    printf("Found 'f' at index: %ld\n", found - str); // 9
}
                                    
strrchr <string.h> 文字列 s 内で文字 c が最後に現れる位置へのポインタを返します。 見つかった場合はその文字へのポインタ。見つからない場合は NULL

char str[] = "Find the last 'f'";
char *found = strrchr(str, 'f');
if (found != NULL) {
    printf("Found last 'f' at index: %ld\n", found - str); // 14
}
                                    
strstr <string.h> 文字列 haystack 内で部分文字列 needle が最初に現れる位置へのポインタを返します。 見つかった場合は部分文字列の開始位置へのポインタ。見つからない場合は NULL

char haystack[] = "This is the haystack string.";
char needle[] = "haystack";
char *found = strstr(haystack, needle);
if (found != NULL) {
    printf("Found '%s' starting at index: %ld\n", needle, found - haystack); // 12
}
                                    
strpbrk <string.h> 文字列 s1 内で、文字列 s2 に含まれるいずれかの文字が最初に現れる位置へのポインタを返します。 見つかった場合はその文字へのポインタ。見つからない場合は NULL

char str[] = "Look for vowels here.";
char vowels[] = "aeiouAEIOU";
char *found = strpbrk(str, vowels);
if (found != NULL) {
    // 最初の母音 'o' が見つかる
    printf("First vowel '%c' found at index: %ld\n", *found, found - str); // 1
}
                                    
strspn <string.h> 文字列 s1 の先頭から、文字セット s2 に含まれる文字のみで構成される部分の長さを返します。 条件に一致する先頭部分文字列の長さ (size_t)。

char str[] = "12345ABCDE";
char digits[] = "0123456789";
size_t len = strspn(str, digits);
printf("Length of initial digit segment: %zu\n", len); // 5 ("12345")
                                    
strcspn <string.h> 文字列 s1 の先頭から、文字セット s2 に含まれる文字が最初に現れるまでの長さを返します。 条件に一致する先頭部分文字列の長さ (size_t)。

char str[] = "Hello World!";
char break_chars[] = " W"; // スペースまたは 'W'
size_t len = strcspn(str, break_chars);
printf("Length before space or 'W': %zu\n", len); // 5 ("Hello")
                                    

文字列を区切り文字に基づいて部分文字列(トークン)に分割します。

関数 ヘッダ 説明 使用例 注意点 ⚠️
strtok <string.h> 文字列 str を区切り文字 delim で分割します。連続する呼び出しで次のトークンを取得します。

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

int main() {
    char str[] = "Split,this,string by commas.";
    char delim[] = ", ."; // カンマ、スペース、ピリオドで分割
    char *token;

    // 最初の呼び出しでは、分割対象の文字列を渡す
    token = strtok(str, delim);

    while (token != NULL) {
        printf("Token: %s\n", token);
        // 2回目以降の呼び出しでは NULL を渡す
        token = strtok(NULL, delim);
    }
    // 出力:
    // Token: Split
    // Token: this
    // Token: string
    // Token: by
    // Token: commas
    return 0;
}
                                    
  • 元の文字列を変更します! 区切り文字をヌル文字で置き換えます。元の文字列を保持したい場合はコピーしてから使用してください。
  • 内部で静的状態を保持するため、スレッドセーフではありません
  • 複数の区切り文字が連続している場合、それらは1つの区切りとして扱われ、空のトークンは生成されません。
strtok_r (POSIX) / strtok_s (C11 Annex K, Windows) <string.h> strtok のリエントラント(再入可能)/ スレッドセーフなバージョン。内部状態を引数 saveptr (または context) で管理します。

#define _POSIX_C_SOURCE 200809L // strtok_r を使う場合 (glibc)
// または #define __STDC_WANT_LIB_EXT1__ 1 (strtok_s)
#include <string.h>
#include <stdio.h>

int main() {
    char str[] = "Thread-safe;tokenization example.";
    char delim[] = "; .";
    char *saveptr; // POSIX strtok_r
    // errno_t context; // C11 strtok_s (使い方が少し異なる)
    char *token;

    token = strtok_r(str, delim, &saveptr); // POSIX
    // token = strtok_s(str, &context, delim); // C11 / Windows (引数順序注意)

    while (token != NULL) {
        printf("Token: %s\n", token);
        token = strtok_r(NULL, delim, &saveptr); // POSIX
        // token = strtok_s(NULL, &context, delim); // C11 / Windows
    }
    // 出力:
    // Token: Thread-safe
    // Token: tokenization
    // Token: example
    return 0;
}
                                    
  • 元の文字列を変更する点は strtok と同じです。
  • スレッドセーフなので、マルチスレッド環境や再帰呼び出しでも安全に使用できます。
  • strtok_r (POSIX) と strtok_s (C11/Windows) では引数の順序や最後の引数の型が異なる場合があるので注意が必要です。

推奨: スレッドセーフ性が求められる場合や、より現代的なコードでは strtok_r / strtok_s を使用してください。ただし、どちらも元の文字列を変更する点には注意が必要です。

文字列と数値の相互変換や、大文字/小文字の変換などを行います。

8.1. 文字列から数値への変換

関数 ヘッダ 説明 使用例 注意点
atoi <stdlib.h> 文字列を int 型に変換します。

int val = atoi("12345"); // val は 12345
int invalid = atoi("abc"); // invalid は 0 (エラー)
int partial = atoi("99 bottles"); // partial は 99
                                    
エラーチェック機能がありません。変換できない場合やオーバーフローした場合の挙動が未定義または特定の値 (多くは0) を返すため、エラーと有効な値の区別が難しいです。非推奨。
atol <stdlib.h> 文字列を long 型に変換します。 long val = atol("987654321"); atoi と同様の問題点があります。非推奨。
atof <stdlib.h> 文字列を double 型に変換します。 double val = atof("3.14159"); atoi と同様の問題点があります。非推奨。
strtol <stdlib.h> 文字列を long 型に変換します。基数指定とエラーチェックが可能です。

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

int main() {
    char str[] = "  -1234 Leaves this part";
    char *endptr;
    long val;

    errno = 0; // errno をクリア
    val = strtol(str, &endptr, 10); // 10進数で変換

    if (errno == ERANGE) {
        printf("Error: Number out of range.\n");
    } else if (endptr == str) {
        printf("Error: No digits were found.\n");
    } else if (*endptr != '\0') {
        printf("Converted value: %ld\n", val); // -1234
        printf("Remaining string: '%s'\n", endptr); // " Leaves this part"
    } else {
        printf("Converted successfully: %ld\n", val);
    }
    return 0;
}
                                    
推奨。 エラーハンドリング (errno, endptr) が可能です。基数 (2〜36) を指定できます。
strtoul <stdlib.h> 文字列を unsigned long 型に変換します。 unsigned long val = strtoul("FF", NULL, 16); // val は 255 strtol と同様にエラーハンドリング可能。推奨。
strtoll (C99) <stdlib.h> 文字列を long long 型に変換します。 long long val = strtoll("1234567890123", NULL, 10); strtol と同様にエラーハンドリング可能。推奨。
strtoull (C99) <stdlib.h> 文字列を unsigned long long 型に変換します。 unsigned long long val = strtoull("FFFFFFFFFFFFFFFF", NULL, 16); strtol と同様にエラーハンドリング可能。推奨。
strtod <stdlib.h> 文字列を double 型に変換します。エラーチェックが可能です。

char str[] = "3.14159 is pi";
char *endptr;
double val = strtod(str, &endptr);
// エラーチェック (errno, endptr) は strtol と同様
printf("Value: %f, Remaining: '%s'\n", val, endptr);
                                    
strtol と同様にエラーハンドリング可能。推奨。
strtof (C99) <stdlib.h> 文字列を float 型に変換します。 float val = strtof("1.618", NULL); strtod と同様。推奨。
strtold (C99) <stdlib.h> 文字列を long double 型に変換します。 long double val = strtold("2.718281828459045", NULL); strtod と同様。推奨。

8.2. 数値から文字列への変換

関数 ヘッダ 説明 使用例 注意点
sprintf <stdio.h> 書式指定に従って、数値を文字列に変換し、指定されたバッファに書き込みます。

char buffer[50];
int num = 123;
double pi = 3.14;
sprintf(buffer, "Int: %d, Double: %.2f", num, pi);
// buffer は "Int: 123, Double: 3.14"
                                    
危険! バッファオーバーフローの可能性があります。書き込み先のバッファサイズをチェックしません。使用は避けるべきです。
snprintf <stdio.h> sprintf の安全なバージョン。書き込む最大文字数 (バッファサイズ) を指定します。

char buffer[20];
long long big_num = 9876543210LL;
int written = snprintf(buffer, sizeof(buffer), "Num: %lld", big_num);
// written は書き込もうとした文字数 (ヌル文字除く)
if (written >= 0 && written < sizeof(buffer)) {
    printf("Success: %s\n", buffer); // "Num: 9876543210"
} else {
    printf("Failed or truncated.\n"); // バッファが小さい場合
}
                                    
推奨。 バッファオーバーフローを防ぎます。戻り値で成功/失敗/切り詰めを確認できます。

8.3. 大文字/小文字変換

関数 ヘッダ 説明 使用例 注意点
tolower <ctype.h> 文字を小文字に変換します。引数は int です。 char lower_c = tolower('A'); // 'a' 文字単位の変換です。文字列全体を変換するにはループが必要です。
toupper <ctype.h> 文字を大文字に変換します。引数は int です。 char upper_c = toupper('a'); // 'A' 文字単位の変換です。文字列全体を変換するにはループが必要です。
ループによる変換 N/A 文字列全体を大文字または小文字に変換します。

#include <ctype.h>
#include <string.h>

void string_to_lower(char *str) {
    for (int i = 0; str[i]; i++) {
        str[i] = tolower((unsigned char)str[i]);
    }
}

void string_to_upper(char *str) {
    for (int i = 0; str[i]; i++) {
        str[i] = toupper((unsigned char)str[i]);
    }
}

int main() {
    char my_str[] = "MixED CaSe";
    string_to_lower(my_str); // "mixed case"
    // string_to_upper(my_str); // "MIXED CASE"
    return 0;
}
                                    
tolower/toupper に渡す前に unsigned char にキャストするのが安全です(特に負の char 値を扱う場合)。元の文字列を変更します。

string.h には、文字列だけでなく、任意のメモリブロックを操作する関数も含まれています。これらはヌル文字を特別扱いしないため、バイナリデータや途中にヌル文字を含む可能性のあるデータの扱いに便利です。

関数 ヘッダ 説明 使用例 対応する文字列関数
memcpy <string.h> n バイトのメモリを src から dest にコピーします。コピー元とコピー先がオーバーラップしてはいけません。

char src[] = {'A', '\0', 'B', 'C'};
char dest[4];
memcpy(dest, src, sizeof(src));
// dest は {'A', '\0', 'B', 'C'}
                                    
strcpy, strncpy (ヌル終端なし)
memmove <string.h> n バイトのメモリを src から dest にコピーします。コピー元とコピー先がオーバーラップしていても安全に動作します。

char buf[] = "abcdefgh";
// buf+2 の位置に buf から 4 バイトコピー ("abcd")
memmove(buf + 2, buf, 4);
// buf は "ababcdgh" になる
                                    
オーバーラップを考慮する場合の strcpy, strncpy
memcmp <string.h> 最初の n バイトについて、メモリブロック s1s2 を比較します。

char b1[] = {1, 2, 3, 4};
char b2[] = {1, 2, 5, 4};
int result = memcmp(b1, b2, 4); // result は負の値 (3 < 5)
int result2 = memcmp(b1, b2, 2); // result2 は 0
                                    
strcmp, strncmp
memchr <string.h> メモリブロック s の最初の n バイトの中から、文字 c (int として渡されるが unsigned char として扱われる) を検索します。

char data[] = {0, 10, 20, 0, 30};
void *found = memchr(data, 0, sizeof(data));
if (found != NULL) {
    // 最初の 0 が見つかる (インデックス 0)
    printf("Found 0 at index: %ld\n", (char*)found - data);
}
                                    
strchr
memset <string.h> メモリブロック s の最初の n バイトを、文字 c (int として渡されるが unsigned char として扱われる) で埋めます。

char buffer[10];
memset(buffer, 0, sizeof(buffer)); // バッファをゼロクリア
memset(buffer, 'A', 5); // 先頭5バイトを 'A' で埋める
// buffer は {'A','A','A','A','A', 0, 0, 0, 0, 0}
                                    
特定の文字での初期化 (例: ゼロクリア)

使い分け: 文字列として扱い、ヌル終端が保証されている場合は文字列関数 (strcpy, strcmp など) を使います。バイナリデータ、固定長データ、ヌル文字を含む可能性のあるデータ、またはパフォーマンスが非常に重要な場合はメモリ関数 (memcpy, memcmp など) を使います。オーバーラップの可能性がある場合は memmove を使用します。

日本語のようなマルチバイト文字や、Unicode (UTF-16/UTF-32) を扱うための関数です。wchar.hstdlib.h などに含まれます。

10.1. ワイド文字 (wchar_t) 操作

wchar_t 型 (通常 UTF-16 または UTF-32) の文字列を操作します。関数名は多くの場合、対応する char 関数の前に wcs が付きます。

ワイド文字関数 対応するchar関数 ヘッダ 説明
wcslenstrlen<wchar.h>ワイド文字列の長さを取得
wcscpystrcpy<wchar.h>ワイド文字列をコピー (危険 ⚠️)
wcsncpystrncpy<wchar.h>最大n文字のワイド文字列をコピー (ヌル終端注意)
wcscpy_sstrcpy_s<wchar.h>安全なワイド文字列コピー (C11 Annex K)
wcscatstrcat<wchar.h>ワイド文字列を連結 (危険 ⚠️)
wcsncatstrncat<wchar.h>最大n文字のワイド文字列を連結
wcscat_sstrcat_s<wchar.h>安全なワイド文字列連結 (C11 Annex K)
wcscmpstrcmp<wchar.h>ワイド文字列を比較
wcsncmpstrncmp<wchar.h>最大n文字のワイド文字列を比較
wcschrstrchr<wchar.h>ワイド文字列からワイド文字を検索 (前方)
wcsrchrstrrchr<wchar.h>ワイド文字列からワイド文字を検索 (後方)
wcsstrstrstr<wchar.h>ワイド文字列から部分ワイド文字列を検索
wcstokstrtok<wchar.h>ワイド文字列をトークン化 (非スレッドセーフ, 元文字列変更)
wcstok_sstrtok_s<wchar.h>安全なワイド文字列トークン化 (C11 Annex K)
swprintfsprintf<wchar.h>書式付きでワイド文字列を生成 (サイズ指定版もあるが注意)
swprintf (サイズ指定版) / snwprintf (非標準)snprintf<wchar.h>安全な書式付きワイド文字列生成 (標準では `swprintf` がサイズ指定可能)
wcstol, wcstoul, wcstoll, wcstoull, wcstod, wcstof, wcstoldstrtol<wchar.h>ワイド文字列を数値に変換

#include <wchar.h>
#include <locale.h> // ロケール設定に必要
#include <stdio.h>

int main() {
    setlocale(LC_ALL, ""); // システムのデフォルトロケールを設定

    wchar_t wstr[] = L"これはワイド文字列です。"; // L プレフィックス
    size_t len = wcslen(wstr);

    // ワイド文字を出力するには printf 系ではなく wprintf 系を使う
    wprintf(L"文字列: %ls\n", wstr);
    wprintf(L"長さ: %zu 文字\n", len);

    wchar_t copy[50];
    // 安全なコピー (例: swprintf)
    int result = swprintf(copy, sizeof(copy)/sizeof(wchar_t), L"コピー: %ls", wstr);
    if (result > 0) {
        wprintf(L"%ls\n", copy);
    }

    return 0;
}
                

10.2. マルチバイト文字 ⇔ ワイド文字 変換

システムの現在のロケール設定に基づいて、マルチバイト文字 (char 配列、例: UTF-8, Shift_JIS) とワイド文字 (wchar_t 配列) を相互に変換します。

関数 ヘッダ 説明 使用例 注意点
mbtowc <stdlib.h> 1文字のマルチバイト文字をワイド文字に変換します。

#include <stdlib.h>
#include <locale.h>
#include <stdio.h>
#include <wchar.h>

int main() {
    setlocale(LC_ALL, "");
    const char* mb_char = "あ"; // UTF-8環境なら3バイト
    wchar_t wc;
    int len = mbtowc(&wc, mb_char, MB_CUR_MAX);
    if (len > 0) {
        wprintf(L"Converted: %lc (%d bytes)\n", wc, len);
    }
    return 0;
}
                                    
1文字ずつ変換する必要があります。状態を持つ場合があり、スレッドセーフではありません。
wctomb <stdlib.h> 1文字のワイド文字をマルチバイト文字に変換します。

char mb_buf[MB_CUR_MAX];
wchar_t wc = L'あ';
int len = wctomb(mb_buf, wc);
if (len > 0) {
    printf("Converted: ");
    fwrite(mb_buf, 1, len, stdout); // バイナリとして出力
    printf(" (%d bytes)\n", len);
}
                                     
状態を持つ場合があり、スレッドセーフではありません。出力バッファサイズに注意。
mbstowcs <stdlib.h> マルチバイト文字列をワイド文字列に変換します。

const char *mb_str = "マルチバイト文字列";
wchar_t wc_buf[50];
size_t converted_len = mbstowcs(wc_buf, mb_str, sizeof(wc_buf)/sizeof(wchar_t));
if (converted_len != (size_t)-1) {
    wc_buf[converted_len] = L'\0'; // 必要ならヌル終端
    wprintf(L"Converted string: %ls\n", wc_buf);
}
                                    
変換する最大文字数を指定できます。ロケール依存です。
wcstombs <stdlib.h> ワイド文字列をマルチバイト文字列に変換します。

wchar_t wc_str[] = L"ワイド文字列";
char mb_buf[100];
size_t converted_bytes = wcstombs(mb_buf, wc_str, sizeof(mb_buf));
if (converted_bytes != (size_t)-1) {
    mb_buf[converted_bytes] = '\0'; // 必要ならヌル終端
    printf("Converted string: %s\n", mb_buf);
}
                                    
変換する最大バイト数を指定できます。ロケール依存です。
mbrtowc (C99) <wchar.h> mbtowc のリエントラント版。変換状態を引数で管理します。 より複雑な状態管理が必要な場合に使用。 スレッドセーフ。状態 (mbstate_t) を明示的に扱います。
wcrtomb (C99) <wchar.h> wctomb のリエントラント版。変換状態を引数で管理します。 より複雑な状態管理が必要な場合に使用。 スレッドセーフ。状態 (mbstate_t) を明示的に扱います。
mbsrtowcs (C99) <wchar.h> mbstowcs のリエントラント版。変換状態を引数で管理します。 より複雑な状態管理が必要な場合に使用。 スレッドセーフ。状態 (mbstate_t) を明示的に扱います。
wcsrtombs (C99) <wchar.h> wcstombs のリエントラント版。変換状態を引数で管理します。 より複雑な状態管理が必要な場合に使用。 スレッドセーフ。状態 (mbstate_t) を明示的に扱います。

重要: これらの変換関数は、setlocale(LC_CTYPE, "...") で設定された現在のロケールに強く依存します。UTF-8 環境と Shift_JIS 環境では結果が異なります。特定のエンコーディング (例: UTF-8) を確実に扱いたい場合は、ロケールに依存しないライブラリ (例: ICU – International Components for Unicode) の使用を検討してください。

コメント

タイトルとURLをコピーしました