質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.51%

ファイルの先頭から指定した行数分表示するときコマンド数が2の時10行表示するには

受付中

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 1,516

sanchu52

score 177

>conhead  test.c -n5で→test.c ファイルの中身を先頭から5行表示するプログラムで
 >conhead  test.cとしたとき、デフォルトで10行表示したいのですが、うまくいきません。main()のelse if(argc<3)を書き換えればいいと思うのですが、どのようにすればいいでしょうか。

コード
#include <stdio.h>
#include <stdlib.h>                 // exit()のため必要
#include <string.h>

int put_data(int m)
{    
    FILE *fin;
    FILE *fout;
    char InputFileName[256];        // 読み込みファイル名
    char OutputFileName[256];        // 書き出しファイル名
    char textbuffer[512];             // テキストを読み込む作業用文字列

    int line_no=1;

    printf("読み込みファイル名 : ");
    gets(InputFileName);            // 読み込みファイル名の取得

    printf("書き出しファイル名 : ");
    gets(OutputFileName);            // 書き出しファイル名の取得

    fin=fopen(InputFileName,"r");
    if (fin==NULL) {
         printf("can't open file <%s>\n",InputFileName);
         exit(1);                    //ファイルオープンエラーで緊急停止
    }

     fout=fopen(OutputFileName,"w");
    if (fout==NULL) {
            printf("can't open file <%s>\n",OutputFileName);
            exit(1);                    //ファイルオープンエラーで緊急停止
    }

    while (line_no < m) { 
            fgets(textbuffer,512,fin);

                //ファイル読み込みエラーでない限り                            
                //fgets(textbuffer,512,fin)とはファイルfinから一行読み込み,
                //文字配列textbufferに保存しなさいの意味。                    
                //ただし,文字列長制限があり511文字まで                        
            fprintf(fout,"%04d %s",line_no,textbuffer);
            fprintf(stdout ,"%04d %s",line_no, textbuffer );
            line_no++;
    }
    m=0; 

    fclose(fin);
    fclose(fout);
    return 0;
}

void  copy(FILE *src, FILE *dst);     // srcが指す文字列をdstが指す配列にコピーする。

int max = 11;
int main(int argc,char* argv[])
{
    char *max,*max1;
    int     m;

    FILE *fp;

    if(argc<2) {
        copy(stdin, stdout);        // コマンドライン引数が1のとき 
    }
    else if(argc<3) {                 // コマンドライン引数が2のとき 
        fp =fopen(argv[1], "r");
        copy(fp, stdout);
        fclose(fp);
    } 
    else if(argc<4) {                // コマンドライン引数が3(C:\Users\username\chap09\kadai>conhead abc.c -n5)のとき 
        m=strlen(argv[2]);

        if(m==3){
            max=&argv[2][2];
            m=*max-'0';
            printf("mは「%d」です\n",m);
            ++m;
        }
        if(m==4){
            max =&argv[2][2];
            max1=&argv[2][3];

               m=*max-'0';
            m =m*10 + *max1-'0';
            printf("mは「%d」です\n",m);
            ++m;
        }   
        put_data(m);
    }
    return 0;

}

void  copy(FILE *src, FILE *dst)    // srcが指す文字列をdstが指す配列にコピーする。
{
    int ch;
    int i;
    int max;

          while ((ch = fgetc(src)) != EOF) { 
            fputc(ch, dst);
            if(ch == '\n')          //改行をカウント
                  i++;
                  if(i ==  max)
                         break;
        }
}
/* 実行時のコンソール画面
C:\MinGW\users\chap09\kadai>gcc -I. -o kad9-5 kad9-5.c pdcurses.a


C:\MinGW\users\chap09\kadai> kad9-5 a.c -n8
mは「8」です
読み込みファイル名 : a.c
書き出しファイル名 : b.txt
0001 /*プログラムソースファイルを行ごとに読み込んで,行頭に行番号
をつけて,テキストファイルに書き出す。
0002
0003 あらかじめチェック用プログラムソースファイル「a.c」をテキス
トエディタでつくってから実行し,
0004 「b.txt」が出来たことを確認して,テキストエディタで「b.txt」
を見るとよい。
0005
0006 関数fgets()は,ファイルから一行を読み込み文字列にする。
0007 一行とは,改行文字があるところまでの文字列。
0008

C:\MinGW\users\chap09\kadai>
  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

0

copy関数内のmaxの値が不定です。(グローバル変数maxとここのmaxは別物です。)

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

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

引数maxを追加するのが最もシンプルに思えます。
グローバル変数を使っても解決出来ますが、あまり良い作法とは言えないでしょう。

ついでに言うと、iの値が不定なのもよくないですね。
何らかの変数を参照する際には、適切に初期化されているか確認する癖をつけた方が良いです。


適当に作ってみました。

void copy(FILE *src, FILE *dst, int max) {
    char ch;
    for(int i = 0; i < max; i++) {
        while((ch = fgetc(src)) != '\n') {
            if(ch == EOF) return;

            fputc(ch, dst);
        }
        fputc('\n', dst);
    }
}

Cではデフォルト引数が(確か)使えないので、10という数値は呼び出し側で指定してください。
デフォルト引数もオーバーロードも工夫なしに使えないのは不便ですね...

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/11/02 21:03

    こんばんわ いつもお世話になっています。通常は-n8で行数を指定するのですが、指定しない場合は10行表示するようにしたいのですが。

    キャンセル

  • 2017/11/02 21:14

    -nオプションのない場合は呼び出し側で10を指定するのが最もシンプルです。
    工夫次第でいろいろ出来ないことはないですが、この『デフォルト値10』という情報をmain関数が知っていてもそんなに問題はない気がします。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.51%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

同じタグがついた質問を見る

  • トップ
  • Cに関する質問
  • ファイルの先頭から指定した行数分表示するときコマンド数が2の時10行表示するには