
C言語基礎|大文字・小文字の変換
英字だけを、きれいに統一! toupper / tolower で文字列の見た目を整えよう
大文字・小文字をそろえると、文字列が読みやすくなる
ユーザー入力やログ、ID、ファイル名みたいな文字列って、大文字と小文字が混ざりがちです。
でも「大文字に統一」「小文字に統一」できると、検索もしやすいし、比較もラクになります。
ここでは、文字列を先頭から順に走査して、英字だけを変換する方法を学びます。
ポイントは、英字以外(数字や記号)はそのままにできること。C言語標準ライブラリの toupper と tolower が、その仕事をうまくやってくれます。

変換の全体像:1文字ずつ見て、必要なら置き換える
文字列走査と変換(イメージ)

図の説明
- 文字列は配列(char の並び)なので、先頭から s[i] を順に見ていけます
- toupper / tolower の返り値を、そのまま s[i] に代入すると「その場で更新」できます
- 数字や記号は変換されずに残ります
サンプルプログラム
入力は空白を含めない想定で scanf を使います。
プロジェクト名:chap9-10-1 ソースファイル名:chap9-10-1.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
// 文字列内の英字を大文字/小文字に変換
#include <ctype.h>
#include <stdio.h>
// 文字列内の英字を大文字に変換
void str_toupper(char s[])
{
int i = 0;
while (s[i]) {
s[i] = toupper((unsigned char)s[i]);
i++;
}
}
// 文字列内の英字を小文字に変換
void str_tolower(char s[])
{
int i = 0;
while (s[i]) {
s[i] = tolower((unsigned char)s[i]);
i++;
}
}
int main(void)
{
char str[128];
printf("英字まじりの文字列を入力してください:");
scanf("%127s", str);
str_toupper(str);
printf("大文字にそろえる:%s\n", str);
str_tolower(str);
printf("小文字にそろえる:%s\n", str);
return 0;
}実行例
英字まじりの文字列を入力してください:KaTaKaNa-Box_19
大文字にそろえる:KATAKANA-BOX_19
小文字にそろえる:katakana-box_19
toupper と tolower が「安全」な理由
toupper / tolower は、英字以外を変換しません。
なので、数字や記号を壊さずに「英字だけ」を統一できます。
変換の挙動(例)
| 入力文字 | toupper の結果 | tolower の結果 | ひとこと |
|---|---|---|---|
| 'a' | 'A' | 'a' | 小文字→大文字 |
| 'Z' | 'Z' | 'z' | 大文字→小文字 |
| '7' | '7' | '7' | 数字はそのまま |
| '-' | '-' | '-' | 記号もそのまま |
表の説明
- 変換対象は基本的に半角の英字です。
- それ以外は「触らずに返す」ので、文字列の構造を保てます。
命令の書式と「何をする命令か」
while の書式と役割
- 書式
while (条件式) 文; - 何をする?
条件式が真のあいだ文を繰り返します。
今回は s[i] が 0(終端のナル文字)になるまで、文字を走査します。
代入の書式と役割
- 書式
左辺 = 右辺; - 何をする?
右辺の値を左辺に入れます。
今回は s[i] = toupper(...) の形で、変換結果を同じ場所へ上書きしています。
toupper の書式と役割
- 書式
int toupper(int c); - 何をする?
c が英小文字なら対応する英大文字に変換して返します。
英小文字でなければ、そのまま返します。
tolower の書式と役割
- 書式
int tolower(int c); - 何をする?
c が英大文字なら対応する英小文字に変換して返します。
英大文字でなければ、そのまま返します。
なぜ (unsigned char) を付けているの?
toupper / tolower は「引数に EOF か、unsigned char として表現できる値」を渡す前提で使うのが安全です。
char が負の値になり得る環境もあるので、付けておくと安心です。
変換関数に渡すときの考え方
| 渡し方 | 安全性 | 理由 |
|---|---|---|
| toupper(s[i]) | 環境によって注意 | char が負になる場合がある |
| toupper((unsigned char)s[i]) | 安全寄り | 値域が確実に正になる |
表の説明
- 日本語などマルチバイト文字は、この変換では対象外です
- 英字処理に限定して使うのが基本です
変換関数を2つ書くのが面倒なら、共通化もできる
「大文字化」と「小文字化」は構造が同じなので、関数ポインタで共通化もできます。
ただ、最初は2つに分けた方が読みやすいので、教材としては分ける形が分かりやすいです。
2つの関数が同じ形(イメージ)
str_toupper: s[i] = toupper(...)
str_tolower: s[i] = tolower(...)
どちらも「走査して上書き」
演習問題
演習9-10:文字列から数字文字を全部取り除く
文字列 s 内のすべての数字文字を除去する関数を作成せよ。
void del_digit(char s[]);
たとえば AB1C9 を受け取ったら、ABC に更新する。
解答例
プロジェクト名:chap9-10-2 ソースファイル名:chap9-10-2.c
Visual Studio でこのプログラムを実行するには、SDLチェック設定を変更しておく必要があります。
1.プロジェクト名を右クリックして、「プロパティ」をクリックします。
2.「C/C++」→「全般」→「SDLチェック」を「いいえ」に切り替えて「OK」をクリックします。
#include <stdio.h>
void del_digit(char s[])
{
int r = 0; // 読み取り位置
int w = 0; // 書き込み位置
while (s[r]) {
if (!(s[r] >= '0' && s[r] <= '9')) {
s[w] = s[r];
w++;
}
r++;
}
s[w] = 0; // 終端を付け直す
}
int main(void)
{
char s[128];
printf("文字列:");
scanf("%127s", s);
del_digit(s);
printf("数字を除去:%s\n", s);
return 0;
}解説
- 文字列を「読む位置 r」と「書く位置 w」で分けると、削除が簡単になります。
- 数字以外だけを前に詰めてコピーして、最後に 0(ナル文字)を付け直します。
- 文字列はナル文字で終わるルールなので、終端処理がとても大事です。
