しずくぶろぐ

競技ぷろぐらみんぐしたり、なんかしたりします

入出力をできるようにしよう #雫ぷよ

Fortranでやっていると、入出力ができないせいでパフォーマンスが伸びないということがあるのでまとめました

入力:基本

私は基本

integer a,b
read*,a,b

のようにread*,で読み込んでいます。ここはread(*,*)などいろんな読みこませ方をする人がいます。*はなんかうまいこと読み込んでおいてくれといった意味合いです。
よくある

5
1 2 3 4 5

と先に配列の大きさが与えられてそのあとに要素が一列で与えられるものは

integer N
integer,allocatable,dimension(:)::P
read*,N
allocate(P(N))
read*,P

という感じに読み込んでいます。
例えばこういう問題とか
atcoder.jp

大変だった入力1

列の先頭に配列の大きさが与えられてその真後ろに要素が一列で与えられるもの
atcoder.jp
この場合allocateしている暇がないので余裕を持たせた配列を準備しておいて読ませます。*1
例えば

4 1 1 1 1

というものであれば

integer k
integer reader(10)
read*,k,reader(1:k)

とやると読み込ませることが可能です。

大変だった入力2

これは滅多にないと思うんですが0*で始まる文字列をread*,で読み込むとエラーを起こします。
ちなみにここで出てきました。
atcoder.jp
これはread*,で式を読み込むのではなく

character(10**5) S
read"(A)",S

と形式を指定して読み込ませてやるとうまくいきます。

追記.
全くの空白を読み込ませてくるときも同様です。
yukicoder.me

大変だった入力3

Query を受け取る際、行の途中まで読み込んで、また続きから読み込みたいときがあると思います。
そのときは、read(*,"(A)",advance="no")として読み込ませます。
ここで出てきました。
atcoder.jp

read(*,"(A)",advance="no") Q1

これでクエリが複数出てくる問題にも対応できそうです。

これに限らず型の指定をきっちりした方がミスなく読み込みやすいかもしれません。

出力:基本

大抵はprint"(A)"かprint"(i0)"で済みます。print*でうまくいくときもありますが、怖いので毎回形式を整えています。print"(I0)"が整数用でprint"(A)"が文字列です。

integer N
character(3) S
N=3
S="ABC"
print"(i0)",N
print"(A)",S
end

こんな感じです。
他にもwrite文使っている人などがいます。

特殊な出力1

出力するものが実数のときは

print"(f0.10)",bo

のようにやります10のところを大きくすると出てくる桁数が大きくなります。

atcoder.jp

特殊な出力2

配列をスペース一字空けで出力するとき

atcoder.jp
このときはprint文ではなくwrite文を使いました。

write(*,'(i0)', advance='no') A(1)
do i=2,len_trim(S)
  write(*,'(x,i0)', advance='no')A(i)
end do
write(*,*)

こんな感じです。advance='no'で改行しないようにしています。最後のwrite(*,*)は改行の為に必要です、多分。

特殊な出力3

100を000100など桁数が足りない分を0で埋めたいとき

atcoder.jp
これは12桁でした

  print"(i12.12)",ans

*1:実際これしか方法がないのかは詳しくないので断言できないけど