
No.2ベストアンサー
- 回答日時:
> とんでもなく長くなりそうな気がします
長くなりますね。フツーだと。
その「長くなりそうだ」と言うのが「勘」で、大概そういう勘って正しいんですよ。
プログラミングに向いてる人ってのは、結局、
「その長くなりそうなブツを如何に短く書くか」
腐心出来る人なんです。短く書ければ成功、そうじゃなきゃ失敗、で、その短く書く事に挑戦する事を楽しめる人なんです。
このケースだと変換ルーティンをマトモに考えるとクソ長くなるのは一発で分かる。そして文字列を準備しておかなきゃならないのは自明です。
後者はしょうがないとしても、数値はどう英語で表現してるのか・・・・・・。実は、仮にこれが「日本語」だったら割に簡単なんだけど、「英語」ってのがクセモノなんですよ(笑)。英語の知識でルールらしきモノをでっち上げなきゃならない。
結局、キモは数値と英名の対応ルールです。これをif文だけでデッチ上げるのは大変です。
そこで、配列を使います。
全然C#は分からないんで、例によってC#に一番似てると思われるJavaを使ってみます(多分C言語よかJavaに近いでしょう)。
// ここから
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
// 一の位の配列
String[] digits = {"", "one",
"two", "three",
"four", "five",
"six", "seven",
"eight", "nine"};
// 十の位の配列
String[] tensPlace = {"", "ten",
"twenty", "thirty",
"forty", "fifty",
"sixty", "seventy",
"eighty", "ninety"};
// 十代
String[] teens = {"", "eleven",
"twelve", "thirteen",
"fourteen", "fifteen",
"sixteen", "seventeen",
"eighteen", "nineteen"};
int n = new Scanner(System.in).nextInt(); // 整数の入力
if (n < 0 || n > 99) { // 範囲外
System.out.println("エラー"); // 例外を投げても良いかも
} else if (n > 10 && n < 20) { // 十代
System.out.println(teens[n-10]);
} else if (n == 0) { // 入力が0だった場合
System.out.println("zero");
} else {
int r = n % 10; // 一の位
int q = (int)(n - r)/10; // 十の位
System.out.println(tensPlace[q] + " " + digits[r]);
}
}
}
// ここまで
結局、何がメンド臭いか、と言うと、英語での数値表現の場合、微妙に十二進法が混ざってる事なんですよね。
幸いな事にそこが絡んでるのは十代のトコロだけ。だからそこの英語表現だけをまずは括りだす、と言うのが一つ目の戦略(フランス語だったら多分僕もぶん投げてる・笑)。
あとは、十の位をどう表現してるのか、の配列と一の位の配列を準備します。
・・・まぁ、もっと細かくしてもいいけど、例えばteenが付く数値と接頭辞の関係を記述・・・とか言うのも考えられますが、現実的じゃないでしょう。我々は言語学者じゃないですし、そもそもC系の言語は元々そういうのが苦手。そういうのはシンボルを相手に自在にいろいろやれる言語(Lisp)とか、性器もとい正規表現が得意な言語(Perl)なんかに任せておけば良い。少なくとも、ルールが
1. 10 < n < 20 のnの表現
2. それ以外
で済むのなら現実的に充分実装出来る範疇です。
じゃあ、あとはどう配列を設計するか、ってだけになる。
ここでは例えば
String[] digits = {"", "one",
"two", "three",
"four", "five",
"six", "seven",
"eight", "nine"};
みたいに設計してます。
何で配列の先頭を""としてるのか、と言うと
1. 配列の要素番号と、単純には一桁の入力の数値を対応させる為
2. ゼロ項目が""だったら一桁の数値と二桁の数値で場合分けする必要がなくなる
からです。
例えば入力が3だった場合、単に配列digitsから3番目の要素を探してくれば良い。例: digits[3] ==> "three"
お忘れかもしれませんが、配列は0から数えたりするんで、一個ズレてるんですよね。
もちろん
String[] digits = {"one",
"two", "three",
"four", "five",
"six", "seven",
"eight", "nine"};
してn = 3の時、digits[n-1] => "three"でも良いんですが、コード書いてる最中に間違えるかもしれんですし、いずれにせよ、C言語由来(いや、Pascalか?)の「良くある手」です。そしてより重要なのは2番目、です。
例えば94と入力された時、我々はそれを9と4に分解せんとイケない。
そして十桁ではtensPlace[9] => "ninty"、一桁ではtensPlace[4] => "four"、合わせてninty fourと言う文字列を得られます。
でもこの入力システムを汎用的に使うとすると、一桁の数値が入力されると、例えば
3が入力される => 3は0と3に分解される
となります。十桁は0、一桁は3、と。
そうすると、十桁の配列の0番目は""なんで結果表示に影響を与えないんですよ。残りの3はdigit[3]に適用されて"three"を返してくる。つまり、単純に"three"だけになるんですね。
データ型の方にこの仕組み、つまり、0番目を""にする、と言う設計をしておかないと、場合によっては数値が10以下の場合、数値が20以上の場合、とif節を増やしてメンド臭い事になる。
その辺の影響を踏まえると各配列の第0要素は""にしておいた方が都合が良い、のです。仮に0が入力されたら、その時だけは例外として"zero"を表示させた方が結果紛れがないんですよね。
と言うわけで・・・宿題だとしたら、目的は「データの上手な設計の仕方・入門編」ってトコかな。上手く配列を設計出来たりすれば、のちのプログラムを書くのが滅茶苦茶ラクになりますよ、と。そう言った題意の問題だと思います。
丁寧な説明、ありがとうございます!
配列について覚えることができました。
短くすることに挑戦し、それを楽しむように今後も頑張ります。
No.3
- 回答日時:
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var input = Console.ReadLine();
int value;
if (!int.TryParse(input, out value))
{
Console.WriteLine("エラー");
Console.ReadLine();
return;
}
if (value < 0 || value > 99)
{
Console.WriteLine("エラー");
Console.ReadLine();
return;
}
Console.WriteLine(value.ToEnglish());
Console.ReadLine();
}
}
static class IntExtensions
{
/// <summary>
/// 与えられた99以下の数値を英語に変換します。
/// </summary>
/// <param name="value">値。</param>
/// <returns></returns>
public static string ToEnglish(this int value)
{
var onesPlace = new[] { "", "one", "two", "three", "four", "five", "six", "seven", "eight", "nine" };
var lessTwenty = new[] { "ten", "eleven", "twelve", "thirteen", "fourteen", "fifteen", "sixteen", "seventeen", "eighteen", "nineteen" };
var tensPlace = new[] { "", "", "twenty", "thirty", "forty", "fifty", "sixty", "seventy", "eighty", "ninety" };
if (value == 0)
{
return "zero";
}
if (value < 10)
{
return onesPlace[value];
}
if (value > 9 && value < 20)
{
return lessTwenty[value % 10];
}
return $"{tensPlace[value / 10]} {onesPlace[value % 10]}";
}
}
}
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 中国語 新しい中国語入力ソフトを発明しました 22 2023/02/06 07:13
- Java コンソールから所属財産を入力(単位:万円 1000~100000以内でIntegerに変換できない場 2 2022/05/31 21:32
- Visual Basic(VBA) A列にある値をB列・C列にVBAで切り出し 3 2022/04/09 19:20
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分 1 2022/07/19 17:03
- Excel(エクセル) VBAで、㉑という数値が、正しく、入力できない 2 2022/07/26 20:22
- C言語・C++・C# 至急教えてください。プログラミングの問題です。 malloc関数を使ってください!お願いします! 最 1 2022/07/21 09:28
- C言語・C++・C# 至急お願いします。プログラミングの問題です。 最初に正の整数nの入力を受け付け、次に分数の分子と分母 3 2022/07/19 17:09
- C言語・C++・C# C言語初心者 構造体 課題について 2 2023/03/10 19:48
- Excel(エクセル) 条件に合った数値の合計を表示させたい関数と条件指定の方法 3 2023/05/13 16:07
- Excel(エクセル) Excelにの以下の設定方法について教えてください! C列にデータ入力の設定をしています。(出、入を 3 2022/06/22 01:33
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
動的配列が存在(要素が有る)か...
-
IF関数でEmpty値を設定する方法。
-
EXCEL VBA で、0から?1から?
-
パソコンキーボードで時分秒を...
-
ランダムに並んでるキーボード...
-
VBでbyte配列型のインスタンス...
-
VBAで配列の計算
-
VB.net 引数で配列変数を渡す際...
-
配列プロパティをREDIMする方法...
-
C#の質問
-
VB.net(2005)での配列の要素数...
-
変数を動的に作るには?
-
For文と配列
-
MATLABで
-
五目並べのプログラムを配列と...
-
複数のテキストボックスに同じ...
-
シート上のオプションボタン、...
-
(漢和辞典)部首の配列法は?
-
[EXCEL VBA] 配列メモリの動的...
-
Javaで文字と数字が混ざったも...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
動的配列が存在(要素が有る)か...
-
IF関数でEmpty値を設定する方法。
-
パソコンキーボードで時分秒を...
-
EXCEL VBA で、0から?1から?
-
VBAで配列の計算
-
C言語 重複しない4ケタの乱数...
-
VB.net 引数で配列変数を渡す際...
-
変数を動的に作るには?
-
C#の質問
-
VBでbyte配列型のインスタンス...
-
VBで作った乱数を一度も重複さ...
-
javaプログラムについて
-
配列の要素数を超えた参照のコ...
-
For文と配列
-
複数のテキストボックスに同じ...
-
Excel VBAで配列の途中から(X)M...
-
ラジオボタンのチェックをEnter...
-
遅延バインディングを使用でき...
-
ジャグ配列とは
-
int型配列の一括初期化
おすすめ情報