みんなの「教えて(疑問・質問)」にみんなで「答える」Q&Aコミュニティ

こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

論理演算子について

◎1-----------------------------
int main(void)
{
int a=10,b=20;

while(1){
if(a= =12 && b= =25){
break;
}
++a;
++b;
}

return 0;
}
--------------------------------

◎2-------------------------------------------------------
#include<stdio.h>
#include<ctype.h>

int main(void)
{
char ss[256]="10%%'%shin(no((100!w**a'16&'shi&%$#n~|=~de)&64";
int dt,i=0;

printf("右の文字列には言葉が隠れています: ");
printf("%s\n",ss);
puts("");
printf("1を入力すると言葉が分かります: ");

scanf("%d",&dt);

puts("");

while(dt!=1 && ss[i] !='\0'){
if( !isalnum(ss[i]) ){
ss[i]=' ';
}
++i;
}
printf("%s\n",ss);
puts("");

return 0;
}
------------------------------------------------------------

以上2つのプログラムにおいて疑問があります。

まず◎1のプログラムで、aが12、bが25になるという2つの条件を満たしたら、プログラムを終了させようと思ったのですが、条件を満たしても、ずっとデクリメントし続け終了しません。
「if(a= =12 && b= =25)」の部分を「if(a= =12 || b= =25)」とすれば、aが12になった時点で終了しました。
◎1では「if(a= =12 && b= =25)」という条件が何故適用されないかという疑問があります。

次に、◎2ではdtが1になり、配列ssに格納されている文字列が、'\0'になるという2つの条件を満たしたら終了させようとしたのですが、1を入力すると、「ss[i]!='\0'」の条件が偽にもかかわらず、while文が一度も実行されませんでした。
そこで、1以外を入力すると、while文は実行されましたが、dtの条件が真になる事はないのに、ちゃんと終了しました。

プログラム◎1、◎2について何故こうのようになってしまうのか、教えていただければ嬉しいです。

投稿日時 - 2009-05-04 13:42:37

QNo.4930337

すぐに回答ほしいです

質問者が選んだベストアンサー

◎2に関して。
表示部分等を省いて敷き詰めて書くと、

char ss[256]="10%%'%shin(no((100!w**a'16&'shi&%$#n~|=~de)&64";
int dt,i=0;
scanf("%d",&dt);

while(dt!=1 && ss[i] !='\0'){
if( !isalnum(ss[i]) ){
ss[i]=' ';
}
++i;
}

こういう文なわけですが、
while文はwhile(…)の…の部分が「真」であれば{}内の処理を実行します。
上の…の部分を見てみると、
dt != 1 && ss[i] != '\0'
訳すと、dtが1じゃない かつ ss文字列のi文字目が'\0'じゃない ならば真
&&演算子は、左辺と右辺どちらも真ならば真を返します。


>>1を入力すると、「ss[i]!='\0'」の条件が偽にもかかわらず、while文が一度も実行されませんでした。
1を入力すると、「dtが1じゃない」という条件に対しては「偽」を返します。
よって、どちらも真ならば…という条件を満たさないので、dt != 1 && ss[i] != '\0'は「偽」が返され、while文は{}内の処理を1度も実行しません。


>>「ss[i]!='\0'」の条件が偽にもかかわらず
&&演算子を理解しているなら、「「ss[i]!='\0'」の条件が真にもかかわらず」という勘違いの方がましだと思います。
どちらも真であれば、while文の{}内の処理が実行されます。


>>そこで、1以外を入力すると、while文は実行されましたが、dtの条件が真になる事はないのに、ちゃんと終了しました。
1以外を入力すると、「dtが1じゃない」という条件に対しては「真」を返します。
ちゃんと終了したのは、「ss文字列のi文字目が'\0'じゃない」が途中で「偽」になったからです。

文字列についても一応説明しておくと、
char ss[4]="abc"; とすると、実際には
ss[0] = 'a'
ss[1] = 'b'
ss[2] = 'c'
ss[3] = '\0'
と格納されているので、途中で\0が現れます。



一通り答えてみてから気づきましたが、&&演算子以前に、
>>dtの条件が真になる事はないのに、
が一番の勘違いの原因かな。
dt != 1
訳すと、「dtが1じゃない ならば真」
dtに1以外を入力すると真です。
dtに1を入力すると偽です。



上に書いた内容を理解すれば、「回答番号:No.2へのお礼」での疑問も解決すると思います。

理解できなければ、参考URLを熟読したら理解できると思います。
「真理値表 C言語」でググって2番目に出ました。

参考URL:http://www.asahi-net.or.jp/~AX2S-KMTN/ref/logicope.html

