Mac(BSD 系) のwc とlinux(GNU 系) のwc は行数の数え方が違うのね
最近はlinux の勉強をしています。サーバ触ることになったからというのと、プログラミングの基礎知識が足りないと感じたためです。
プロセスとか、ストリームとか、その辺りの理解も曖昧だったしね。青木さんの「ふつうのLinux プログラミング」で勉強してます。超良い本。
ふつうのLinuxプログラミング Linuxの仕組みから学べるgccプログラミングの王道
- 作者: 青木峰郎
- 出版社/メーカー: ソフトバンククリエイティブ
- 発売日: 2005/07/27
- メディア: 単行本
- 購入: 35人 クリック: 450回
- この商品を含むブログ (150件) を見る
この本の6章の練習問題に「wc -l」のように、ファイルの行数を数えるプログラムを書く課題があります。
例えば自分で最初に書いたのはこんなの。1文字ずつ読んで改行の数を数えるという超単純。
- wc.c
#include <stdio.h> #include <stdlib.h> static int line_count(); int main(int argc, char *argv[]) { int result; result = line_count(); printf("%d\n", result); exit(0); } static int line_count() { int counter = 0; int c; while((c = getchar()) != EOF) { if(c == '\n') counter++; } return counter; }
1文字でなく行毎に読み込む方法をとるとline_count はこんな感じ。
#include <string.h> # main は同じ・・・ #define BUFSIZE 1024 static int line_count() { char buf[BUFSIZE]; int counter = 0; while(fgets(buf, sizeof buf, stdin)) { if((buf[(int)strlen(buf) - 1]) == '\n') counter++; } return counter; }
実行結果はこんな感じ。
- test.txt
test hoge
$./wc < test.txt 2 $ wc -l test.txt 2
このtest.txt は2行目の最後に改行が入っています。この改行を外すと、結果は以下のようになります。
- test.txt
test hoge
$./wc < test.txt 1 $ wc -l test.txt 1
これは2行なんじゃないか?でも、オリジナルのwc とあってるからいいか・・・( ・ิω・ิ)
しかし、解答例を見て作り直してみると以下のような感じになりました。
- wc.c
#include <stdio.h> #include <stdlib.h> static int line_count(); int main(int argc, char *argv[]) { int result; result = line_count(); printf("%d\n", result); exit(0); } static int line_count() { int counter = 0; int c; char prev = '\n'; // for empty file while((c = getchar()) != EOF) { if(c == '\n') counter++; prev = c; } if(c != '\n') counter++; // for missing LF at the end of file return counter; }
実行結果。
- test.txt
test hoge
$./wc < test.txt 2
はうぁ(⊃д⊂)
きちんと、最後の行に改行がない場合も1行とカウントするようになってる。Mac のwc はあくまで「行数=改行の数」の模様。