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

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

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

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

Q&A

解決済

3回答

2931閲覧

全角10文字以内を入力し、それ以上だと再入力させるプログラムを作りたい

gyoruo

総合スコア61

C

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

0グッド

0クリップ

投稿2020/07/30 02:51

以下のプログラムで全角10文字までを入力可能としているのに、「あ」と20文字入れても代入されてしまいます。
MAXDATAで11などの制限をかけるとそれ以上入力した場合にコアダンプで処理が落ちてしまうため、多く値をとることで改行文字かの判定をifで行っています。なぜ10文字以上でも代入されてしまうのでしょうか?

C

1#include <stdio.h> 2#include <string.h> 3 4#define MAXDATA 256 5 6int main(void) { 7 char test[MAXDATA]; 8 char flag = 0; 9 10 while (flag == 0) { 11 puts("何か文字を入力して、エンターキーを押してください"); 12 printf(">>"); 13 // 半角全角10文字以内を想定 14 fgets(test,MAXDATA,stdin); 15 if (test[11] <= '\n') { 16 printf("10文字以下で、%sと入力されました",test); 17 flag = 1; 18 } else { 19 // 範囲を超えて入力された場合のオーバーラン対策 20 if (strchr(test, '\n') == NULL) { 21 while (fgetc(stdin) != '\n'); 22 } 23 } 24 } 25 26 return 0; 27} 28

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

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

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

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

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

dodox86

2020/07/30 02:57

> if (test[11] <= '\n') { もしかしてこのコードは、「test[0]~test[11]」の範囲に改行コード('\n')が入っているかを判定しよう(したい)としていませんか。もしそうだとすれば、意味が全然違います。
Daregada

2020/07/30 03:03

使用しているエンコーディング(UTF-8とかShift_JISとか)を追記してください。
gyoruo

2020/07/30 04:10

お返事ありがとうございます。 そのように考えていましたが、よくよく考えてみれば、文字コードによって全角は[0][1][2]を占領したりするのでできないと判明しました。 ちなみに、文字コードはUTF-8です。
guest

回答3

0

amiyaさんのアドバイス通り、文字判定のif文を変更したら意図した通りに動きました。

C

1#include <stdio.h> 2#include <string.h> 3 4#define MAXDATA 256 5 6int main(void) { 7 char test[MAXDATA]; 8 char flag = 0; 9 10 while (flag == 0) { 11 puts("何か文字を入力して、エンターキーを押してください"); 12 printf(">>"); 13 // 半角全角10文字以内を想定 14 fgets(test,MAXDATA,stdin); 15 if (strchr(test, '\n') - test <= 31) { 16 printf("%d\n", strchr(test, '\n') - test); 17 printf("10文字以下で、%sと入力されました",test); 18 flag = 1; 19 } 20 else { 21 // 範囲を超えて入力された場合のオーバーラン対策 22 if (strchr(test, '\n') == NULL) { 23 while (fgetc(stdin) != '\n'); 24 } 25 } 26 } 27 28 return 0; 29} 30

投稿2020/07/30 07:51

編集2020/07/30 07:53
gyoruo

総合スコア61

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

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

kazuma-s

2020/07/30 08:53

質問に追記するのではなく、新規の回答として投稿したんですね。 それは、まあいいでしょう。 全角文字をすべて 3バイトだと仮定して、「<= 31」で判定しています。 コード内のコメントに「// 半角全角10文字以内を想定」とありますが、 半角文字を 12文字入力しても 「10文字以下で、abcdefghijklと入力されました」 になりますよ。
gyoruo

2020/07/30 08:55

ご返信ありがとうございます! 全角で10文字超えなければ大丈夫なので半角は何文字でもOKです!
guest

0

OS やコンパイラは何ですか?

次のコードは期待通りに動きますか?

C

1#include <stdio.h> // printf, fgets, getchar 2#include <stdlib.h> // mbstowcs 3#include <string.h> // strchr 4#include <locale.h> // setlocale 5 6#define MAXDATA 256 7 8int main(void) 9{ 10 char test[MAXDATA]; 11 12 setlocale(LC_CTYPE, ""); // マルチバイト文字を使用するため 13 14 while (1) { 15 printf("何か文字を入力して、エンターキーを押してください\n>>"); 16 if (!fgets(test, MAXDATA, stdin)) break; 17 char *p = strchr(test, '\n'); // 改行文字を探す 18 if (p) *p = '\0'; // 改行文字があれば、削除 19 else { // 改行文字が無ければ、 20 int c; // 改行文字まで読み飛ばす 21 while ((c = getchar()) != EOF && c != '\n') ; 22 } 23 int n = mbstowcs(NULL, test, 0); // 文字数を数える 24 if (n >= 0 && n <= 10) { 25 printf("10文字以下で、%sと入力されました\n", test); 26 break; 27 } 28 } 29 return 0; 30}

投稿2020/07/30 04:26

kazuma-s

総合スコア8224

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

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

gyoruo

2020/07/30 05:06

ご回答ありがとうございます。 OSはCentOSで、コンパイラはatomについているものを用いています。 上記のプログラムでは全角10文字以内でも10文字以下でも何度も入力させられました。
kazuma-s

2020/07/30 05:57

私は、Ubuntu で、環境変数 LANG=ja_JP.UTF-8 で動いています。
guest

0

ベストアンサー

文字列が何文字かはstrlen関数で求めることができます。
その返り値と文字数制限を比較してください。

ただし、正確にはこれで分かるのはバイト数であり、1文字が2バイト以上の文字コードを使った場合には、
文字数とは限りません。

fgetsは改行まで含めてしまうので、その分を減らすか、始めから複数行を前提で、「改行まで」の文字数を検知したいのであれば、
strchr(test,'\n')-test 等として求めてください(これもバイト数です)

今の状態だと、入力内容次第で問題が起きそうなので…こんな感じ?

C

1#include <stdio.h> 2#include <string.h> 3 4#define MAXDATA 256 5 6int main(void) { 7 char test[MAXDATA]; 8 char flag = 0; 9 10 while (flag == 0) { 11 puts("何か文字を入力して、エンターキーを押してください"); 12 printf(">>"); 13 // 半角全角10文字以内を想定 14 fgets(test,MAXDATA,stdin); 15 16 char *p = strchr(test, '\n'); // 改行位置を取得 17 if (p != NULL){ // 改行があった場合 18 *p = '\0';       // 改行位置で文字列を終了させる 19 } else { //ついでにMAXDATAオーバーの処理 20 // 範囲を超えて入力された場合のオーバーラン対策 21 while (fgetc(stdin) != '\n'); 22 } 23 24 int len = strlen(test); // 改めて長さを取得 25 if (len <= 30) { // 一文字3Byte固定なら30? 26 printf("%d\n", len); 27 printf("10文字以下で、%sと入力されました",test); 28 flag = 1; 29 } 30 } 31 32 return 0; 33}

scanfとかsscanfを使った方が手っ取り早い気がする。

投稿2020/07/30 03:09

編集2020/07/30 08:48
amiya

総合スコア1218

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

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

gyoruo

2020/07/30 04:12

お返事とアドバイスありがとうございます。 半角と全角でバイト数が異なるので、そもそもこの判定の仕方が無理でした。。。
gyoruo

2020/07/30 05:07

アドバイス通りにしてみたところ、意図した通りに動きました! ありがとうございます。
kazuma-s

2020/07/30 07:44

意図したとおりに動いたというコードを、質問に追記してもらえませんか。 質問は編集できます。
gyoruo

2020/07/30 07:54

ご指摘ありがとうございます。 追記しておきました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問