C言語のif文の中にif文を書く条件分岐の使い方編

# 注意
・AtCoderの[abc003_B - AtCoderトランプ](https://atcoder.jp/contests/abc003/tasks/abc003_2)のネタバレあり。

# 学んだこと3つ！
・C言語の標準ライブラリとは編
・if文の中にif文を書く条件分岐の使い方編
・論理演算子！の使い方編


# chatGPTに教えてもらったコード
```C
#include <stdio.h>   
#include <string.h>  
#include <stdbool.h> 

int main() {
    char s[11];
    char t[11];

    scanf("%s", s);
    scanf("%s", t);

    int len = strlen(s);
    bool canWin = true;

    for (int i = 0; i < len; i++) {
        if (s[i] != t[i]) {
            if (s[i] != '@' && t[i] != '@') {
                canWin = false;
                break;
            }

            if (s[i] == '@' && !(t[i] == 'a' || t[i] == 't' || t[i] == 'c' || t[i] == 'o' || t[i] == 'd' || t[i] == 'e' || t[i] == 'r')) {
                canWin = false;
                break;
            }

            if (t[i] == '@' && !(s[i] == 'a' || s[i] == 't' || s[i] == 'c' || s[i] == 'o' || s[i] == 'd' || s[i] == 'e' || s[i] == 'r')) {
                canWin = false;
                break;
            }
        }
    }

    if (canWin) {
        printf("You can win\n");
    } else {
        printf("You will lose\n");
    }

    return 0;
}

``` 
# C言語の標準ライブラリとは編
C言語を書くときに1行目に必ず書く```#include <stdio.h> ```について調べてみた。
そもそもの英語の知識として
標準ライブラリは英語で"Standard Library"、"include"は英語で含む・加えるという意味がある。
私はここを最初に調べなかったので頭の中の整理が遅れた。
今回のAtCoderの問題の解答で使用した3つのヘッダーファイルを例に挙げて省略しない表記すると理解ができた。



# ```#include <stdio.h> ```　
→　Standard Input Output Header
```#include <stdio.h> ```と書くことで、C言語の標準ライブラリ関数の
書式付きで標準入力から読み取ることができるscanf関数や
書式付きで標準出力に書き込むことができるprintf関数などの標準的な入出力関数を使用することができる。



# ```#include <string.h>```
→　string Header
```#include <string.h>```と書くことでC言語の標準ライブラリ関数の
文字列の長さを取得できるstrlen関数や
文字列をコピーできるstrcmp関数を使用することができる。



# ```#include <stdbool.h>``` 
→　Standard bool Header
 ```#include <stdbool.h>``` と書くことで、C言語の標準ライブラリマクロのbool・true・falseを使用することができる。
※言い訳
標準ライブラリマクロはよく理解していないけどこちらの本に記載があったので次出会った時の手助けになるためにちょっとだけ書いとく。
[スッキリわかるC言語入門](https://www.amazon.co.jp/%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8BC%E8%A8%80%E8%AA%9E%E5%85%A5%E9%96%80-%E7%AC%AC2%E7%89%88-%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8B%E5%85%A5%E9%96%80%E3%82%B7%E3%83%AA%E3%83%BC%E3%82%BA-%E4%B8%AD%E5%B1%B1-%E6%B8%85%E5%96%AC/dp/4295012785/ref=sr_1_1?adgrpid=58811617088&hvadid=658841644543&hvdev=c&hvlocphy=1009308&hvnetw=g&hvqmt=e&hvrand=14038157454558149293&hvtargid=kwd-492334848933&hydadcr=27265_14678545&jp-ad-ap=0&keywords=%E3%82%B9%E3%83%83%E3%82%AD%E3%83%AA%E3%82%8F%E3%81%8B%E3%82%8Bc%E8%A8%80%E8%AA%9E%E5%85%A5%E9%96%80&qid=1684488871&sr=8-1)

https://daeudaeu.com/c-bool/

# if文の中にif文を書く条件分岐の使い方編
用語の整理をしてみる。
if文の中にif文を書くことを
```ネストされたif文```や```if文の入れ子構造```と呼ばれていて、このワード検索できる。
ネストと知って、ラボットの充電器？って思って[調べてみた](https://www.weblio.jp/content/%E3%83%8D%E3%82%B9%E3%83%88)ら巣とか入れ子という意味なので納得した。
改めて、[ネストされたif文](https://kanda-it-school-kensyu.com/java-super-intro-contents/jsi_ch06/jsi_0605/)を調べてみたり、聞いてみたりしたらネストされたif文を日本語で書いてくださる方がいたので理解できた。感謝。

例えば、赤い食べ物かどうかを判定する条件分岐はネストされたif文で書ける。
・for文で物を渡されて、最初のif文で食べ物かどうかを判定する。
・2番目のif文では、色が赤いかかどうか分岐した結果、ここでは食べ物で赤いが判定される。
・3番目のif文では、果物かどうか分岐した結果、ここでは食べ物で赤くて果物が判定される。
(ここ説明不足かもだけどこれみんなに知って欲しい！)
```
for (物を渡される) {
    if (食べれるか) {
        if (赤いか) {
            // 赤いし食べれる
            if (果物か) {
                // 果物である
                // 赤い
                // 食べれる
            } else {
                // 食べれる
                // 赤い
                // 果物ではない
            }
        }
        // 食べれる
        // 赤いかも
        // 赤くないかもしれない
    }
    // 赤いどうかわからない
    // 食べれるかわからない
}
```


# 論理演算子！の使い方編
条件分岐で```!=```は使ったことがあったけど
chatGPTに教えてもらったコードでこの条件分岐の```&& !```が
何をしているかわかった。

```C
if (s[i] == '@' && !(t[i] == 'a' || t[i] == 't' || t[i] == 'c' || t[i] == 'o' || t[i] == 'd' || t[i] == 'e' || t[i] == 'r')) {
    canWin = false;
    break;
}

if (t[i] == '@' && !(s[i] == 'a' || s[i] == 't' || s[i] == 'c' || s[i] == 'o' || s[i] == 'd' || s[i] == 'e' || s[i] == 'r')) {
    canWin = false;
    break;
}
```

# ```!```を調べてみた！
この表をみたら比較したものが等しい時にfalse、等しくないときにtrueを判定する。

![スクリーンショット 2023-05-20 17.14.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823837/34fc3ca3-c7c2-26b7-82ea-bf3b6915701a.png)

[論理演算子の表を参考にした記事](https://kanda-it-school-kensyu.com/php-intro-contents/pi_ch09/pi_0907/)

https://www.javadrive.jp/cstart/if/index3.html


# シンプルな数字で```!```を実験してみた！
```C
#include <stdio.h>
int main(void){

    int a = 100;
    int b = 200;
    
    if(!(a == b)){
        printf("aとbは違う値です\n");
    } else {
        printf("aとbは同じ値です\n");
    }
}
```
<b>実行結果</b>
aとbは違う値です

# わからなかったところ
<b>問題文編</b>
＠が普通のトランプのジョーカーの役割をしているので
sとtの文字列に＠があれば、a,t,c,o,d,e,rのどれかと入れ替え可能だから
入力例1だと
sの文字列 ch@ku@ai
と
tの文字列 choku@@i
は
＠を以下のように入れ替えることができるから出力例1がYou_can_winになる。
```
sの文字列 c h @ k u @ a i
             ↓     ↓
             o     d
tの文字列 c h o k u @ @ i
                   ↓ ↓
                   d a
```
<b>条件分岐編</b>
下の図のように条件分岐がどこで分岐しているかわからなかった。
(間違ってるかも)
![スクリーンショット 2023-05-22 16.59.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2823837/ca4cc684-ecba-6c4f-3ce1-132ad67b1c00.png)

# 復習したコード！
```C
#include <stdio.h>   //scanf関数・ printf関数を使う時に必要なヘッダーファイル
#include <string.h>  //strlen関数を使う時に必要なヘッダーファイル
#include <stdbool.h> //boolを使う時に必要なヘッダーファイル
int	main(void)
{
	char s[11],t[11];

	//for文でsとtの文字列を先頭から一文字ずつ判定するので
	//標準入力の値を取得する。
	scanf("%s%s", s, t);
	// printf("%s %s\n",s,t);

	//for文でsとtの文字列を先頭から一文字ずつ判定するので
	//文字列のsかtの文字列の長さを取得する。int n = strlen(t);でも可
	int n = strlen(s);
	// printf("%d\n", n);

	//boolの初期値をtrueにしてfalseの場合の条件を以下で判定する。
	bool win = true;

	for (int i = 0; i < n; i++)
	{
		//for文でsとtの文字列を先頭から一文字ずつ比較して同じ文字でない時は win に false を代入する。
		if(s[i] != t[i]){
			win = false;
		}
			//for文でsとtの文字列を先頭から一文字ずつ比較して同じ文字でない時かつ
			//for文でsとtの文字列を先頭から一文字ずつ'@'でない場合は win に false を代入する。
			if(s[i] != '@' && t[i] != '@'){
			win = false;
			}
			//for文でsとtの文字列を先頭から一文字ずつ比較して同じ文字でない時かつ
			//s[i]が＠でt[i]がa,t,c,o,d,e,r以外の場合はcanWinにfalseを代入する。
			if(s[i] == '@' &&
				!(t[i] == 'a' ||
				t[i] == 't' ||
				t[i] == 'c' ||
				t[i] == 'd' ||
				t[i] == 'e' ||
				t[i] == 'r'
				)){
				win = false;
				break;
			}

			//for文でsとtの文字列を先頭から一文字ずつ比較して同じ文字でない時かつ
			//t[i]が＠でs[i]がa,t,c,o,d,e,r以外の場合はcanWinにfalseを代入する。
			if(t[i] == '@' && !(
				s[i] == 'a' ||
				s[i] == 't' ||
				s[i] == 'c' ||
				s[i] == 'd' ||
				s[i] == 'e' ||
				s[i] == 'r' )){
				win = false;
				break;
			}
	}
	if(win){
		printf("You can win\n");
	} else {
		printf("You will lose\n");
	}

	return (0);
}
```