学ぶ › TypeScript
データ · 11
1文字を扱う
1文字を値として:コード、文字の計算、i 番目の文字、繰り返し。
1文字も値です。
中身は数(コード)なので、足したり引いたりできます。
下の例は c2a3z1 のように小文字1つと数字1つが交互に並ぶ文字列を2文字ずつ読み、文字とそのコード、アルファベットで次の文字、そしてその文字を数字の回数だけ繰り返した文字列を1行ずつ表示します。
s = input()for i in range(0, len(s), 2): ch = s[i] # i번째 글자 count = int(s[i + 1]) # 숫자 글자 → 수 code = ord(ch) after = chr(ord("a") + (code - ord("a") + 1) % 26) # 다음 글자(z 다음은 a) print(ch, code, after, ch * count)const s = require("fs").readFileSync(0, "utf8").trim();const a = "a".charCodeAt(0);for (let i = 0; i < s.length; i += 2) { const ch = s[i]; // i번째 글자 const count = Number(s[i + 1]); // 숫자 글자 → 수 const code = ch.charCodeAt(0); const after = String.fromCharCode(a + ((code - a + 1) % 26)); // 다음 글자(z 다음은 a) console.log(ch, code, after, ch.repeat(count));}import { readFileSync } from "node:fs";const s: string = readFileSync(0, "utf8").trim();const a: number = "a".charCodeAt(0);for (let i = 0; i < s.length; i += 2) { const ch: string = s[i]; // i번째 글자 const count: number = Number(s[i + 1]); // 숫자 글자 → 수 const code: number = ch.charCodeAt(0); const after: string = String.fromCharCode(a + ((code - a + 1) % 26)); // 다음 글자(z 다음은 a) console.log(ch, code, after, ch.repeat(count));}import java.util.Scanner; public class Main { public static void main(String[] args) { String s = new Scanner(System.in).next(); for (int i = 0; i < s.length(); i += 2) { char ch = s.charAt(i); // i번째 글자 int count = s.charAt(i + 1) - '0'; // 숫자 글자 → 수 int code = ch; char after = (char) ('a' + (ch - 'a' + 1) % 26); // 다음 글자(z 다음은 a) System.out.println(ch + " " + code + " " + after + " " + String.valueOf(ch).repeat(count)); } }}using System; class Program{ static void Main() { string s = Console.ReadLine().Trim(); for (int i = 0; i < s.Length; i += 2) { char ch = s[i]; // i번째 글자 int count = s[i + 1] - '0'; // 숫자 글자 → 수 int code = ch; char after = (char)('a' + (ch - 'a' + 1) % 26); // 다음 글자(z 다음은 a) Console.WriteLine($"{ch} {code} {after} {new string(ch, count)}"); } }}#include <iostream>#include <string> int main() { std::string s; std::cin >> s; for (size_t i = 0; i < s.size(); 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) std::cout << ch << ' ' << code << ' ' << after << ' ' << std::string(count, ch) << '\n'; }}#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;}s = コンソール.行読み().空白除去();a = 文字.コード("a");繰り返す (i = 0; i < s.長さ; i += 2){ ch = s[i]; // i번째 글자 count = s[i + 1].数に(); // 숫자 글자 → 수 code = 文字.コード(ch); after = 文字.コードから(a + (code - a + 1) % 26); // 다음 글자(z 다음은 a) コンソール.書く(ch + " " + code + " " + after + " " + ch.繰り返し(count));}c2a3z1
c 99 d cc a 97 b aaa z 122 a z
ポイント
- C・C++・Java・C# には1文字だけを入れる型
charがあり、シングルクォートで書きます('a')。
Python・JavaScript・Craykon にはその型がなく、1文字も長さ 1 の文字列です。 - 文字の計算:アルファベットのコードは順番に並んでいます(
a97、b98、…)。
だから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) |
| TypeScript | JavaScript と同じです |
| Java | char 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)(個数が先) |
| C | char ch = s[i] — C++ と同じく char は小さな整数です。printf の %c は文字として、%d はコードとして表示します。s[長さ] には終わりの印 \0 があり、その先を読むのは確認もなく未定義動作です(でたらめな値が出たり落ちたりします)。繰り返しはないのでループで表示します |
| Craykon | コードは 文字.コード(ch)、文字へは 文字.コードから(n)。数字の文字は ch.数に()。s[i] — 範囲外は「文字列には 0〜2 番しかありません」というエラー(負の番号も同じ)。繰り返しは ch.繰り返し(3) |
よくある間違い
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)。
文字に 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) と書きます。
数字の文字をそのまま数として使ったC · C++ · Java · C#
char ch = '7';
int n = ch;
printf("%d\n", n);→ 55 — 7 ではなく '7' のコードです
'0' を引きます:ch - '0' → 7。
数字の文字のコードが '0'(48)から順番に並んでいるのでうまくいきます。
言語ごとの違い
繰り返しは掛け算と間違えやすいです。
Python の
JavaScript は逆に
C++ の
順番を逆にして
繰り返しは掛け算と間違えやすいです。
Python の
"3" * 2 は 6 ではなく "33" なので、入力を数に変えずに掛けると文字列の繰り返しになります。JavaScript は逆に
"3" * 2 が 6、TypeScript はコンパイルエラー、Craykon は「* の計算は数どうしでしかできません」と言って止まります。C++ の
std::string(3, '*') は個数が先です。順番を逆にして
std::string('*', 3) と書くと、エラーなしで見当違いの 42 文字の文字列になります('*' のコードが 42)。