質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

3回答

631閲覧

与えられた数値に対して文字列を返す

Merrifield

総合スコア31

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2020/09/04 16:06

編集2020/09/04 22:21
0 = sıfır 1 = bir 2 = iki 3 = üç 4 = dört 5 = beş 6 = altı 7 = yedi 8 = sekiz 9 = dokuz 10 = on 20 = yirmi 30 = otuz 40 = kırk 50 = elli 60 = altmış 70 = yetmiş 80 = seksen 90 = doksan

0~99までの数値が与えられそれに応じて、下の例のようにに文字列を返す関数を作成しています。これはcodewars内での問題です。https://www.codewars.com/kata/5ebd53ea50d0680031190b96/train/c

1 --> "bir" 13 --> "on üç" 27 --> "yirmi yedi" 38 --> "otuz sekiz" 77 --> "yetmiş yedi" 94 --> "doksan dört"

下にコードを示します。10が与えられたときに、onではなくyirmiを返してしまうのですが、どこが問題なのか指摘して頂けないでしょうか?また、エラーに関係なく、コードの改善点だったり、より効率の良い書き方などがあれば教えていただければありがたいです。

c

1#include <stdlib.h>//malloc 2#include <string.h>//strcpy 3#include <stdio.h>//sprintf 4 5char* getTurkishNumber(unsigned int n) 6{ 7 char* string = malloc(12); 8 char* base = string; 9 char unit[10][7] = { 10 "sıfır", 11 "bir", 12 "iki", 13 "üç", 14 "dört", 15 "beş", 16 "altı", 17 "yedi", 18 "sekiz", 19 "dokuz", 20 }; 21 char tens[9][8] = { 22 "on", 23 "yirmi", 24 "otuz", 25 "kırk", 26 "elli", 27 "altmış", 28 "yetmiş", 29 "seksen", 30 "doksan", 31 }; 32 int te = n /10, un = n % 10; 33 34 if(te == 0) 35 { 36 strcpy(string, &unit[un - 1][7]); 37 38 return base; 39 } 40 41 if(un == 0 && (te == 1 || te == 2 || te == 3 || te == 4 || te == 5 || te == 6 || 42 te == 7 || te == 8 || te == 9 ) ) 43 { 44 strcpy(string, &tens[te -2][8]); 45 46 return base; 47 } 48 49 50 sprintf(string,"%s %s",tens[te - 1], unit[un - 1]); 51 52 return base; 53 54 55} 56 } 57 58 sprintf(string,"%s %s",tens[te - 1], unit[un - 1]); 59 60 return base; 61 62 63}

テスト用コード

c

1#include <criterion/criterion.h> 2#include <stdlib.h> 3#include <string.h> 4#include <memory.h> 5void Tester(unsigned int n, const char* expected); 6 7Test(Turkish_Numbers, should_pass_all_the_tests_provided) 8{ 9 Tester(1,"bir"); 10 Tester(10,"on"); 11 Tester(26,"yirmi altı"); 12} 13

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答3

0

"sıfır" は 7バイトなので、char unit[10][7] に入れると、
文字列終端の '\0' が付きません。

"altmış" は 8バイトなので、char tens[9][8] に入れると、
文字列終端の '\0' が付きません。

char unit[10][7]; と宣言すると、
その配列の要素を unit[i][j] で参照するとき、
i は 0~9、j は 0~6 でなければなりません。
&unit[un - 1][7] だと、un - 1 が -1 になることがあります。
&tens[te -2][8] だと、te - 2 が -1 になることがあります。

69 は "altmış dokuz" ですが、これは 15バイトです。
char *string = malloc(12); では足りません。

質問のコードはコンパイルエラーになります。
テスト用の main も書いてください。

C

1#include <stdlib.h> // malloc, free 2#include <string.h> // strdup 3#include <stdio.h> // sprintf, puts 4 5char *getTurkishNumber(unsigned int n) 6{ 7 static const char *unit[10] = { 8 "sıfır", "bir", "iki", "üç", "dört", 9 "beş", "altı", "yedi", "sekiz", "dokuz", 10 }; 11 static const char *tens[9] = { 12 "on", "yirmi", "otuz", "kırk", "elli", 13 "altmış", "yetmiş", "seksen", "doksan", 14 }; 15 int te = n / 10, un = n % 10; 16 if (te == 0) return strdup(unit[un]); 17 if (un == 0) return strdup(tens[te-1]); 18 char *str = malloc(strlen(tens[te-1]) + strlen(unit[un]) + 2); 19 sprintf(str, "%s %s", tens[te-1], unit[un]); 20 return str; 21} 22 23int main(void) 24{ 25 unsigned int n; 26 while (printf(">> "), scanf("%u", &n) == 1) { 27 char *p = getTurkishNumber(n); 28 puts(p); 29 free(p); 30 } 31}

投稿2020/09/04 18:57

編集2020/09/04 20:19
kazuma-s

総合スコア8224

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mjk

2020/09/04 19:42

