tolower() / toupper()
| 対応: | C89(1989) |
|---|
英字の大文字・小文字を相互に変換する関数です。『<ctype.h>』に定義されており、大文字・小文字を区別しない文字列比較や入力の正規化によく使います。
構文
// 大文字を小文字に変換します。英字以外はそのまま返します。 // 引数: unsigned char の値(または EOF)。 // 戻り値: 変換後の文字を int で返します。 int tolower(int c); // 小文字を大文字に変換します。英字以外はそのまま返します。 int toupper(int c);
変換対象
| 入力 | tolower() | toupper() |
|---|---|---|
| 大文字(A-Z) | 対応する小文字に変換します。 | そのまま返します。 |
| 小文字(a-z) | そのまま返します。 | 対応する大文字に変換します。 |
| 数字・記号・非ASCII文字 | 変更せずそのまま返します。 | 変更せずそのまま返します。 |
サンプルコード
sample_tolower_toupper.c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
/* 文字列をすべて小文字に変換します(インプレース)。 */
void str_tolower(char *s) {
for (; *s; s++) {
*s = (char)tolower((unsigned char)*s);
}
}
/* 大文字・小文字を区別しない文字列比較です。 */
int strcasecmp_manual(const char *a, const char *b) {
while (*a && *b) {
int diff = tolower((unsigned char)*a) - tolower((unsigned char)*b);
if (diff != 0) return diff;
a++; b++;
}
return tolower((unsigned char)*a) - tolower((unsigned char)*b);
}
int main(void) {
printf("tolower('A') = %c\n", tolower('A'));
printf("toupper('z') = %c\n", toupper('z'));
printf("tolower('3') = %c\n", tolower('3')); /* 数字や記号はそのまま */
char str[] = "Hello, WORLD! 123";
str_tolower(str);
printf("小文字化: %s\n", str);
int cmp = strcasecmp_manual("Goro", "goro");
printf("\"Goro\" と \"goro\" の比較: %d\n", cmp); /* 0 = 等しい */
return 0;
}
gcc tolower_toupper.c -o tolower_toupper
./tolower_toupper
tolower('A') = a
toupper('z') = Z
tolower('3') = 3
小文字化: hello, world! 123
"Goro" と "goro" の比較: 0
コマンドを正規化して処理する
ユーザー入力をすべて大文字や小文字に統一することで、大文字・小文字の違いを吸収できます。コマンド解析やメニュー処理に使われます。
tolower_command.c
#include <stdio.h>
#include <ctype.h>
#include <string.h>
void normalize(char *s) {
for (; *s; s++) {
*s = (char)tolower((unsigned char)*s);
}
}
int main(void) {
const char *inputs[] = {"QUIT", "Quit", "quit", "EXIT", "help"};
int n = (int)(sizeof(inputs) / sizeof(inputs[0]));
for (int i = 0; i < n; i++) {
char buf[32];
strncpy(buf, inputs[i], sizeof(buf) - 1);
buf[sizeof(buf) - 1] = '\0';
normalize(buf);
if (strcmp(buf, "quit") == 0 || strcmp(buf, "exit") == 0) {
printf("'%s' → 終了コマンドです。\n", inputs[i]);
} else {
printf("'%s' → 通常コマンドです。\n", inputs[i]);
}
}
return 0;
}
gcc tolower_command.c -o tolower_command ./tolower_command 'QUIT' → 終了コマンドです。 'Quit' → 終了コマンドです。 'quit' → 終了コマンドです。 'EXIT' → 終了コマンドです。 'help' → 通常コマンドです。
よくあるミス
よくあるミス: char を直接渡す
char 型は符号付きの場合があり、ASCII 範囲外のバイト値(128〜255)を渡すと負の値になり未定義動作が発生します。必ず『(unsigned char)』にキャストしてから渡してください。
tolower_cast_ng.c
#include <stdio.h>
#include <ctype.h>
int main(void) {
/* NG: signed char の値が負になると未定義動作 */
/* char c = (char)0xE5; */ /* 日本語などのマルチバイト文字の1バイト目 */
/* tolower(c); */ /* c が負の値のとき未定義動作 */
/* OK: (unsigned char) にキャストしてから渡す */
char c = (char)0xE5;
int result = tolower((unsigned char)c);
printf("tolower(0xE5) = %d\n", result); /* ASCII 範囲外は変換されず元の値 */
/* 文字列処理でも同様にキャストが必要 */
const char *s = "Hello";
for (int i = 0; s[i]; i++) {
putchar(tolower((unsigned char)s[i]));
}
putchar('\n');
return 0;
}
gcc tolower_cast_ng.c -o tolower_cast_ng ./tolower_cast_ng tolower(0xE5) = 229 hello
概要
char 型の変数を直接 tolower() / toupper() に渡すと、符号付き char が負の値をとった場合に未定義動作が発生します。必ず『(unsigned char)c』にキャストしてから渡してください。
これらの関数はロケールの影響を受けます。デフォルト("C" ロケール)では ASCII の A-Z と a-z のみが変換対象です。アクセント付き文字など拡張文字の変換にはロケールを設定する必要があります。
文字の種類判定には『isalpha() / isdigit()』も参照してください。
記事の間違いや著作権の侵害等ございましたらお手数ですがこちらまでご連絡頂ければ幸いです。