投稿日時 - 2009-05-05 06:48:46

お礼

ご回答ありがとうございます。

どちらかの条件式が偽になれば処理をしないという理解が、完全に曖昧でした。そして「!=」という記述に対して、どちらが真偽であるか混乱してしまいました。

   条件式1     条件式2     結果
     真        真         真
     真        偽         偽
     偽        真         偽
     偽        偽         偽

論理積演算子は左辺式、右辺式が両方真でない限り処理が行われないという事と、以上の真偽関係をしっかり頭に入れておきます!

投稿日時 - 2009-05-05 12:40:26

ANo.8

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(8)

ANo.7

>aが12になった時点で、aはデクリメントされないという

デクリメントするコードは、もともとどこにも見あたらないです。
もしかすると、インクリメント(++)とデクリメント(--)とを
取り違えられているのかもしれません。

投稿日時 - 2009-05-04 19:39:41

お礼

お礼内容、質問内容の記述はインクリメントの間違いでした。
すいません。

投稿日時 - 2009-05-04 21:24:26

ANo.6

>ここにそのまま書き込むと、代入演算子のように見えた

一見そのように見えますが、=の長い短いで判断できます。
なるべく、お手持ちのソースコードに手を加えることなく、
そっくりそのまま載せてくださる方がよいです。

投稿日時 - 2009-05-04 19:07:02

ANo.5

◎2
dtの値はループの中で変化しません。
したがって、while文の条件にする必要がありません。
if文で1回だけ判断すればじゅうぶんです。

投稿日時 - 2009-05-04 17:25:46

お礼

確かにdtは常に一定なので、条件式としては意味はないですね。。
でも今回、dtを条件式に入れた事によって何故このような処理が行われたのか、疑問に思いました。

投稿日時 - 2009-05-04 21:21:24

ANo.4

== 演算子を = = のように空白をあけて書くと、
コンパイルエラーが出ませんか?

投稿日時 - 2009-05-04 15:02:23

お礼

ご回答ありがとうございます。

ここにそのまま書き込むと、代入演算子のように見えたので、スペースを入れて書き込みいたしました(;^_^)

投稿日時 - 2009-05-04 15:26:43

ANo.3

◎1だけ回答します。
if(a= =12 && b= =25){
break;
}
の意味は、
aが12で かつ bが25の場合、breakが実行されます。
従って、aが12になったとき、bは22なので、breakは実行されません。

>>「if(a= =12 && b= =25)」の部分を「if(a= =12 || b= =25)」とすれば、aが12になった時点で終了しました。
if(a= =12 || b= =25){
break;
}
の意味は、aが12 または bが25 の場合、breakが実行されます。
従って、aが12になった時、bは何でもよいので(b=22ですが)
breakが実行されます。
&& の意味と || の意味をきちんと理解することが大切です。

投稿日時 - 2009-05-04 14:59:12

お礼

ご回答ありがとうございます。

aが12になった時点で、aはデクリメントされないという、馬鹿な考えをしていました。恥ずかしい限りです。。
詳しくご説明ありがとうございました。
後、&&の意味と||の意味をきちんと理解しておきます!

投稿日時 - 2009-05-04 15:37:46

ANo.2

◎2
dt!=1
ですからdtが1ではないという条件を求めていますが?
「dtの条件が真になる事はないのに」というのは
たんなる勘違いでは?

投稿日時 - 2009-05-04 14:06:54

お礼

ご回答ありがとうございます。

まずdt側の終了条件をscanf入力によりあらかじめ満たしておいて、その後、デクリメントされた後、ss[i]側が'\0'になり、2つの終了条件を満たし、終了させるという事をさせようと思ったのですが、何かやはり勘違いがありますかね?
後、1以外を入力した場合、「1以外の場合はループを続ける」ということで、ループが終わらないと思ったのですが、終わってしまいました。

以上についてご回答いただければ嬉しいです。

投稿日時 - 2009-05-04 15:20:47

ANo.1

> ◎1では「if(a= =12 && b= =25)」という条件が
> 何故適用されないかという疑問があります。

a==12の時はb==22でありb==25の時にはa==15なので、
a==12 && b==25という条件は永遠に有り得ません。

集合はやらなかった世代か弱いですか?
あまり考える所ではないのですが、センスなのかな?

2はパスです。

投稿日時 - 2009-05-04 13:51:36

お礼

ご回答ありがとうございます。

>a==12の時はb==22でありb==25の時にはa==15なので、
>a==12 && b==25という条件は永遠に有り得ません。

そうですよね♪
何か恥ずかしいです(;^_^)
ありがとうございました。

投稿日時 - 2009-05-04 14:47:03