なるほど。配列に入れてるはずなのに何故か添字指定してもズレるので違和感があったのですがそういう理屈だったのですね。勉強になります。
mjk

2020/09/04 20:10

ちょっと理解出来ない点があるので別件として質問させて頂きます。
Merrifield

2020/09/04 22:24

sıfırはんなぜ7バイトになるのでしょうか?5バイトだと思っていたのですが
maisumakun

2020/09/04 22:33

> sıfırはんなぜ7バイトになるのでしょうか? ıはASCII外の文字です。UTF-8では2バイトになります。
Merrifield

2020/09/04 22:36

"ı"はよく見たらiとは違う文字ですね。アスキーコード以外の文字を今まであまり意識していなかったです。教えていただいてありがとうございます。
guest

0

ベストアンサー

何か無駄に難しくしているような感じが。
たんに、2つ並べて出すだけであれば、こんなんで良いのでは。

C

1#include <stdlib.h>//malloc 2#include <string.h>//strcpy 3#include <stdio.h>//sprintf 4 5char* getTurkishNumber(unsigned int n) 6{ 7 char* string = malloc(14); 8 char unit[10][7] = { 9 "sıfır", 10 "bir", 11 "iki", 12 "üç", 13 "dört", 14 "beş", 15 "altı", 16 "yedi", 17 "sekiz", 18 "dokuz", 19 }; 20 char tens[10][8] = { 21 "", 22 "on", 23 "yirmi", 24 "otuz", 25 "kırk", 26 "elli", 27 "altmış", 28 "yetmiş", 29 "seksen", 30 "doksan", 31 }; 32 int te = n /10 %10, un = n % 10; 33 34 if(te == 0) 35 { 36 strcpy(string, unit[un]); 37 38 return string; 39 } 40 41 if(un == 0) 42 { 43 strcpy(string, tens[te]); 44 45 return string; 46 } 47 48 sprintf(string,"%s %s",tens[te],unit[un]); 49 50 return string; 51}

ズレるのが気持ち悪いので、char tens[10][8] = {"","on",にしたけど、
元のままがよいなら、tens[te]を全部tens[te-1]に。


もう少しいじるなら

C

1#include <stdlib.h>//malloc 2#include <string.h>//strcpy 3#include <stdio.h>//sprintf 4 5char* getTurkishNumber(unsigned int n) 6{ 7 char *string; 8 char *unit[10] = { 9 "sıfır", 10 "bir", 11 "iki", 12 "üç", 13 "dört", 14 "beş", 15 "altı", 16 "yedi", 17 "sekiz", 18 "dokuz", 19 }; 20 char *tens[10] = { 21 "", 22 "on", 23 "yirmi", 24 "otuz", 25 "kırk", 26 "elli", 27 "altmış", 28 "yetmiş", 29 "seksen", 30 "doksan", 31 }; 32 int te = n /10 %10, un = n % 10; 33 34 if(te == 0) 35 { 36 string = malloc(strlen(unit[un])+1); 37 strcpy(string, unit[un]); 38 39 return string; 40 } 41 42 if(un == 0) 43 { 44 string = malloc(strlen(tens[te])+1); 45 strcpy(string, tens[te]); 46 47 return string; 48 } 49 50 string = malloc(strlen(tens[te])+1+strlen(unit[un])+1); 51 sprintf(string,"%s %s",tens[te],unit[un]); 52 53 return string; 54}

とか。

投稿2020/09/04 17:33

編集2020/09/04 17:57
amiya

総合スコア1218

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Merrifield

2020/09/04 22:32

回答ありがとうございます。配列のポインタの宣言だったり、if文書き方だったり、こちらのほうが分かりやすいですね。
guest

0

※単語はそのままだと他国語の文字コード系のエラーが出たので数字で置き換えました。
元のコードの原型はありませんがロジックだけでも参考になればと思います。

C

1#include <stdio.h> 2 3void func(int n) { 4 const char unit[10][3] = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"}; 5 const char tens[9][4] = {"10", "20", "30", "40", "50", 6 "60", "70", "80", "90"}; 7 if (n / 10) { 8 if (n % 10) { 9 printf("%02d %s %s\n", n, &tens[(n / 10)], &unit[(n % 10)]); 10 } else { 11 printf("%02d %s\n", n, &tens[(n / 10)]); 12 } 13 } else { 14 printf("%02d %s\n", n, &unit[n]); 15 } 16} 17int main() { 18 for (int i = 0; i < 100; i++) { 19 func(i); 20 } 21 getchar(); 22}

output

1 200 0 301 1 402 2 503 3 604 4 705 5 806 6 907 7 1008 8 1109 9 1210 10 1311 10 1 1412 10 2 1513 10 3 1614 10 4 1715 10 5 1816 10 6 1917 10 7 2018 10 8 2119 10 9 2220 20 2321 20 1

投稿2020/09/04 18:01

編集2020/09/04 20:57
mjk

総合スコア303

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Merrifield

2020/09/04 22:26

回答ありがとうございます。if文の書き方、こちらのほうがすっきりしていて良いですね
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問