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

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

ただいまの
回答率

90.50%

  • C

    3699questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • アルゴリズム

    412questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

  • 関数

    220questions

    関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

  • Emacs

    124questions

    GNU Emacsと拡張性の高い、高性能なテキストエディタです。豊富なライブラリの導入により、統合開発環境やWebブラウザとしても機能させる事が可能です。

C言語でテキストファイルを読み、入力された行数のテキストを表示するコード

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 283

tenjin

score 214

前提・実現したいこと

C言語でテキストファイルを読み、入力された行数のテキストを表示しようとしています。
例えば以下の「Hello.dat」というテキストファイルを読み、以下のように2行目と指定して実行すると、テキストファイルの2行目が表示されることを実現したいです。

//Hello.dat
Hello world
Hello C
Hello world
Hello C
Hello world 
Hello C
Hello world
Hello C
Hello world
./example Hello.dat 2
Hello C

該当のソースコード

現状では、以下のコードを実行すると、テキストファイルの中身が全て表示されるコードは実装できています。これをどのように変更していけばいいかわからず、困っています。

#include <stdio.h>
int main(){
  FILE* fp; // file pointer                                                     
  char tmpline[256]; // temporary space                                         
  fp = fopen("Hello.dat", "r"); // open a file                                   
  if (fp != NULL) {
    while (fgets(tmpline, 256, fp)){
      if (tmpline != NULL){
        printf("%s", tmpline);
      }
    } }
  fclose(fp);
  return 0; }
% ./example r
ファイルのデータが全て表示される

試したこと

以下のようなfor文を用いたコードを実行したところ、エラーが出てしまいました。

//trial.c
#include <stdio.h>
int main(){
  FILE* fp; // file pointer                                                    

  char tmpline[256]; // temporary space                                        

  fp = fopen("Hello.dat", "r"); // open a file                                  

  if (fp != NULL) {
    for(int i = 0; fgets(tmpline, 256, fp); ++i){
        printf("%d : %s", i, tmpline);
      }
    }

  fclose(fp);
  return 0; }
