NodeSchoolでNode.jsの学習を始めよう!#2 - 問題1〜3の解答と解説
こんにちは、ちゃんとくです!
前回の記事で、NodeSchoolの概要と基本の解き方を紹介しました。
今回はカリキュラム「learnyounode」の問題1〜3の解答を解説付きで紹介したいと思います!
※筆者はMacユーザのため、基本的にMacに沿った説明になっています。Windows向けの説明も書いていますが、わからないときは適宜調べてみてください。
はじめに
さっそく問題を解いていきましょう。インストール方法や基本の解き方は前回記事をチェック!
$ cd /your/working/directory
まずは解答用のファイルを作成するディレクトリに移動します。パスはご自身のものに置き換えてください。
おさらいですが、$
マークはコマンドラインであることを表しているので不要ですよ!
$ learnyounode
「learnyounode」コマンドでNodeSchoolのカリキュラムを起動します。
こんな画面が立ち上がりましたか?カーソルキーで問題を選択します。1問目の「こんにちは世界」からやっていきましょう!
問題1「こんにちは世界」
コンソール (stdout) に “こんにちは世界”と出力するアプリを書いてください。
問題の「コンソール」とは今表示しているコマンドラインツール、「アプリ」とはここでは「Node.jsのプログラム」を意味しています。
この問題は「実行するとコマンドラインに”こんにちは世界”と表示させるプログラムを書いてみましょう」ということです。
ヒントを読んでみると、
Node.jsのアプリを作るためには .jsという拡張子を持つファイルを新規に作ってJavaScriptを書くだけです。
とあるので、.js
という拡張子のファイルを作りましょう。
今回は1.jsというファイルを作ったので、エディタでファイルを開き、編集していきます。(操作がよくわからないという方は前回記事を確認!)
さらにヒントを読んでいくと、console.log("text")
と書くとコンソールに出力できます、とありますね。
console.log()
は「渡したものをコンソールに表示してね」という命令です。関数の()
に入れたものは「引数」と呼ばれ、関数に渡されます。
上記はconsole.log()
というメソッドに、"text"
という引数を渡している状態です。
""
(または''
)は、型が「文字列」であることを表しています(その他の型は今後登場します)。
つまり「こんにちは世界」という文字列を表示させたい場合は、console.log()
の引数に"こんにちは世界"
を渡してあげればよいですね!
解答
console.log("こんにちは世界");
解答用のファイルに、上記のプログラムを書き込みましょう。
$ node 1.js
Node.jsでファイルを実行して試してみます。
こんにちは世界、と表示されました。これで良さそうですね!
$ learnyounode verify 1.js
上記コマンドを実行して答え合わせをします。正解したら次の問題へ進みましょう!
問題2「ベイビーステップ」
1つ以上の整数をコマンドライン引数として受け取り、それらを足し合わせた値をコンソール(stdout)に出力するコマンドラインアプリを書いてください。
ちょっとレベルが上がりました。先ほどは関数に直接引数を渡しましたが、「コマンドライン引数」は、コマンドラインからプログラムに渡すものを指します。
コマンドライン引数を読むためにはグローバル変数の process というオブジェクトが使えます。process には argv という配列のプロパティがあります。その配列の中には全てのコマンドライン引数が入っています。
とヒントに書いてあります。
まずprocess.argv
の挙動を探るため、console.log()
を使って表示させてみましょう。
console.log(process.argv);
上記のようなプログラムを書いた.js
ファイルを作成します(2.js
というファイルにしました)。
$ node 2.js "hello"
プログラムに"hello"
という文字列を渡してみます。
こんな感じの答えが返ってきました。[]
は「配列」を表していて、,
で区切られた3つの要素が入っています。
1つ目の要素の/Users/yuka/.nodebrew/node/v9.3.0/bin/node
は皆さんのNode.jsがインストールされているパス、2つ目の要素の/Users/yuka/workspace/nodeschool/learnyounode/2.js
は今実行したファイルのパス、3つ目の要素には渡したコマンドライン引数が入っています。
コマンドライン引数を表示させるには、process.argv
の3つ目の要素を取り出してあげると良さそうです!
試しにこんなプログラムを書いてみましょう。
console.log(process.argv[2]);
配列の中身の位置を指定して取り出すには、[]
を使います。配列の序列は0から始まるので、3つ目の要素は「0,1,2」で「2」となります。
このファイルに、先ほどと同様"hello"
を渡してみます。
コマンドライン引数だけを表示することができました!
ではいくつかの引数を渡して足し算するプログラムを書いてみます。
console.log(process.argv[2]+process.argv[3]);
こんなプログラムを書いてみます。
$ node 2.js 1 1
実行して試してみます。
「2」となって欲しいところ、「11」となってしまいました。
これは、「1」という文字列と「1」という文字列をくっつけた結果になってしまっています(ちょっとわからない、という人は$ node 2.js "hel" "lo"
など実行してみてください)。
process.argv
の要素は全て文字列になるので、プログラムには「これは数字だよ!」と教えてあげないと、わかってくれないんですね。
ヒントを読んでみると、数字に変換する方法が書いてあります。
変換するには、数字の前に + を書きます。Number()を使う方法もあります。
数字の前に+
をつけるか、
console.log(+process.argv[2] + +process.argv[3]);
Number()
という関数を使って文字列を数字に変換してあげます。
console.log(Number(process.argv[2]) + Number(process.argv[3]));
エラーが出てしまった人は、Number()
の頭文字が大文字になっているか、()の数が合っているかなど確認してみてくださいね。
問題3「初めてのI/O!」
同期処理をするファイルシステムの関数を使ってファイルの改行文字(\n)の数を出力するアプリを書いてください。
3問目です。この問題は少し難しいので、「ファイルの中身を取り出す」ステップと、「改行を数える」ステップに分けてみます。
ファイルの中身を取り出す
「同期処理?ファイルシステムの関数???」となりますね。
Node.jsには、あらかじめ色々な関数を用意してくれているモジュール(パッケージのようなもの)があります。その一つがfs
(file system)というモジュールです。
fs
には、ファイルを扱うためのいろいろな関数が用意されています。
var fs = require('fs');
モジュールを呼び出すためには、上記のように記述します。
var
は、「変数の宣言」です(最近はvar
ではなくconst
が推奨)。var fs
のfs
は「変数名」で、任意の名前を付けられます。「fs」という名前の箱に、require('fs')
の結果を収納しているイメージです。
require()
はモジュールを呼び出す関数、引数には文字列でモジュールの名前を渡します。
var fs = require('fs');
console.log(fs.readFileSync(process.argv[2]));
3.js
というファイルを作って、上記のようなプログラムでfs
の機能を試してみましょう。ヒントによるとfs.readFileSync()
の引数には読み込むファイルのパスを指定するので、コマンドライン引数で渡すようにしてみます。
読み込みを試す用に、sample.txt
というテキストファイルを作ってみました。
$ node 3.js ./sample.txt
実行して試してみます(./
は現在の位置です)。
こんな結果が出ました。「なんじゃこりゃ!」ですね
readFileSync()
は「Bufferオブジェクト」という形式でファイルの中身を返します。これを文字列に変換するには、toString()
という関数を使います。
var fs = require('fs');
var buf = fs.readFileSync(process.argv[2]);
var text = buf.toString();
console.log(text);
取り出したものを変換してからconsole.log()
してみましょう。
文字列として取り出すことができました!
改行を数える
改行を数えるには、ヒントのようにsplit()
を使ってみます。
JavaScriptの String は .split() 関数を使って分割出来ます。\n を区切り文字として使えば String を1行ずつに分割した Array を受け取ることが出来ます。ただし、ファイルの最後の改行には気をつけてください。
下記のようなプログラムで、文字列を\n
で分割してみます(\n
は改行を表しています)。
var fs = require('fs');
var buf = fs.readFileSync(process.argv[2]);
var text = buf.toString();
var array = text.split('\n');
console.log(array);
実行してみます。
ファイルの中身を\n
で区切ることができました!
ただし、ヒントにあるように、最後に意図しない''
が入っていますね。これはファイルの最後には改行が入るようになっているためです。
なので、改行の数を数えるには「要素の数 - 1」をしてあげればよさそうです。
「こんな関数使いたい!」というときは「JavaScript 配列 要素 数える」などと検索してみましょう。配列の要素を数えるためには、Array.length
というプロパティを使います。
var fs = require('fs');
var buf = fs.readFileSync(process.argv[2]);
var text = buf.toString();
var array = text.split('\n');
var n_num = array.length - 1;
console.log(n_num);
上記のように、配列.length
で要素数を数え、最後の改行分の1を引いてみます。
意図した数字になりました!
$ learnyounode verify 3.js
で答え合わせです。
まとめ
これで「learnyounode」の1〜3問目は終了です。お疲れ様でした!
プログラミングを初めて学ぶ方は、新しい情報が多く難しく感じたかもしれません。でも問題を解きながら変数や関数に慣れていけば、「おっ、こういうことか」とわかる瞬間がくるはずです!
めげずにNode.js勉強頑張っていきましょう!