明解C言語中級編 9章の自由課題5、6を解いてみた

さてさて、今回は簡易版headコマンドと簡易版tailコマンドです。

どんなコマンドかと言いますと

head は入力の先頭10行を標準出力に表示する。表示すべき行数はコマンド行オプションで変更できる。
tail は入力の末尾10行を標準出力に表示する。表示すべき行数はコマンド行オプションで指定でき、表示単位(行、ブロック、バイトなど)も変更できる。

てな感じです。Wikipediaのコピペですが。

これは簡易版ということで、オプションは-nだけで、本家コマンドのようなオプション付加時のスペースだったり、パイプで渡したときの動作だったり色々なことはできません。

そーす headmimic.c

#include <stdio.h>

int max = 10;  // 指定しないときは10行

void
copy(FILE *src, FILE *dst)
{
   int ch;
   int i;

   while((ch = fgetc(src)) != EOF ){
     fputc(ch, dst);
     if(ch == '\n')          //改行をカウント
       i++;
       if(i ==  max)
         break;
   }
}

int
main(int argc, char *argv[])
{
   FILE *fp;

   if(argc < 2)
     copy(stdin, stdout);    // 引数がないときは標準入力を標準出力に返す
   else{
     while(--argc > 0){
       if(**(++argv) == '-'){
         if(*++(*argv) == 'n')
           max = atoi(++*argv);
         else{
           fputs("パラメタが不正\n", stderr);
           return 1;
         }
       }else if((fp =fopen(*argv, "r")) == NULL ){
         fprintf(stderr, "ファイル%sが正しくオープンできません。\n",
           *argv);
         return 1;
       }else{
         copy(fp, stdout);
         fclose(fp);
       }
     }
   }
   return 0;
}

実行結果

$ ./headmimic -n7 /etc/httpd/conf/httpd.conf
#
# This is the main Apache server configuration file.  It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs/2.2/> for detailed information.
# In particular, see
# <URL:http://httpd.apache.org/docs/2.2/mod/directives.html>
# for a discussion of each configuration directive.

 

そーす tailmimic.c

#include <stdio.h>

int max = 10;  // 指定しないときは10行

void
copy(FILE *src, FILE *dst)
{
   int ch, ch2;
   int i, j;
   long pos;

   pos = ftell(src); //読み書き位置を記録

   i = j = 0;
   while((ch = fgetc(src)) != EOF ){
     if(ch == '\n')          //いったん改行を全てカウント
       i++;
   }

   fseek(src, pos, SEEK_SET); // 位置を戻す

   while((ch = fgetc(src)) != EOF){
     if(ch == '\n')
       j++;
       if(j >= i - max)
       fputc(ch, dst);
   }
}

int
main(int argc, char *argv[])
{
   FILE *fp;

   if(argc < 2)
     copy(stdin, stdout);    // 引数がないときは標準入力を標準出力に返す
   else{
     while(--argc > 0){
       if(**(++argv) == '-'){
         if(*++(*argv) == 'n')
           max = atoi(++*argv);
         else{
           fputs("パラメタが不正\n", stderr);
           return 1;
         }
       }else if((fp =fopen(*argv, "r")) == NULL ){
         fprintf(stderr, "ファイル%sが正しくオープンできません。\n",
           *argv);
         return 1;
       }else{
         copy(fp, stdout);
         fclose(fp);
       }
     }
   }
   return 0;
}

実行結果

$ ./tailmimic /etc/httpd/conf/httpd.conf

# The first VirtualHost section is used for requests without a known
# server name.
#
#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host.example.com
#    DocumentRoot /www/docs/dummy-host.example.com
#    ServerName dummy-host.example.com
#    ErrorLog logs/dummy-host.example.com-error_log
#    CustomLog logs/dummy-host.example.com-access_log common
#</VirtualHost>
$ ./tailmimic -n7 /etc/httpd/conf/httpd.conf

#<VirtualHost *:80>
#    ServerAdmin webmaster@dummy-host.example.com
#    DocumentRoot /www/docs/dummy-host.example.com
#    ServerName dummy-host.example.com
#    ErrorLog logs/dummy-host.example.com-error_log
#    CustomLog logs/dummy-host.example.com-access_log common
#</VirtualHost>

例題に簡易catコマンドがあるので、それをいじっただけですが、こういうのは楽しいね(^^)