% gcc -Wall trial.c -o trial
trial.c: In function 'main':
trial.c:7:5: error: 'for' loop initial declarations are only allowed in C99 mode
     for(int i = 0; fgets(tmpline, 256, fp); ++i){
     ^
trial.c:7:5: note: use option -std=c99 or -std=gnu99 to compile your code

補足情報(言語/FW/ツール等のバージョンなど)

GNU Emacs 22.1.1

  • 気になる質問をクリップする

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 4

checkベストアンサー

+1

ご提示プログラムすこし加えました、ご参考まで

#include <stdio.h>
int main(int argc, char *argv[]){
  FILE* fp; // file pointer
  int i,j;
  char tmpline[256]; // temporary space
  if (argc < 3){
     printf("パラメータ数エラー %d\n",argc);
     return -1;
  }

  char *fname = argv[1];
  j = atoi(argv[2]);
  if (j == 0) {
     printf("ライン数エラー\n");
     return -1;
  }

  fp = fopen(fname, "r"); // open a file
  if( fp == NULL ) {
    printf( "ファイルオープンエラー\n" );
    return -1;
  }
  for (i=1; fgets(tmpline, 256, fp) != NULL; i++){
    if ( i == j ){
      printf("%s", tmpline);
    }
  }
  fclose(fp);
  return 0;
}

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/30 09:41

    ご回答いただきましてありがとうございました。

    キャンセル

  • 2017/12/30 09:43

    if (argc < 3){
    printf("パラメータ数エラー %d\n",argc);
    return -1;
    }
    の部分に関して3以下とされているのは、何故でしょうか。

    キャンセル

  • 2017/12/30 09:51 編集

    ./example Hello.dat 2 とした場合パラメータは3個です。最後の数値が無い場合にargv[2]を参照すると、アドレス例外になるので、これを避ける為です。多い分にはエラーとしていません。

    キャンセル

  • 2017/12/30 09:54

    わかりました。丁寧なご回答とご説明をありがとうございました。

    キャンセル

+1

一番簡単な方法は、whileループをforループに置き換えることだと思います。
あまりにも愚直ですが、これなら直感的に記述可能ですね。

for(int i = 1; fgets(tmpline, 256, fp); ++i){
    printf("%d行目: %s", i, tmpline);
}

なお、コマンドラインから引数を受け取りたい場合は、次のように書けばよいでしょう。

int main(int argc, char **argv) {
    if(argc < 3) {
        printf("USAGE: .exe filename line_num\n");
        return -1;
    }

    char *filename = argv[1];
    int row_num = atoi(argv[2]);

    if(row_num < 1) {
        return -1;
    }

    後略

追記

以下のようなfor文を用いたコードを実行したところ、エラーが出てしまいました。

原因と解決策がもろに書いてあります。まずは表示されたものを読んでください。
単語は日頃カタカナで使うものばかりですし、文法は中学生レベルです。

trial.c:7:5: error: 'for' loop initial declarations are only allowed in C99 mode
trial.c:7:5: note: use option -std=c99 or -std=gnu99 to compile your code

オプションを変えるか、for文の初期化部分を少し書き換えれば良いです。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/29 23:11

    ご回答いただきましてありがとうございます。試したことに、for文を用いたコードとコンパイルエラーを明記させていただきました。可能であれば、このエラーに関してもアドバイスいただけますと幸いです。

    キャンセル

  • 2017/12/29 23:39

    回答に追記した通りです。

    キャンセル

  • 2017/12/30 09:39

    ご回答いただきましてありがとうございました。

    キャンセル

+1

ステップ1

main関数を以下のように変更して、引数の数と引数の文字列を受け取れるようにする。
受け取ったら引数の数をチェックしておこう。
引数の数が2個ならargcには3が入る。なぜなら、argv[0]にはコマンド名が入り、引数はargv[1]から入るのでカウントが1個多くなる。

main(int argc, char *argv[])

ステップ2

引数は文字列で渡されるので、行数にあたる2番目の引数を数値に変換する。
1番目の引数は文字列なのでそのまま使える。
Cの標準ライブラリには文字列をintに変換する関数atoi(3)が用意されている。
以下をソースの先頭に追加すれば使用できる。

#include <stdlib.h>

ステップ3

ファイルを1行読み込む度に回数をカウントする。
それが行数と一致したときだけprint文を実行する。

投稿

編集

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/29 23:28

    ご回答いただきましてありがとうございます。ステップ2がまだ十分に理解できていません。
    #include <stdio.h>
    int main(int argc, char *argv[]){
    FILE* fp; // file pointer
    char tmpline[256]; // temporary space
    fp = fopen("Hello.dat", "r"); // open a file
    if (fp != NULL) {
    for(int i= 1; fgets(tmpline, 256, fp); ++i){
    if (i == argc){
    printf("%s", tmpline);
    }
    }
    }

    fclose(fp);
    return 0;
    }
    現状で理解できている範囲でコードを書いたものです。

    キャンセル

  • 2017/12/29 23:48 編集

    ステップ2に追記しました。
    2番目の引数はargv[2]に文字列で入っています。

    キャンセル

  • 2017/12/30 09:39

    追記のご説明をいただきましてありがとうございました。
    大変助かりました。

    キャンセル

+1

一歩ずつ進みましょう。
「int型変数iを1から10までカウントアップして、2のときだけ表示する」
というプログラムをまず作ってみましょう。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/12/29 22:50

    for(int i= 1; i<=10; ++i){
    if (i == 2){
    printf("%s", tmpline);
    }
    }
    でしょうか。

    キャンセル

  • 2017/12/29 22:58

    これがすっと出来るのに、元の質問がわからないというのは、どの部分がわからないのでしょうか?

    int main() と書いていると言うことは、コマンドライン引数が分からないんですかね。
    コマンドライン引数の1番目は、int main(int argc, char **argv){ ~と書いて、
    argv[1] で参照できます。引数があるときにはargcが2以上になるので、それも確認します。
    argv[1] は文字列なので、intにするにはatoi()等を使います。

    キャンセル

  • 2017/12/30 09:40

    ご回答いただきましてありがとうございました。

    キャンセル

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

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

関連した質問

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

  • C

    3699questions

    C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

  • アルゴリズム

    412questions

    アルゴリズムとは、定められた目的を達成するために、プログラムの理論的な動作を定義するものです。

  • 関数

    220questions

    関数(ファンクション・メソッド・サブルーチンとも呼ばれる)は、はプログラムのコードの一部であり、ある特定のタスクを処理するように設計されたものです。

  • Emacs

    124questions

    GNU Emacsと拡張性の高い、高性能なテキストエディタです。豊富なライブラリの導入により、統合開発環境やWebブラウザとしても機能させる事が可能です。