質問: ### 実現したいこと 文字列`s[7]`と`t[7]`が一致していたら`same`,そうではなくて大文字と小文字の違いだけであったら`case-insentive`,これらに該当しなかったら`different`を出力したい。 以下私の考え方です。 1. 文字が一致している->`cnt++` 2. 1が一致していないとき、`s[i]`が大文字で`t[i]`が小文字のとき、または`s[i]`が小文字で`t[i]`が大文字のとき、それぞれを大文字または小文字変換してそれが`t[i]`と一致すればカウント->`cnsup++`または`cnlow++` 3. 上記以外になったとき->`cdiff++` 回りくどい気がしますが私が思いついたのはこの程度です。 ### 問題点 一致しないカウントの`cdiff`は何をいれてもカウントが0になってしまう。 `printf("もはや全部違う\n");`で`while`の最後の`if`を通過したかどうか確認してみたが出力されることはなかった。 **実行例** ``` s: AbcDe t: AbcDf 一致cnt= 5 大文字小文字cnsup= 0 小文字大文字cnlow= 0 違うcdiff= 0 -------------------------------------------------------------------- 文字列を入力してください s: AbCdE t: AbcDe s[2]が大文字でt[2]が大文字のとき s[3]が小文字でt[3]が大文字の時 s[4]が大文字でt[4]が大文字のとき 一致cnt= 3 大文字小文字cnsup= 2 小文字大文字cnlow= 1 違うcdiff= 0 case-insensitive ------------------------------------------------------------------- 文字列を入力してください s: AbcDe t: AbcDe 一致cnt= 6 大文字小文字cnsup= 0 小文字大文字cnlow= 0 違うcdiff= 0 same ``` ### コード ``` //文字列の比較1 #include #include int main(void) { char s[7],t[7]; printf("文字列を入力してください\n"); printf("s: "); fgets(s,7,stdin); printf("t: "); fgets(t,7,stdin); int cnt,cnsup,cnlow,cdiff; cnt=0; cnsup=0; cnlow=0; cdiff=0; int i=0; while(t[i]!='\0'){ if(s[i]==t[i]){ //小文字大文字もすべて一致 cnt++; }else if(isupper(s[i])){ //s[i]が大文字で if(islower(t[i])){ //t[i]が小文字の時 printf("s[%d]が大文字でt[%d]が大文字のとき\n",i,i); char isi=tolower(s[i]); if(isi==t[i]){ //s[i]を小文字に変換して一致したらOK cnsup++; } } }else if(islower(s[i])){ //s[i]が小文字でt[i]が大文字の時 if(isupper(t[i])){ printf("s[%d]が小文字でt[%d]が大文字の時\n",i,i); char isl=toupper(s[i]); if(isl==t[i]){ //s[i]が大文字変換して一致したらOK cnlow++; } } }else{ //もはや文字が違う時 printf("もはや全部違う\n"); char isi=tolower(s[i]); //小文字 char isl=toupper(s[i]); //大文字 if(isi!=t[i] || isl!=t[i]) cdiff++; //小文字を大文字に変換しても大文字を小文字に変換しても一致しないとき } i++; } printf("一致cnt= %d 大文字小文字cnsup= %d 小文字大文字cnlow= %d 違うcdiff= %d \n",cnt,cnsup,cnlow,cdiff); if(cnt==6){ //\0を含めて一致している printf("same\n"); }else if(cdiff>0){ printf("differnt\n"); }else if(cnsup>0||cnlow>0){ printf("case-insensitive\n"); } return 0; } ```
回答: これはif文とelse文の対応(というべきか?)に起因する問題ですね。 PAST2020 Aだと思いますが、その場合入力は英大小文字のみなので、 ``` }else if(isupper(s[i])){ //s[i]が大文字で ``` 英大文字の場合ここでキャッチされ、 ``` }else if(islower(s[i])){ //s[i]が小文字でt[i]が大文字の時 ``` 英小文字の場合ここでキャッチされ、 ``` }else{ //もはや文字が違う時 printf("もはや全部違う\n"); char isi=tolower(s[i]); //小文字 ``` ここに到達することはありません。 これをそのままのコードの構造で解決するのはなかなか面倒なので、アルゴリズムから見直すことにしましょう。 質問者様のやりたかったことは、 1. `s[i] == t[i]`なら、`cnt++` 2. `s[i]`が大文字かつ`t[i]`が小文字のとき、`tolower(s[i]) == t[i]`なら、`cnsup++` 3. `s[i]`が小文字かつ`t[i]`が大文字のとき、`toupper(s[i]) == t[i]`なら、`cnlow++` 4. どの条件も満たさないとき、`cdiff++` だと思われますが、この2と3は区別する必要がないのではありませんか? 例えば、もうどちらも小文字に変換してから比較すれば、どちらが元々どうだったか考える必要はありません。 こういうのはどうでしょう。 1. `s[i] == t[i]`なら、`cnt++` 2. `tolower(s[i]) == tolower(t[i])`なら、`cnlow++` 3. どの条件も満たさないとき、`cdiff++` また、もしかすると、カウントする必要すらないのではないでしょうか。