🌏

[CS50x学習メモ] Week 1: C (1/2)

2023/02/14に公開

導入

Week 1はC言語。前回はScratchというグラフィカルな(パズルピースを組み立てるような)プログラミングを行ったが、暗号文や記号のような不可解なものに変わっていく
これからScratch、C、Pythonなど言語に関わらず、学んで書いていく物をsource codeと呼ぶが、Computerは二進数(binary digit)しかわからないため、0と1のパターンで表されたmachine codeが必要となる
つまりは人間が書いたsource codeをmachine codeにする必要がある
    input → □ → output
source code → □ → machine code
この□に当てはまる部分をcompilerと呼ぶ

大事なこと

・やるべきことをする
・正しくしたい
・適切(良い)な設計 correctness, design, style
=多くの場合適切な設計だと、高速で保守しやすい
スタイル美学

VSCode(Visual Studio Code)

紙の上やメモ帳、Wordなどにもsource codeを書くこともできるが、書いて、コンパイルし、実行することができるVSCodeを使っていく
VSCode for CS50x
※課題提出のため、[Log in via GitHub]でGitHubアカウントと連携しています
※VSCodeの画面説明
右上部が実際にコードを書く場所
TERMINAL window(Command line, interface, CLI)
GUI(Graphycal User Interface)とは対称なもの
アイコンを選択しクリック…するよりもキーボード入力の方が効率的なので、TERMINALを使ってコードをコンパイルしたり実行したりします

画面左側には見慣れたファイルエクスプローラー(自分のアカウントのファイルがツリー表示で見える)や、アクティビティバーなどがあり、GUIとCLIの両方が提供されているが、CS50の授業ではCLIのTERMINAL windowを主に使いGUIは非表示にして授業を進めていく

TERMINALには$が表示されているが、これはタイプコマンドでカーソルのようなもの

準備とC言語でのHello, world

VSCodeのTERMINALに、書いて実行するのが一番簡単。
$の後にcode hello.cを入力しEnterを押すと、上部にhello.cのタブが開く

#include <stdio.h>

int main(void)
{
    printf("hello, world\n");
}

まずは実際に始めてのsource codeを実行してみたいが、Scratchのように緑の旗や、コンパイル・実行するアイコン・GUIはない。では、どうするか
TERMINALに戻り、2行目の$が表示されている(コマンド準備OK状態)箇所へいき、実際の動くプログラムへコンパイルします
$の後ろにmake helloと入力し、Enter

何も起きず、次の行に$が表示されたらそれはいいこと。エラーメッセージもミスもなにもない!
次に実行をするにはどうするか、$の表示は次のコマンド待機中なので、そこに./helloを入力し

Enterを押す。TERMINALにhello.cが実行され、Hello, worldが表示される
これでC言語の初めてのプログラムが完成。

Hello, worldプログラムの深堀り

VSCodeの非表示にしたエクスプローラーを見てみるとhello,ハイライトされたhello.cが入っている。ハイライトはタブで開いているためである。
ただのhelloがプログラムで、CLI上ではできないが、通常のPC上での作業に例えるなら、「プログラムをダブルクリックしたら実行」をTERMINALでコマンドから行った形になる

VSCodeやほかのテキストエディタには自動的に色を変えたりハイライトされたりする機能がある
この色の設定は自分で変更することができScratchのブロックのような決まりはない

Scratchのsayコマンドに該当するC言語の関数はprintf()。fはフォーマット済の意味
C言語として書くには、括弧の中身を「文字」として扱うための""や文末の;など必要な構文が沢山あってミスしやすい。これらがScratchから始める理由とのこと。

ミスをしたら(エラーメッセージの読み方)

ミスをしたら何が起こるのかの説明。
挙動としては、TERMINALにエラーメッセージが表示され、コンパイルされない

ファイル名:行:文字数 error: 内容のような形で、source codeの何行目にどんなエラーがあるのか、何が必要なのかの提案が表示される(提案は必ずあるわけではない)
エラーの内容を修正し、make helloで再コンパイルし、何も起きなければ再コンパイル完了となる

\nの意味
構文的には不必要なコマンドですが、特殊な記号でCだけでなくPythonでも使う"escape sequences"で、次の行にカーソルを送ります

header files(libraries)の必要性

C言語ではいろいろな機能・動作をする(今回はまずprintf)時に、それがどんな機能なのかが分からない状態からスタートする。そのため、標準的な機能セットを冒頭(Header)に入れなければいけない。
この#include <stdio.h>の部分は、コンパイラにstandard I/Oの機能を使用したいよ‼というお知らせになる
standard I/Oがなかったり、違うライブラリを入れてしまった場合は、その関数がどんな挙動をするのかが分からず、動かないので注意。
各ライブラリにどんな関数が含まれているのかは、マニュアルサイトを参照すること(使い方や引数の指定方法も記載されている)

CS50用のライブラリの提供について

  • manual.cs50.io/#cs50.h
    この中にはユーザーのキーボード入力から、文字列や整数、小数点、長文文字列などを取得する関数などが含まれているので、これらを使用して課題を行っていく

Practics

実際にライブラリを使ってみよう
モデル化したものを考えてみると
arguments → [function] → return value
return value(戻り値)部分がScratchでは自動的に返ってきていたが、Cでは戻り値に任意の名前を付けることができる
※戻り値は使用したり再利用できる

先週のScratchのHello, worldをCにしてみよう
ブロックでask (What's your name?) and waitブロックに対し、ユーザーのインプットanswerをCにすると、文字列をユーザーに入力してもらう必要があるのでget_stringを使う。また、戻り値に任意で名前を付けることができるのでanswerとし、この変数が文字列であることもコンパイラに伝える必要がある。
結果的に、ブロック部分のみをCに書き換えると
string answer = get_string("What's your name? ")となる

上記を踏まえ、実際のコードも考えるとどうなるか

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string answer = get_string("What's your name? ");
    printf("hello, answer\n");
}

コンパイルして実行してみると、hello, answerが表示される
answerの内容ではなく、単なる文字のanswerが表示されてしまった
どこが間違えているのか?
Scratchのブロックを思い出してみると[say(join(hello,)(answer)]のようなブロック構造だったが、上のCではsayに該当する部分にprintfを用いている。ここで、前の行に取得したget_stringの戻り値であるstring answerを使いたい場合、文字列(string)なので%sを入れる必要がでてくる

#include <cs50.h>
#include <stdio.h>

int main(void)
{
    string answer = get_string("What's your name? ");
    printf("hello, %s\n", answer);
}

ここで一旦講義にも休憩が入ったので前編として区切ります

Discussion