こんにちはRockinWoolです。最近は仕事でもマークダウンを使用しているので、少々使い方に幅がでてきたかな・・・という感じです。マークダウンって凄い楽なので良いですね〜。
さて、今日はPythonやCに慣れる日と決めていたので早速実況しながら色々やって行こうと思います。
- Python3.8にアップデート「python3.8からf文字がデフォルトで入ってくるのではないか?」という噂を聞いていたので、そろそろアップデートしておこうと思ってやりました。f文字はprint文の書き方が楽になるやつ。例えば
print(f'バラバシアルバートモデルを追加次数{m}で作成します') 結果>>バラバシアルバートモデルを追加次数2で作成しますといった感じで簡単に書き込むことができる仕組みのことです。噂では先頭のfを入れなくても対応してくれるようになったと聞いていたわけです。以下のコマンドを実行してanaconda(in Ubuntu)のPythonをアップデートしました。conda install python=3.8 - Atcoderに挑戦
- Atcoderへの登録前々から興味あったAtcoderに登録しました。で、最初の練習問題すら解けず(Pythonでもわからなかった)これは再修行が必要だなと思いAtCoder Programing Guide for beginnersをやることにしました。まあ、前々からC++に興味がありましたので、ここの恥はすぐに取り返して来月にはツヨツヨプログラマの仲間入りを果たしてやりたいですね()
- C++の修行の開始まず、C++のプログラムの基本形は
#include <bits/stdc++.h> using namespace std; int main(){ }らしいです(恥ずかしながらほぼコピペ)。もはやプログラマとして自信を持っていた自分が偉く恥ずかしいナウであるわけですが、この呪文の意味を知るところからはじめようと思います。たしかC言語では#include<stdio.h>て感じで標準入出力のヘッダファイルを読み込んでいたような・・・かすかな記憶ですが。調べたらこのヘッダファイルの本体は一般的には/usr/include/stdio.hにあるらしいですね。未だに/usrの立ち位置が分かっていない・・・。というより何も分かっていないんでしょうな私は。ということでbits/stdc++.hについても調べてみました。参考ページ
ふむ。どうやら、普段使うようなc++の基本のライブラリであるlibstdc++(スタンダードC++ライブラリってことなのかな?)を改造してまとめてコンパイルしたプリコンパイル済みのヘッダファイルってことっぽいですね。つまりはこれを#includeしておけば大体使いたいライブラリは揃っているって感じなのでしょう。速さの利点があるため、競技プログラミングの世界では普通に使われているそうですが、linuxの環境以外(というよりGCC)では無いところではそもそもlibstdc++が使えないのでこの呪文もバグの原因になってしまうそう。ちょっと悩みましたが、今の自分の環境もubuntuなのであまり気にせずにどんどん#include<bits/stdc++.h>を使っていって慣れて行こうとおもいます。 - C++の出力実はこれが一番ビックリした内容かもしれません。出力がprintfで無い・・・だと?
#include <bits/stdc++.h> using namespace std; int main() { cout << "Hello_World">>endl; }これはどういうことだ?C++はC言語の拡張だから互換性とかでprintfは使えるのでは無いのか?となったので調べました。
その結果、どうやら2つの理由があるようですね。- C言語のprintfは脆弱性がある
- std::coutは型チェックがあるので異常な出力が出にくい
そういえばこれを調べている時に気づいたのですが、2行目のusing namespace std;を入れることによってstd::coutを使うときにcoutだけで済むようになるらしいです。namespaceというのだからコンテナとかと関係があるのかしら?と踏んでいたのですが、どちらかといえばPythonのimport numpy as npのほうに近いのかしら?一応調べておきます。 - 名前空間ああ、またコイツか。仕事でも出会うヤバイヤツってイメージしか無い。名前空間はコンテナ化に必要な技術で、「こいつを正しく設定することによってシステムの頑強性を高めます!」って謳い文句を何も分かってなさそうなコンサルが上長にオススメしている印象しかない。この際だから慣れてしまおうか。
まず、冒頭のusing namespace std;。こいつはどこからどう読んでも「stdってヤツ(namespace)を使うぜ!」って宣言しているようにしか見えない。解説サイトなどを読んでもstdという名前空間内に様々な関数などを登録しておけば、それをusing namespace stdすることによってstd名前空間内にあるものはそのプログラム内ではグローバル変数チックに登録されるという流れのように見える。
つまり、本質的にfrom numpy import hogeとは異なるものの使い勝手としては大した差は無いという感じかな?個人的にはimport numpy as npのほうが、プログラム内の関数とnumpyの関数が同じ関数名になっても助かる可能性があるので後者のほうが好きなんですよね(トラウマ)。ですので、名前空間をまとめてusing namespace std;するのは流石のツヨツヨ先人の呪文とは言え採用は難しいです・・・。自分はstd::coutって宣言したいなあ・・・。ダメかなあ・・・。
というか結局、基本的にこの程度の隔離がコンテナ空間の隔離にまで至る気持ちがあまりわからなかった・・・。 - コメントの記法これも「ああ、こんな感じだったね・・」ってなった内容です。Pyhtonのコメントは#であるのに対してCは//や/**/でしたわ。
- 細かい話さっき一生懸命(?)探した
#include<bits/stdc++.h>やusing namespace std;の解説が乗ってました。哀れ自分。 coutは#include<iostream>と書くことによって個別に読み込むことができるそうですね。業務ではこちらが推奨されるとも書いてあるので、コンテストでもこちらを使って行こうかしら(気持ちのブレ)。using namespce std;も業務で推奨されないとか書いてあるので極力使わないで行こうかな。 - iostreamの罠ということで例題を解いてみたんですけど、ACになるまでめっちゃかかってしまって自分でも面白かったです。とりあえず今回かいてみた回答はこんな感じ
#include <iostream> int main(){ std::cout << "こんにちは" <<std::endl; std::cout << "AtCoder" <<std::endl; }ミスの一覧: \<iostream>を<iostream.h>と打ってしまってコンパイルエラーint main(){}が正解なのにintを抜いたり、()を抜いたりする- coutのstdを抜く(なんでやねん)
- endlにstdが必要だったのに気づかなかった特にこれが一番悔しかっった。冷静に考えればendlは文字列ではなくendlineを意味する関数であるのは当たり前。iostream内のstdネームスペースのendl関数であったということ。