Fortran入門(Fortran版APG4b)

# 本記事について
競技プログラミングサイトAtCoderではプログラミング初心者のために[C++入門 AtCoder Programming Guide for beginners (APG4b)](https://atcoder.jp/contests/APG4b)というC++のプログラミング教材が提供されています.
更にこれのPython版である[Python入門（Python版 APG4b）](https://qiita.com/saba/items/b9418d7b54cce4b106e4)もありPython初心者への大きな助けとなっています.
本記事は本家APG4bのFortran版となっており, Fortran初心者でも本記事を読めば実際のコンテストでFortranを使えるようになることを目的としています.

本記事の大部分をAPG4b及びPython版APG4bをもとにしているため, 問題があれば本記事は削除いたします.
各節の見出しは本家へのリンクとなっています.

現在途中までの記述となっていますが第1章までは追記する予定です.

#目次
[Fortranとは](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#Fortranとは)
[実行環境](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#実行環境)
[提出練習](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#提出練習)
[第1章](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#第1章)
- [1.01.出力とコメント](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#101出力とコメント)
- [1.02.プログラムの書き方とエラー](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#102プログラムの書き方とエラー)
- [1.03.四則演算と優先順位](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#103四則演算と優先順位)
- [1.04.変数と型](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#104変数と型)
- [1.05.実行順序と入力](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#105実行順序と入力)
- [1.06.if文・比較演算子・論理演算子](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#106if文比較演算子論理演算子)
- [1.07.条件式の結果とlogical型](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#107条件式の結果とlogical型)
- [1.08.変数のスコープ](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#108変数のスコープ)
- [1.09.複合代入演算子](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#109複合代入演算子)
[参考文献](https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#参考文献)

# Fortranとは
Fortranは主に数値計算で使われている言語です.
CやC++に引けを取らないくらい速く, 簡単に並列化ができることから未だに人気の根強い言語となっています.
競技プログラミングではAtCoderを始め, yukicoderやPOJで使用することができます.
ソート関数や各種データ構造を自分で実装しなくてはならないデメリットもありますがC++よりも記述が簡単でかつPythonよりも実行速度が早いため個人的にはおすすめの言語です.
Fortranについてもっと詳しく知りたい方はこちらをご覧ください.
[Fortranとは -日本NAG](https://www.nag-j.co.jp/fortran/FI_1.html#_1)

Fortranには大きく分けてFORTRANとFortranがあります.
FORTRANはFortran77以前のものを指し, 一行に書ける文字数が72文字までと決まっているなど古き良きレガシーなものとなっています(Fortranをあまり知らない人がイメージするFortranはこちらのほうが多いように感じます).
一方, FortranはFortran90以降のいわゆるModern Fortranのことを指し, 一行に132文字まで書けたりモジュールを記述できたりします.
ここではFortran90以降のModern Fortranを使って説明していきます.
FORTRANについてはこちらに詳しく書いてありますので興味のある方はこちらも合わせてご覧ください.
[知識として必要な過去の Fortran - 日本NAG](https://www.nag-j.co.jp/fortran/FI_17.html)

# 実行環境
手元に環境を構築するかAtCoderのコードテストを使用してください.
## Linux
以下のコマンドでFortranの環境構築をすることができます.

```
sudo apt install gfortran
```
## Windows
1. MinGWをインストールし, PATHを通す.  
[MinGW-w64のダウンロードとインストール](https://www.javadrive.jp/cstart/install/index6.html)
2. MinGW Installation Managerを開き,MinGW Compiler Suiteをクリックし, `mingw-gcc-fortran-bin`のチェックボックスをクリックする.
![スクリーンショット 2021-03-24 071353.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692201/92712097-195a-86e1-9c16-6b5d2b55c0ab.png)

3. `Installation -> Apply Changes`をクリックし, 出てきたウィンドウのAppplyボタンをクリックする.
4. コマンドプロンプトを開き`gfortran -v`と入力して以下のようになったら成功です.
![スクリーンショット 2021-03-24 071940.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/692201/1571b04c-d743-d30a-d7a4-40404684bc8d.png)

# 提出練習
以下に記載するコードをコピーし, [A - 1.00.はじめに](https://atcoder.jp/contests/apg4b/tasks/APG4b_a)の下にある提出欄に移動し提出してみましょう.

```Fortran
program main
    implicit none
    print'(A)',"Hello, world!"
end program main
```

提出する際は言語をFortran(GNU Fortran9.2.1)にしてから提出するようにしてください.
見つからない場合は言語欄にFortranと入力すると出てきます.

# 第1章
## [1.01.出力とコメント](https://atcoder.jp/contests/apg4b/tasks/APG4b_b)
### プログラムの基本形
以下がFortranのプログラムの基本形となります.

```Fortran
program main
    implicit none
end program main
```
`main`がこのプログラムのプログラム名となります. 必ず`main`である必要はなく, 別の文字列にしても構いませんが, プログラム中の変数と大文字小文字の区別なく重複しないようにしてください. 
後述しますが例えばプログラム名が`MaIN`であるときに変数名で`main`を使用するとコンパイルエラーとなり, プログラムが動かなくなってしまうため注意してください.
なお, FortranはPythonのようにインデントに注意しなくても大丈夫です.

### 出力
Fortranで出力は`print`文を使います.
基本的な書き方は以下のとおりです.

```Fortran
program main
    implicit none
    print*,"Hello, World!"
end program main
```
FortranはPythonと同じくデフォルトで改行されるようになっています.
`print*`を使用することで出力する変数型を気にすることなく出力できるのですが, 以下のように先頭に空白が入った状態出力されてしまい, 不正解となってしまいます.

```:実行結果
 Hello, World!
```
そのため, 文字列を出力する際には以下のように書くと不正解(WA)にならず安全です.

```Fortran
program main
    implicit none
    print'(A)',"Hello, World!"
end program main
```

```:実行結果
Hello, World!
```

整数を出力する際には以下のように書きます.

```Fortran
program main
    implicit none
    print'(i0)',1
end program main
```

```:実行結果
1
```

小数点以下までの数値を出力する際には以下のように書きます.

```Fortran
program main
    implicit none
    print'(f0.3)',3.141
end program main
```


```:実行結果
3.141
```
`f0.3`のように`.`以降で小数点以下何桁まで表示させたいかを指定しています.
もし例えば小数点以下1桁まで表示させたい場合は以下のように書くとできます.

```Fortran
program main
    implicit none
    print'(f0.1)',3.141
end program main
```

```:実行結果
3.1
```

文字列と整数型を同じ行に出力したい場合は以下のように書きます.

```Fortran
program main
    implicit none
    print'(A,i0)',"Hello",1
end program main
```

```:実行結果
Hello1
```

空白区切りで出力したい場合には以下のように書きます.

```Fortran
program main
    implicit none
    print'(A,1x,i0)',"Hello",1
end program main
```

```:実行結果
Hello 1
```

### コメント
コメントアウトする際は`!`を使用します.
`!`を使用すると`!`以降の1行がコメントアウトとなり, コンパイルの際に無視されます.

```Fortran
program main
    implicit none
    !コメントアウト
    print'(A)',"Hello, World" !ここ以降もコメントアウト
end program main
```

### 全角文字について
全角文字はC++と同様, プログラム中にあるとエラーとなってしまいますが出力する際に`" "`で囲ってあれば問題なく出力されます.

### 問題
ここまで読み進めたら以下のリンク先の問題を解いてみましょう.
[EX1 - コードテストと出力の練習](https://atcoder.jp/contests/apg4b/tasks/APG4b_cv)
[解答例](https://atcoder.jp/contests/apg4b/submissions/15890591)

## [1.02.プログラムの書き方とエラー](https://atcoder.jp/contests/APG4b/tasks/APG4b_c)
### プログラムの書き方
FortranはC++と違い必ず1行に1つの命令文を書き, 改行するようにします.
命令文の途中で改行したいときは以下のように行末に`&`と記述して改行します.

```Fortran
program main
    implicit none
    integer(8)::a
    a=1+2+ &
    3
    print'(i0)',a
end program main
```
一方でC++と同様にスペースとインデントで動作が変わることはありません.
また, C++と同様にプログラム中に全角スペースが入っているとコンパイルエラーとなりますので注意してください.

### 問題
ここまで読み進めたら以下のリンク先の問題を解いてみましょう.
[EX2 - エラーの修正](https://atcoder.jp/contests/apg4b/tasks/APG4b_cu)

```Fortran:A君の書いたプログラム
program ex2
    implicit none
    print'(A,i0)',"いつも,252
    print'(A)',"AtCoderくん"
end program ex2

```

```:標準エラー出力
./Main.f08:3:19:

    3 |     print'(A,i0)',"いつも,252
      |                   1
Error: Unterminated character constant beginning at (1)
```

[解答例](https://atcoder.jp/contests/apg4b/submissions/15891699)

## [1.03.四則演算と優先順位](https://atcoder.jp/contests/APG4b/tasks/APG4b_d)
### 四則演算
次のプログラムは上から順に「足し算」「引き算」「掛け算」「割り算」を行っています.

```Fortran
program main
    implicit none
    print'(i0)',1+1 !2
    print'(i0)',3-4 !-1
    print'(i0)',2*3 !6
    print'(i0)',7/3 !2
end program main
```

```:実行結果
2
-1
6
2
```

`+`, `-`, `*`, `/`を算術演算子といいます.
C++と同様に`*`が掛け算で`/`が割り算です.

### 剰余演算
FortranにはC++やPythonのような剰余演算子はなく, 代わりに組み込み関数である`mod()`を使います.
例えば7を3で割った余りを求めたい場合は以下のように書きます.

```Fortran
program main
    implicit none
    print'(i0)',mod(7,3)
end program main
```

```:実行結果
1
```

このように`N`を`M`で割ったあまりを出したいときには`mod(N,m)`と書くと求めることができます.
### 演算子の優先順位
Fortranの演算子の優先順位はC++と同様算術演算子と同じです.
そのため`1+2*3+4→1+6+4`となります.

|優先順位|高い|低い|
|:---:|:---:|:---:|
|演算子|`*` <br> `/` <br> `mod()`|`+` <br> `-`|

C++と同様`( )`を使うことで計算の優先順位を変えることができます.

```Fortran
program main
    implicit none
    print'(i0)',1+2*3 !7
    print'(i0)',(1+2)*3 !9
end program main
```

```:実行結果
7
9
```

### 割り算の順序
C++と同様小数点以下の切り捨ての関係により割り算の順序によって計算結果が異なってしまうことがあります.
なるべく割り算は計算の後ろの方で行うようにしましょう.
`3/2*4→1*4→4`
`3*4/2→12/2→6`
### ゼロ除算
以下のようにプログラム中でゼロ除算を行うとコンパイルエラーが出るため注意してください

```Fortran
program main
    implicit none
    print'(i0)',3/0
end program main
```

```:標準エラー出力
./Main.f08:3:17:

    3 |     print'(i0)',3/0
      |                 1
Error: Division by zero at (1)
```

### 負の数の剰余
C++と同様に負の数の剰余は$A$, $B$の絶対値をそれぞれ$|A|$, $|B|$としたときに以下のようになります.

* $A$が正のとき: mod($|A|$,$|B|$)
* $A$が負のとき: -mod($|A|$,$|B|$)

このように$B$の正負に関わらず出力は$A$の正負に一致します.

### modulo関数について
※ここを飛ばして問題に行っても構いません.
Fortranには`mod`の他に, `modulo`というもう1つ剰余を取る関数が存在します.
`modulo`関数での負の数の剰余は$A$, $B$の絶対値をそれぞれ$|A|$, $|B|$としたときに以下のようになります.

* $A$が正, $B$が正のとき: mod($|A|$,$|B|$)
* $A$が負, $B$が正のとき: $|B|$-mod($|A|$,$|B|$)
* $A$が正, $B$が負のとき: -$|B|$+mod($|A|$,$|B|$)
* $A$が負, $B$が負のとき: -mod($|A|$,$|B|$)

このように`modulo`関数を使用すると__Pythonと同様の結果になります.__
詳しくはこちらに詳細な解説がありますのでこちらをお読みください.

https://qiita.com/implicit_none/items/db1e04df8eda0bbc3bef

### 問題
ここまで読み進めたら以下のリンク先の問題を解いてみましょう.
[EX3 - 計算問題](https://atcoder.jp/contests/apg4b/tasks/APG4b_ct)
[解答例](https://atcoder.jp/contests/apg4b/submissions/15894061)

## [1.04.変数と型](https://atcoder.jp/contests/apg4b/tasks/APG4b_e)

### 変数
Fortranの主な変数型は以下のとおりです.

|型|書き込むデータの種類|
|:---:|:---:|
|integer|整数|
|real|小数(実数)|
|character(n)|文字列(nに文字列の長さを指定する)|
使用例は以下のとおりです.

```Fortran
program main
    implicit none
    integer a
    real b
    character(7) s
    a=10
    b=3.14
    s="AtCoder"

    print'(i0)',a !10
    print'(i0)',a+2 !12
    print'(i0)',a*3 !30
    print'(f0.2)',b !3.14
    print'(A)',s !AtCoder
end program main
```

```:実行結果
10
12  
30  
3.14
AtCoder
```

### 宣言
変数を使用する際には宣言をする必要があります.
宣言は以下のように「データ型」「変数名」の順で記述します.

```Fortran
integer a
```

### 代入
宣言した変数にデータ(値)を格納する際には`=`を使用します.

```Fortran
a=10
```

### 読み込み
mainプログラム内の`print`文で変数の値を読み込み出力しています.

```Fortran
print'(i0)',a !10
print'(i0)',a+2 !12
print'(i0)',a*3 !30
```

### 変数の初期化
変数を宣言すると同時に値を代入することができます.
宣言するだけのときと記述が変わりますので注意してください

```Fortran
program main
    implicit none
    integer::a=10
    print'(i0)',a
end program main
```

```:実行結果
10
```

値は代入されませんが以下のように宣言のみ行うことも可能です.

```Fortran
program main
    implicit none
    integer::a
    a=10
    print'(i0)',a
end program main
```
### 変数のコピー
`変数1=変数2`と書くと`変数1`に`変数2`の値がコピーされます.

```Fortran
program main
    implicit none
    integer::a=10
    integer b
    b=a !bにaの値である10が代入される
    a=5 !aの値は5に変わるがbの値は10のまま
    print'(i0)',a !5
    print'(i0)',b !10
end program main
```

```:実行結果
5
10
```

### 変数を同時に宣言
変数の宣言時に`,`を間に入れることで複数の変数を同時に宣言できます.

```Fortran
program main
    implicit none
    integer::a=10,b=5
    print'(i0)',a
    print'(i0)',b
end program main
```

```:実行結果
10
5
```

1つ以上変数を宣言すると同時に初期化する場合は以下のように必ず`integer::`と書いてください

```Fortran
program main
    implicit none
    integer::a=10,b
    b=2*a
    print'(i0)',a
    print'(i0)',b
end program main
```

```:実行結果
10
20
```

いずれの変数も宣言と同時に初期化しない場合は以下のように書くことが可能です.

```Fortran
program main
    implicit none
    integer a,b
    a=10
    b=2*a
    print'(i0)',a
    print'(i0)',b
end program main
```

```:実行結果
10
20
```

特に理由がない場合は`integer::`のように書くことをおすすめします.
### 変数名のルール
#### 利用できない変数名
以下の条件に該当する変数名は使用できません

* 数字や`_`で始まる変数名
* `_`以外の記号を含む変数名
`_`は先頭以外に含まれている分には問題ありません.

以下は変数にできない名前の例です.

```Fortran
integer 1abd !数字で始まる名前にできない
integer _abc !_で始まる名前にできない
integer abc+def !_以外の記号を含んではいけない
```

以下は変数にできる名前の例です

```Fortran
integer abc1 !2文字目以降であれば数字にできる
integer abc_ !2文字目以降であれば_にできる
```

#### 同じ名前の変数は定義できない
C++と同様同じ名前の変数は定義できません.
ここで注意してほしいのは__大文字小文字の区別なく同じ名前の変数は定義できません__.
以下は変数を定義できないプログラムの例です

```Fortran
program main
    implicit none
    integer abc
    integer abc !3行目と同じ変数名なので定義できない
    integer AbC !3行目と大文字小文字の区別なく同じ変数名なので定義できない
end program main
```

```:標準エラー出力
./Main.f08:3:15:

    3 |     integer abc !2行目と同じ変数名なので定義できない
      |               1
Error: Symbol ‘abc’ at (1) already has basic type of INTEGER
./Main.f08:4:15:

    4 |     integer AbC !2行目と大文字小文字の区別なく同じ変数名なので定義できない
      |               1
Error: Symbol ‘abc’ at (1) already has basic type of INTEGER
```

#### プログラム名と同じ名前の変数は定義できない
FortranではC++と違いプログラム名を自由に設定することができます.
その際, __プログラム名と同じ名前の変数は大文字小文字の区別なく定義できない__ことに注意してください.
以下は変数を定義できないプログラムの例です

```Fortran
program A
    implicit none
    integer A !プログラム名と同じ変数名なので定義できない
    integer a !大文字小文字の区別なくプログラム名と同じ変数名なので定義できない
end program A
```

```:標準エラー出力
./Main.f08:2:13:

    2 |     integer A !プログラム名と同じ変数名なので定義できない
      |             1
Error: Symbol ‘a’ at (1) cannot have a type
./Main.f08:3:13:

    3 |     integer a !大文字小文字の区別なく同じ変数名なので定義できない
      |             1
Error: Symbol ‘a’ at (1) cannot have a type
```

### 型
`integer`型以外にも様々な変数型があります.
ここではよく使う3つの型を紹介します.

|型|書き込むデータの種類|
|:---:|:---:|
|integer|整数|
|real|小数(実数)|
|character(n)|文字列(nに文字列の長さを指定する)|

```Fortran
program main
    implicit none
    integer::i=10
    real::d=0.5
    character(5)::S="Hello"

    print'(i0)',i
    print'(f0.1)',d
    print'(A)',S
end program main
```

```:実行結果
10
.5
Hello
```

### 異なる型同士の計算
異なる型同士の計算はC++と同様型変換が行われます.
integer型とreal型の計算結果はreal型になります.
そのため, 出力で整数型を指定すると実行時エラーになりますので注意してください.
また, integer型とcharacter型など変換できない型同士の計算はコンパイルエラーになるので注意してください.

```Fortran:実行できるプログラムの例
program main
    implicit none
    integer::i=10
    real::d=0.5
    print'(f0.1)',i+d
end program main
```

```:実行結果
10.5
```

```Fortran:実行時エラーとなるプログラムの例
program main
    implicit none
    integer::i=10
    real::d=0.5
    print'(i0)',i+d
end program main
```

```:標準エラー出力
At line 4 of file ./Main.f08 (unit = 6, file = 'stdout')
Fortran runtime error: Expected INTEGER for item 1 in formatted transfer, got REAL
(i0)
 ^

Error termination. Backtrace:
#0  0x7f4615c5074a
#1  0x7f4615c51235
#2  0x7f4615c51c9b
#3  0x7f4615e66aa9
#4  0x7f4615e733b3
#5  0x7f4615e76462
#6  0x7f4615e7682b
#7  0x7f4615e73035
#8  0x5652a61f3876
#9  0x5652a61f370e
#10  0x7f4615861b96
#11  0x5652a61f3749
#12  0xffffffffffffffff
```

```Fortran:コンパイルエラーになるプログラムの例
program main
    implicit none
    integer::i=10
    character(1)::s="a"
    print'(i0)',i+s
    print'(A)',i+s
end program main
```

```:標準エラー出力
./Main.f08:4:16:

    4 |     print'(i0)',i+s
      |                1
Error: Operands of binary numeric operator ‘+’ at (1) are INTEGER(4)/CHARACTER(1)
./Main.f08:5:15:

    5 |     print'(A)',i+s
      |               1
Error: Operands of binary numeric operator ‘+’ at (1) are INTEGER(4)/CHARACTER(1)
```

### 異なる型同士の代入
異なる型同士の代入でも型変換は行われます.
ただし以下のプログラムのように宣言と初期化を同時に行うときに前で宣言した変数で初期化を行うことはできないので注意してください.

```Fortran:コンパイルエラーになるプログラムの例
program main
    implicit none
    integer::i=10
    real::d=i !iで初期化しようとするとコンパイルエラーになる
end program main
```

```:標準エラー出力
./Main.f08:4:12:

    4 |     real::d=i !iで初期化しようとするとコンパイルエラーになる
      |            1
Error: Parameter ‘i’ at (1) has not been declared or is a variable, which does not reduce to a constant expression
```

別途変数を代入する場合は以下のように一旦変数を宣言してから代入を行うことでできます.

```Fortran:実行できるプログラムの例
program main
    implicit none
    integer::i=10
    real d
    d=i
end program main
```

計算と同様に_型変換できない変数型の代入はできない_ので注意してください.

```Fortran:コンパイルエラーになるプログラムの例
program main
    implicit none
    integer::i=10
    real d
    character(5)::S="Hello"

    i=S !integer型とcharacter型は変換できない
    print'(i0)',S
end program main
```

```:標準エラー出力
./Main.f08:7:6:

    7 |     i=S !integer型とcharacter型は変換できない
      |      1
Error: Cannot convert CHARACTER(1) to INTEGER(4) at (1)
```

### implicit noneについて(重要!!!)
ここまでのサンプルコードでは何の説明もなしに2行目に`implicit none`といういわばおまじないのようなものを書いていたのでこれについて説明します.
`implicit none`とはかつてのFortran(FORTRAN)で使われていた「暗黙の型宣言」を使用しないようにするおまじないです.
「暗黙の型宣言」とは変数名から自動的に変数型を推測する機能のことです.
例えば`i`から始まる変数名は自動的に`integer`型であると判定したりします.
これを使用することはバグの原因となるため使用しないためにも必ず2行目には`implicit none`を書くようにしてください.
尚, 自分の環境でVSCodeを使ってプログラムを書く場合はFortran拡張を入れれば自動で入れてくれますので特に心配する必要はないと思います.
`implicit none`や暗黙の型宣言についてはこちらに詳細な説明がありますので合わせてご覧ください.
[implicit none について - 日本NAG](https://www.nag-j.co.jp/fortran/FI_4.html#AboutImplicitNone)
[暗黙の型宣言 - 日本NAG](https://www.nag-j.co.jp/fortran/FI_18.html#ImplicitTyping)

### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
[EX4 - ◯年は何秒？](https://atcoder.jp/contests/apg4b/tasks/APG4b_cs)

以下のプログラムをコピー&ペーストして指定した場所にプログラムを追記してください

```Fortran
program main
    !1年の年数
    integer::seconds=365*24*60*60

    print'(i0)',!1年は何秒か
    print'(i0)',!2年は何秒か
    print'(i0)',!5年は何秒か
    print'(i0)',!10年は何秒か
end program main
```

[解答例](https://atcoder.jp/contests/apg4b/submissions/15970072)

## [1.05.実行順序と入力](https://atcoder.jp/contests/APG4b/tasks/APG4b_f)
### プログラムの実行順序
C++やPythonと同様プログラムは上から下へ実行されます.

```Fortran
program main
    implicit none
    integer name

    !nameに10を代入
    name=10

    print'(i0)',name !10

    !nameに5を代入
    name=5

    print'(i0)',name !5
end program main
```

```:実行結果
10
5
```

### 入力
入力は`read`文を使います.
以下のプログラムは入力された数値を10倍して出力する例です.

```Fortran
program main
    implicit none
    integer a
    !入力を受け取る
    read*,a
    
    print'(i0)',a*10
end program main
```

```:標準入力
10
```

```:実行結果
100
```

`read*,変数名`で変数に入力を受け取ることができます.
整数型以外のデータを受け取りたいときにはあらかじめ受け取りたいデータ型で変数を宣言し, その変数で入力を受け取るようにすればよいです.

```Fortran
program main
    implicit none
    character(100) text
    real d

    read*,text
    read*,d
    print'(A,A,f0.3)',text(1:len_trim(text)),", ",d
end program main
```

```:標準入力
Hello
1.5
```

```:実行結果
Hello, 1.500
```

ここでプログラム中に`text(1:len_trim(text))`という記述がありますが, これは先頭から入力された文字数分だけ出力するという意味になっています.
詳細は後述予定なのでとりあえずおまじないだと思っておいてください.
ちなみに以下のように`text(1:len_trim(text))`を`text`に書き換えてプログラムを実行すると実行結果が以下のように変わってしまいます.

```Fortran
program main
    implicit none
    character(100) text
    real d

    read*,text
    read*,d
    print'(A,A,f0.3)',text,", ",d
end program main
```

```:標準入力
Hello
1.5
```

```:実行結果
Hello                                                                                               , 1.500

```

### 繋げて入力
`,`で繋げて変数名を書くと複数の変数で入力を受け取ることができます.
C++と同様スペースか改行で区切られていれば分解して入力してくれます.

```Fortran
program main
    implicit none
    integer a,b,c
    read*,a,b,c

    print'(i0)',a*b*c
end program main
```

```:標準入力
2 3
4
```

```:実行結果
24
```

### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
[EX5 - A足すB問題](https://atcoder.jp/contests/apg4b/tasks/APG4b_cr)
[解答例](https://atcoder.jp/contests/apg4b/submissions/15985538)

## [1.06.if文・比較演算子・論理演算子](https://atcoder.jp/contests/APG4b/tasks/APG4b_g)
### if文
if文はある条件が正しいときのみ処理をしたいときに使います.
Fortranでの書き方は以下のとおりです.

```Fortran
if(条件式) then
    処理
end if
```

条件式が正しいとき`then`から`end if`の間の処理が実行され, 正しくないときには処理が飛ばされます.
以下のプログラムは入力の値が10より小さければ「xは10より小さい」と出力してから「終了」と出力し, 10以上であれば「終了」のみ出力するプログラムです.

```Fortran
program main
    implicit none
    integer x
    read*,x

    if(x<10)then
        print'(A)',"xは10より小さい"
    end if

    print'(A)',"終了"
end program main
```

```:入力
5
```

```:実行結果
xは10より小さい
終了
```

```:入力
11
```

```:実行結果
終了
```

プログラム中の以下のコード

```Fortran
if(x<10)then
    print'(A)',"xは10より小さい"
end if
```

は, `x`が10より小さいとき`xは10より小さい`と出力する, という意味になっています.

### 比較演算子
条件式のところには他の言語と同じく比較演算子を使って記述することが多いです.
比較演算子は以下の6つです

|演算子|意味|
|:---:|:---:|
|`x==y`|xはyと等しい|
|`x/=y`|xはyと等しくない|
|`x>y`|xはyより大きい|
|`x<y`|xはyより小さい|
|`x>=y`|xはy以上である|
|`x<=y`|xはy以下である|

ほとんどC++やPythonと同じですが, 等しくないことを表す演算子が`!=`でなく`/=`であることに注意してください.
以下のプログラムは入力された整数値がどんな条件を満たしているかを出力するプログラムです.

```Fortran
program main
    implicit none
    integer x
    read*,x

    if(x<10)then
        print'(A)',"xは10より小さい"
    end if

    if(x>=20)then
        print'(A)',"xは20以上"
    end if

    if(x==5)then
        print'(A)',"xは5"
    end if

    if(x/=100)then
        print'(A)',"xは100ではない"
    end if

    print'(A)',"終了"
end program main
```

```:入力
5
```

```:実行結果
xは10より小さい
xは5
xは100ではない
終了
```

```:入力
100
```

```:実行結果
xは20以上
終了
```

### 論理演算子
Fortranの代表的な論理演算子を紹介します.

|演算子|意味|真になるとき|
|:---:|:---:|:---:|
|`.not. 条件式`|条件式の結果を反転|条件式が偽|
|`条件式1 .and. 条件式2`|条件式1が真_かつ_条件式2が真|条件式1と条件式2の両方が真|
|`条件式1 .or. 条件式2`|条件式1が真_または_条件式2が真|条件式1と条件式2の少なくともどちらか一方が真|

他にも論理値が等しいことを意味する`.eqv.`や論理値が等しくないことを意味する`.neqv.`がありますが, 筆者自身使った経験がないため説明は省略します.
詳しく知りたい方はこちらをお読みください.
[条件分岐（IF文）- 日本NAG](https://www.nag-j.co.jp/fortran/FI_7.html#_7)

```Fortran
program main
    implicit none
    integer x,y
    read*,x,y

    if(.not.x==y)then
        print'(A)',"xとyは等しくない"
    end if

    if(x==10.and.y==10)then
        print'(A)',"xとyは10"
    end if
    
    if(x==0.or.y==0)then
        print'(A)',"xかyは0"
    end if

    print'(A)',"終了"
end program main
```

```:入力
2 3
```

```:実行結果
xとyは等しくない
終了
```

```:入力
10 10
```

```:実行結果
xとyは10
終了
```

```:入力
0 8
```

```:実行結果
xとyは等しくない
xかyは0
終了
```

### 前の条件が真でないときの処理
#### else
elseはif文の後ろに書くことでif文の条件式を満たさなかったときに処理を行えるようになります.
書き方は以下のとおりです

```Fortran
if(条件式)then
    処理1
else
    処理2
end if
```

以下のプログラムは入力の値が10より小さいときに「xは10より小さい」と出力し, そうでなければ「xは10より小さくない」と出力するプログラムです.

```Fortran
program main
    implicit none
    integer x
    read*,x

    if(x<10)then
        print'(A)',"xは10より小さい"
    else
        print'(A)',"xは10より小さくない"
    end if
end program main
```

```:入力
5
```

```:実行結果
xは10より小さい
```

```:入力
15
```

```:実行結果
xは10より小さくない
```

#### else if
else ifは前のif文の条件が偽かつelse if中の条件が真であるときに処理を行います.
書き方は以下のとおりです.

```Fortran
if(条件式1)then
    処理1
else if(条件式2)then
    処理2
end if
```

条件式1が偽かつ条件式2が真のとき処理2が実行されます.
もちろんelse ifのあとにelse ifを書くこともできますしelse ifのあとにelseも書くことができます.

以下のプログラムはその例です.

```Fortran
program main
    implicit none
    integer x
    read*,x

    if(x<10)then
        print'(A)',"xは10より小さい"
    else if(x>20)then
        print'(A)',"xは10より小さくなくて, 20より大きい"
    else if(x==15)then
        print'(A)',"xは10より小さくなくて, 20より大きくなくて, 15である"
    else
        print'(A)',"xは10より小さくて, 20より大きくなくて, 15でもない"
    end if
end program main
```

```:入力
5
```

```:実行結果
xは10より小さい
```

```:入力
30
```

```:実行結果
xは10より小さくなくて, 20より大きい
```

```:入力
15
```

```:実行結果
xは10より小さくなくて, 20より大きくなくて, 15である
```

```:入力
13
```

```:実行結果
xは10より小さくて, 20より大きくなくて, 15でもない
```

### 注意点
`==`のつもりで`=`と書かないように, そして`!=`のつもりで`/=`と書かないように気をつけましょう.
また, `if`と`else if`では条件式のあとに`then`をつけ,最後に`end if`をつけ忘れないようにしてください.(VSCodeでFortran拡張を入れたら入れてないって教えてくれるので忘れる心配がないです)

### 細かい話
飛ばしても大丈夫です.
#### `then`, `end if`の省略
`if`のみで`else if`や`else`がなく, 処理が1文のみの場合は以下のように`then`と`end if`を省略できます.

```Fortran
if(x<10)print'(A)',"xは10より小さい"
```

ただしC++と違って以下のようにはできないことに注意してください.

```Fortran
if(x<10)print'(A)',"xは10より小さい"
else if(x>20)print'(A)',"xは10より小さくなくて, 20より大きい"
else print'(A)',"xは10より小さくて, 20より大きくない"
```

このように`else if`や`else`を付ける場合は必ず`then`と`end if`をつけ忘れないようにしてください.

https://www.nag-j.co.jp/fortran/FI_7.html
### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
[EX6 - 電卓をつくろう](https://atcoder.jp/contests/apg4b/tasks/APG4b_cq)

標準入力の部分については以下のコードを使用してください.

```Fortran
program ex6
    implicit none
    character(100) line
    integer::A,B,i,cur=1!curは読み取り済みでない場所の先頭
    character(1) op
    !一行まるごと文字列型として読み込む
    read(*,'(A)')line

    !入力された文字列の先頭から終わりまで繰り返し
    do i=1,len_trim(line)
        !i文字目が空白文字のとき
        if(line(i:i)==" ")then
            !1文字目から読み取り済みでないとき
            if(cur==1)then
                !先頭から空白の前の文字までを整数型の変数Aに格納
                read(line(1:i-1),*)A
            else
                !前の空白文字の後ろから2つ目の空白の前までを文字列型の変数opに格納
                op=line(cur:i-1)
            end if
            !読み取り済みでないところにカーソルを移動
            cur=i+1
        end if
    end do
    !読み取り済みでない残りを整数型の変数Bに格納
    read(line(cur:len_trim(line)),*)B
end program ex6
```

このプログラムは1行をまるごと文字列として読み込み, 空白を検知することでそれぞれの変数`A`, `op`, `B`に振り分けて格納するようになっています.
`read*,A,op,B`とすると例えば`5 / 2`と入力した際に`/`が文字列として`op`に格納されず, 実行時エラーとなってしまいます.
これは`/`がFortranでは入力の終わりとして使用されているためだからだそうです.

詳しくはこちらをお読みください.
[Fortran の構成要素 - Oracle](https://docs.oracle.com/cd/E19957-01/806-4841/elements.html)
[read 文と / (スラッシュ) | 計算機の達人への道](https://ameblo.jp/pc-no-tatsujin/entry-10019859625.html)

[解答例](https://atcoder.jp/contests/apg4b/submissions/16008216)

## [1.07.条件式の結果とlogical型](https://atcoder.jp/contests/APG4b/tasks/APG4b_h)
### 条件式の結果
Fortranでは真のことを`.true.`で表現し, 偽のことを`.false.`で表現します.
次のプログラムは条件式の結果をそのまま出力し, 真のときと偽のときでどのような値を取るか確認しています.

```Fortran
program main
    implicit none
    print*,1<2 !真
    print*,1>2 !偽
end program main
```

```:実行結果
 T
 F
```

条件式の部分に直接`.true.`や`.false.`を書くことができます.
次のプログラムはその例です.

```Fortran
program main
    implicit none
    !.true.は真を表すのでhelloと出力される
    if(.true.)print'(A)',"hello" 

    !.false.と書くと偽を表すので出力されない
    if(.false.)print'(A)',"world"
end program main
```

```:実行結果
hello
```

### logical型
_logical型_というデータ型があります.
この型の変数には`.true.`または`.false.`が入ります.

```Fortran
program main
    implicit none
    integer x
    logical::a=.true.,b,c=.false.
    read*,x

    b=x<10

    if(a.and.b)print'(A)',"Hello"
    if(c)print'(A)',"world"
end program main
```

```：実行結果
Hello
```

このように条件式の結果など, 真偽のデータを変数で扱いたい場合はlogical型を扱います.
C++やPythonのように真を`1`で, 偽を`0`で表せないことに注意してください.

### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
[EX7 - bool値パズル](https://atcoder.jp/contests/apg4b/tasks/APG4b_cp)

以下のプログラムを書き換えて使用してください.

```Fortran:書き換えるプログラム
program main
    implicit none
    logical::a=!.true.または.false.
    logical::b=!.true.または.false.
    logical::c=!.true.または.false.

    !ここから先は変更しないこと
    if(a)then
        write(*,fmt='(A)',advance='no')"At"
    else
        write(*,fmt='(A)',advance='no')"Yo"
    end if

    if(.not. a .and. b)then
        write(*,fmt='(A)',advance='no')"Bo"
    else if(.not. b .or. c)then
        write(*,fmt='(A)',advance='no')"Co"
    end if

    if(a.and.b.and.c)then
        write(*,fmt='(A)',advance='no')"foo!"
    else if(.true. .and. .false.)then
        write(*,fmt='(A)',advance='no')"yeah!"
    else if(.not. a .or. c)then
        write(*,fmt='(A)',advance='no')"der"
    end if

    print'(A)',""
end program main
```

[解答例](https://atcoder.jp/contests/apg4b/submissions/16064086)

## [1.08.変数のスコープ](https://atcoder.jp/contests/APG4b/tasks/APG4b_i)
C++では`{ }`で囲った部分をブロックといい, 例えば`if`文の中でも変数を定義することができます.
一方でFortranでは`if`文の中を始めとして__あとから変数の定義をすることができない__という制約があります.
そのため, このようなプログラムを書くとエラーになります.

```Fortran
program main
    implicit none
    integer::x=5
    if(x==5)then
        integer::y=10 !ここでエラーになる
    end if
end program main
```

```標準エラー出力
test.f90:5:50:

    5 |         integer::y=10 !ここでエラーになる
      |                                                  1
Error: Unexpected data declaration statement at (1)
```
そのため, 基本的には以下のように変数はすべてプログラムの冒頭で宣言するようにしましょう.

### block構文について
※かなり発展的な内容になります. 飛ばして問題を解いていただいて構いません.
Fortran2008から`block`構文というものが誕生し, `block`の中であとから変数を定義することができるようになっているそうです.
詳細はこちらをお読みください.

https://www.nag-j.co.jp/nagfor/np53_manual/np53_manual_11_2.html

https://qiita.com/implicit_none/items/55c47407aa376277a531

これに際しコメントを頂いていました.本当にありがとうございます.(遅くなってしまい申し訳ありません)

https://qiita.com/jj1guj/items/43a1c876360ddf180f1f#comment-0e08562664843be1716e

### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
[EX8 - たこ焼きセット](https://atcoder.jp/contests/apg4b/tasks/APG4b_co)

以下のプログラムを書き換えて使用してください.

```Fortran:書き換えるプログラム
program main
    implicit none
    integer p
    read*,p

    !パターン1
    if(p==1)then
        integer price
        read*,price
    end if

    !パターン2
    if(p==2)then
        character(20)text
        integer price
        read*,text,price
    end if

    integer N
    read*,N
    print'(A,A)',text(1:len_trim(text)),"!"
    print'(i0)',price*N
end program main
```
もしプログラムを修正した結果、書き換えるプログラムとの違いが大きくなってしまったとしても、ACができればOKです。


[解答例](https://atcoder.jp/contests/apg4b/submissions/28047807)

## [1.09.複合代入演算子](https://atcoder.jp/contests/APG4b/tasks/APG4b_j)
C++やPythonでは`x=x+1`を`x+=1`のように書くことのできる複合代入演算子というものがあります.
一方でFortranにはこのような複合代入演算子が__存在しません__.
そのため, Fortranでこのようなものを使うとエラーが出ます.

```Fortran
program main
    implicit none
    integer::x=5
    x+=1+2 !x=x+1+2のつもり. エラーが出る
    x-=2 !x=x-2のつもり. エラーが出る
    x*=1+2 !x=x*(1+2)のつもり. エラーが出る
    x/=2 !x=x/2のつもり.
         !エラーは出ないが/=演算子は右辺と左辺が異なるかを
         !判定する比較演算子である.
         !そのため, x/2の計算はされない.

    x%=2 !x=mod(x,2)のつもり. エラーが出る.
         !Fortranで%はそもそも剰余演算子ではない.

    x++ !x=x+1のつもり. エラーが出る
    ++x !x=x+1のつもり. エラーが出る

    x-- !x=x-1のつもり. エラーが出る
    --x !x=x-1のつもり. エラーが出る
end program main
```

### 問題
ここまで読み進めたら以下の問題を解いてみましょう.
__複合代入演算子は使えない__ことに注意してください.
[EX9 - 複合代入演算子を使おう](https://atcoder.jp/contests/apg4b/tasks/APG4b_cn)
[解答例](https://atcoder.jp/contests/apg4b/submissions/28048126)

# 参考文献
* [C++入門 AtCoder Programming Guide for beginners (APG4b) - AtCoder](https://atcoder.jp/contests/APG4b)
* [Fortran 入門 - 日本NAG](https://www.nag-j.co.jp/fortran/index.html)
* [Python入門（Python版 APG4b） - Qiita](https://qiita.com/saba/items/b9418d7b54cce4b106e4)
* [MinGW-w64のダウンロードとインストール | C言語入門 | CppDrive](https://www.javadrive.jp/cstart/install/index6.html)
* [Fortranにおける余り/剰余の計算 - Qiita](https://qiita.com/implicit_none/items/db1e04df8eda0bbc3bef)
* [Fortran の構成要素 - Oracle](https://docs.oracle.com/cd/E19957-01/806-4841/elements.html)
* [read 文と / (スラッシュ) | 計算機の達人への道](https://ameblo.jp/pc-no-tatsujin/entry-10019859625.html)
* [FORTRANのModernizeに使えるいくつかの機能 - Qiita](https://qiita.com/implicit_none/items/55c47407aa376277a531)