🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

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

Q&A

解決済

4回答

2564閲覧

【C言語】switch文を利用して、正の整数だけを判別したい

aizaku_san

総合スコア5

C

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

0グッド

0クリップ

投稿2019/10/19 16:37

前提・実現したいこと

switch文だけ利用して、入力した正の整数に対して0以上10未満10以上20未満20以上30未満30以上を判別して知らせるコードを書いたのですが、これに負の整数を入力したときにエラーメッセージ(「正の整数を入力してください」)が表示されるようにしたいです。

自分で下記の様に書いては見たのですが、どうやってもswitch文の中にif文を書かないと、負の整数が入力された場合に対応できません。
switch文だけを利用して書くことは不可能でしょうか?また他に効率の良い方法などがあればご教示くださいm(_ _;)m

該当のソースコード

c

1#include <stdio.h> 2int main(void){ 3 int a; 4 printf("0以上の整数を入力して下さい:\n"); 5 scanf("%d", &a); 6 7 8 9 switch(a / 10) { 10 case 0: 11 if(a < 0) { 12 printf("正の整数を入力してください\n"); 13 } 14 else { 15 printf("%dは0以上10未満.\n", a); 16 } 17 break; 18 case 1: 19 if(a < 0) { 20 printf("正の整数を入力してください\n"); 21 } 22 else { 23 printf("%dは10以上20未満.\n", a); 24 } 25 break; 26 case 2: 27 if(a < 0) { 28 printf("正の整数を入力してください\n"); 29 } 30 else { 31 printf("%dは20以上30未満.\n", a); 32 } 33 break; 34 default : 35 if(a < 0) { 36 printf("正の整数を入力してください\n"); 37 } 38 else { 39 printf("%dは30以上です\n", a); 40 } 41 break; 42 } 43 44 return 0; 45}

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

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

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

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

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

jimbe

2019/10/19 17:05

if 文以外は使ってよいのでしょうか.
dodox86

2019/10/19 17:09

どう考えてももともとの条件分岐がif文案件なのですが、(例えば勉強のために)あくまでswitch文で実現されたいのでしょうか。
aizaku_san

2019/10/20 00:22

そうです。私が使用しているC言語テキスト(大学から配布されたものです)の演習問題なのですが、「swtch文を利用して」と書かれているのでswitch文だけで書いたほうがいいのかと思いまして……
jimbe

2019/10/20 02:12

「〇〇を利用して」は「〇〇以外は使ってはいけない」と同等では無いと思いますが...講師次第でしょうか.
guest

回答4

0

ベストアンサー

あくまでも switch 文での分岐を使うという前提を崩さずに負数に対応するとすればこのような方法が取れます。 与えられた整数が負数であった場合に事前に -1 というひとつの値に置き換えています。

c

1#include <stdio.h> 2 3int main(void){ 4 int a; 5 6 printf("0以上の整数を入力して下さい:\n"); 7 scanf("%d", &a); 8 9 switch(a<0 ? -1 : a/10) { 10 case -1: 11 printf("正の整数を入力してください\n"); 12 break; 13 case 0: 14 printf("%dは0以上10未満.\n", a); 15 break; 16 case 1: 17 printf("%dは10以上20未満.\n", a); 18 break; 19 case 2: 20 printf("%dは20以上30未満.\n", a); 21 break; 22 default : 23 printf("%dは30以上です\n", a); 24 break; 25 } 26 27 return 0; 28}

switch を使わずに同等の処理を書くとすれば、常識的には以下のようになると思います。

c

1#include <stdio.h> 2#define upper_limit 30 3 4int main(void){ 5 int a; 6 7 printf("0以上の整数を入力して下さい:\n"); 8 scanf("%d", &a); 9 10 if(a<0) printf("正の整数を入力してください\n"); 11 else if(a>=upper_limit) printf("%dは%d以上です\n", a, upper_limit); 12 else printf("%dは%d以上%d未満.\n", a, a/10*10, a/10*10+10); 13 14 return 0; 15}

想定する上限が 30 よりも多くなったときにどんどん分岐を追加しなくても upper_limit の定義をいじるだけで済みますし、何より短いです。

プログラムを書く上では条件に対して個別対応するのではなくなるべく一般化するのが好ましく、 switch の分岐で対応するのが妥当であるような場面はそれほど頻出するわけではありません。 もちろん練習であるのならば様々な文法に積極的に習熟するのは良いことですが、質問で提示されている題材だと switch の活用にはあまり適していないと思います。

投稿2019/10/19 18:35

編集2019/10/19 19:30
SaitoAtsushi

総合スコア5684

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

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

aizaku_san

2019/10/20 00:34

なるほど。事前に置き換えることでそのあとのcaseで指定できるのですね。 回答ありがとうございます。
guest

0

