{ }codelper

学ぶ › C

データ · 11

1文字を扱う

1文字を値として:コード、文字の計算、i 番目の文字、繰り返し。

1文字も値です。
中身は数(コード)なので、足したり引いたりできます。
下の例は c2a3z1 のように小文字1つと数字1つが交互に並ぶ文字列を2文字ずつ読み、文字とそのコード、アルファベットで次の文字、そしてその文字を数字の回数だけ繰り返した文字列を1行ずつ表示します。

#include <stdio.h>#include <string.h> int main(void) {    char s[101];    scanf("%100s", s);    int len = strlen(s);    for (int i = 0; i < len; i += 2) {        char ch = s[i];             // i번째 글자        int count = s[i + 1] - '0'; // 숫자 글자 → 수        int code = ch;        char after = 'a' + (ch - 'a' + 1) % 26; // 다음 글자(z 다음은 a)        printf("%c %d %c ", ch, code, after);        for (int k = 0; k < count; k++) putchar(ch); // 되풀이는 반복문으로        printf("\n");    }    return 0;}
stdin
c2a3z1
stdout
c 99 d cc
a 97 b aaa
z 122 a z

ポイント

  • C・C++・Java・C# には1文字だけを入れる型 char があり、シングルクォートで書きます('a')。
    Python・JavaScript・Craykon にはその型がなく、1文字も長さ 1 の文字列です。
  • 文字の計算:アルファベットのコードは順番に並んでいます(a 97、b 98、…)。
    だから ch - 'a' は a から何文字後ろか(0〜25)で、'a' + k は a から k 文字後ろの文字です。
    char のない言語では、コードに変えて計算してから文字に戻します。
  • 数字の文字は数ではありません。
    '7' のコードは 55 です。
    数の 7 がほしいときは '0' のコードを引くか('7' - '0')、数に変える関数を使います。
  • i 番目の文字は s[i] で取り出します(Java は s.charAt(i))。
    最後の文字は 長さ - 1 番です。
    その先を読むと、エラーで止まる言語、黙って undefined を返す言語、まったく確認せず何が起きるか決まっていない言語(C・C++)に分かれます。
  • 繰り返しは同じ文字列を n 回つなげます。
    "ab" を 3 回なら "ababab"、0 回なら空文字列です。
    星や線の表示をループなしで書けます。

言語ごとの書き方

Pythonコードは ord(ch)、文字へは chr(n) — 次の文字は chr(ord(ch) + 1)。
数字の文字は int(ch)。
s[i]、後ろからは s[-1]。
範囲外は IndexError。
繰り返しは ch * 3
JavaScriptコードは ch.charCodeAt(0)、文字へは String.fromCharCode(n)。
数字の文字は Number(ch)。
s[i]、後ろからは s.at(-1)。
範囲外の s[9] はエラーなしで undefined。
繰り返しは ch.repeat(3)
TypeScriptJavaScript と同じです
Javachar ch = s.charAt(i) — s[i] は使えません。
コードは int code = ch、文字へは (char) (ch + 1)。
数字の文字は ch - '0'。
範囲外は StringIndexOutOfBoundsException。
繰り返しは文字列にしかないので String.valueOf(ch).repeat(3)
C#char ch = s[i]、最後は s[^1]。
コードは int code = ch、文字へは (char)(ch + 1)。
数字の文字は ch - '0'。
範囲外は IndexOutOfRangeException。
文字の繰り返しは new string(ch, 3)
C++char ch = s[i] — char はそのまま小さな整数なので、ch + 1 や ch - '0' をそのまま書けます。
s[i] は範囲を確認しないので、長さを超える番号を読むと未定義動作です(でたらめな値が出たり落ちたりします)。
s.at(i) は確認して std::out_of_range を投げます。
文字の繰り返しは std::string(3, ch)(個数が先)
Cchar ch = s[i] — C++ と同じく char は小さな整数です。
printf の %c は文字として、%d はコードとして表示します。
s[長さ] には終わりの印 \0 があり、その先を読むのは確認もなく未定義動作です(でたらめな値が出たり落ちたりします)。
繰り返しはないのでループで表示します
Craykonコードは 文字.コード(ch)、文字へは 文字.コードから(n)。
数字の文字は ch.数に()。
s[i] — 範囲外は「文字列には 0〜2 番しかありません」というエラー(負の番号も同じ)。
繰り返しは ch.繰り返し(3)

よくある間違い

数字の文字をそのまま数として使ったC · C++ · Java · C#

char ch = '7';
int n = ch;
printf("%d\n", n);

→ 55 — 7 ではなく '7' のコードです

'0' を引きます:ch - '0' → 7。
数字の文字のコードが '0'(48)から順番に並んでいるのでうまくいきます。

文字に 1 を足して表示したら数になったJava · C# · C++

System.out.println('a' + 1);   // Java
Console.WriteLine('a' + 1);    // C#
std::cout << 'a' + 1;          // C++

→ 三つとも 98 — char に数を足すと結果は int です

文字に戻します:(char) ('a' + 1) → b。
Java・C# の char c = 'a'; c = c + 1; は同じ理由でコンパイルエラーなので、c++ か c = (char) (c + 1) と書きます。

1文字の文字列に 1 を足したPython · JavaScript · TypeScript · Craykon

print("a" + 1)

→ Python は TypeError: can only concatenate str (not "int") to str。JavaScript・TypeScript・Craykon はエラーなしで a1 — 数を後ろにつなげます

コードに変えて足し、文字に戻します:Python chr(ord("a") + 1)、JavaScript String.fromCharCode("a".charCodeAt(0) + 1)、Craykon 文字.コードから(文字.コード("a") + 1)。

言語ごとの違い
繰り返しは掛け算と間違えやすいです。
Python の "3" * 2 は 6 ではなく "33" なので、入力を数に変えずに掛けると文字列の繰り返しになります。
JavaScript は逆に "3" * 2 が 6、TypeScript はコンパイルエラー、Craykon は「* の計算は数どうしでしかできません」と言って止まります。
C++ の std::string(3, '*') は個数が先です。
順番を逆にして std::string('*', 3) と書くと、エラーなしで見当違いの 42 文字の文字列になります('*' のコードが 42)。

練習問題