ちょっと別の方向から・・・
問題点:最初に空白が有る場合は、負数の判定が出来ない等。
・・・解決方法は有りますが題意ではないと思いますので^^:

c

1#include <stdio.h> 2#include <stdlib.h> 3 4int main(void) 5{ 6 char str[100]; 7 8 fgets(str, sizeof str, stdin); 9 10 switch (str[0]) { 11 case '-': 12 printf("正の整数を入力してください\n"); 13 return 1; 14 default: ; 15 } 16 17 int a = (int)strtol(str, NULL, 10); 18 19 switch (a / 10) { 20 case 0: 21 printf("%dは0以上10未満.\n", a); 22 break; 23 case 1: 24 printf("%dは10以上20未満.\n", a); 25 break; 26 case 2: 27 printf("%dは20以上30未満.\n", a); 28 break; 29 case 3: 30 printf("%dは30以上です\n", a); 31 break; 32 default: 33 return 1; 34 } 35 36 return 0; 37} 38

結果

text

1usr ~/Project/test % ./a.out 2-5 3正の整数を入力してください 4usr ~/Project/test % ./a.out 55 65は0以上10未満. 7usr ~/Project/test % ./a.out 825 925は20以上30未満. 10

投稿2019/10/19 18:35

cateye

総合スコア6851

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

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

aizaku_san

2019/10/20 00:36

これは「-」が入力されたら、その時点でエラーメッセージが表示されるということでしょうか? 回答ありがとうございます。
guest

0

※switch文縛りの問題なのかもしれませんが、回答を書いてしまったので一応投稿します。

勉強のため、あえてswitchのみを使って実現したい、と言うご要望なのかもしれませんが、C言語におけるswitch文は、条件を単一の整数値として判定するものであり、範囲ではないので、このような問題に適用するのはやはり無理があると思います。一般的にはif文での条件判断になるでしょう。

C

1#include <stdio.h> 2 3int main(void) { 4 int a; 5 printf("0以上の整数を入力して下さい:\n"); 6 scanf("%d", &a); 7 8 if (a >= 30) { 9 printf("%dは30以上です\n", a); 10 } else if (a >= 20) { 11 printf("%dは20以上30未満.\n", a); 12 } else if (a >= 10) { 13 printf("%dは10以上20未満.\n", a); 14 } else if (a >= 0) { 15 printf("%dは0以上10未満.\n", a); 16 } else { 17 printf("正の整数を入力してください\n"); 18 } 19 20 return 0; 21} 22

こちらの方が解法とプログラマーの意図を直接反映していますし、シンプルかつ効率的だと思います。

投稿2019/10/19 17:16

dodox86

総合スコア9256

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

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

aizaku_san

2019/10/20 00:26

そうですね、確かにif文を利用したほうがシンプルにかけますね…… 回答ありがとうございます。
guest

0

条件演算子(?:)を使用可でしたら, a<0?1:0 で 0未満=1,0以上=0 が得られます.
使用不可でしたら, ビット演算 a>>sizeof(int)*8-1&1 でも同じ値が得られます.

投稿2019/10/19 17:18

jimbe

総合スコア13202

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

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

aizaku_san

2019/10/20 00:29

条件演算子! まだ未学習の範囲でしたので知らなかったのですが、このようなものがあるんですね! 回答ありがとうございます。
kazuma-s

2019/10/20 00:55

a < 0 だけで、0未満=1、0以上=0 が得られます。
jimbe

2019/10/20 02:02

成立時は !0 だったと思いますが...
kazuma-s

2019/10/20 03:48 編集

!0 は 1 です。 C11(ISO/IEC 9899:2011) の最終ドラフトN1570 6.5.8 Relational operators Syntax   relational-expression:     shift-expression     relational-expression < shift-expression     relational-expression > shift-expression     relational-expression <= shift-expression     relational-expression >= shift-expression Constraints One of the following shall hold: -- both operands have real type; or -- both operands are pointers to qualified or unqualified versions of compatible object types. Semantics If both of the operands have arithmetic type, the usual arithmetic conversions are performed. ... Each of the operators < (less than), > (greater than), <= (less than or equal to), and >= (greater than or equal to) shall yield 1 if the specified relation is true and 0 if it is false. The result has type int. 最後の部分は JIS X3010:2003(ISO/IEC 9899:1999) では、次の通り。 <(小さい),>(大きい),<=(以下)及び>=(以上)の各演算子は, 指定された関係が真の場合は 1を,偽の場合は 0 を返す。 その結果は,型 int をもつ。
jimbe

2019/10/20 03:45

なるほど, ありがとうございます.
Zuishin

2019/10/20 03:52 編集

確かに論理演算の結果は 1 になりますが、そこはコンパイラの最適化に任せて論理演算と算術演算を混ぜない方が好ましいと思います。モダンな言語では混ぜにくいようになっています。少なくとも、混ぜない回答に対してその突っ込みは不要だと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問