カレントディレクトリ内の検索

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
天和

カレントディレクトリ内の検索

#1

投稿記事 by 天和 » 15年前

perl言語で書かれた次のスクリプトmygrep.plと同等以上のコマンドをC言語として書きなさい
# grep for perl version
# Usage: mygrep pattern file1 file2 ...
#

if (@ARGV < 1) {
    die "Usage: mygrep pattern [file..]\n";
}

$pattern = shift;
foreach $file (@ARGV) {
    open(FILE, $file);
    $line = 1;
    while (<FILE>) {
    print "$file $line: $_" if /$pattern/o;
    $line++;
    }
    close(FILE);
}
つまり.cファイル内にある例えばprintfと検索かけたらカレントディレクトリ内にあるファイルの中にある
printfと書いてある文字列を全部書き出しなさいということです
使用環境はVISUALC++ GCC(基本あとでGCCに書き直します)
使用技術レベルは・・・ファイルの入出力の基本ぐらいです。

また
まずはカレントディレクトリ内にある.cファイルを全部ファイル名とファイル内を出力させるところから始めようと思いますので
http://www5c.biglobe.ne.jp/~ecb/c/c00.htmlというところで
ファイルの検索のやり方が書いてあったので(理解できてませんが)
#include <stdio.h>
#include <io.h>
#include <time.h>

void main( void ){
    struct _finddata_t c_file;
    long   hFile;

    // カレント ディレクトリ内の最初のファイルを探します。
    if( (hFile = _findfirst( "*.*", &c_file )) == -1L )
       printf( "カレント ディレクトリにはファイルは存在しません。\n" );
    else{
        printf( "ファイルのリスト\n\n" );
        printf( "RDO HID SYS ARC  FILE         DATE %25c SIZE\n", ' ' );
        printf( "--- --- --- ---  ----         ---- %25c ----\n", ' ' );
        printf( ( c_file.attrib & _A_RDONLY ) ? " Y  " : " N  " );
        printf( ( c_file.attrib & _A_SYSTEM ) ? " Y  " : " N  " );
        printf( ( c_file.attrib & _A_HIDDEN ) ? " Y  " : " N  " );
        printf( ( c_file.attrib & _A_ARCH )   ? " Y  " : " N  " );
        printf( " %-12s %.24s  %9ld\n", c_file.name, ctime( &( c_file.time_write ) ), c_file.size );

        // 残りのファイルを探します
        while( _findnext( hFile, &c_file ) == 0 ){
            printf( ( c_file.attrib & _A_RDONLY ) ? " Y  " : " N  " );
            printf( ( c_file.attrib & _A_SYSTEM ) ? " Y  " : " N  " );
            printf( ( c_file.attrib & _A_HIDDEN ) ? " Y  " : " N  " );
            printf( ( c_file.attrib & _A_ARCH )   ? " Y  " : " N  " );
            printf( " %-12s %.24s  %9ld\n", c_file.name, ctime( &( c_file.time_write ) ), c_file.size );
        }

       _findclose( hFile );
    }
}
を改造して
#include <stdio.h>
#include <io.h>

void main( void ){
    struct _finddata_t c_file;
    long   hFile;

    // カレント ディレクトリ内の最初のファイルを探します。
    if( (hFile = _findfirst( "*.*", &c_file )) == -1L )
       printf( "カレント ディレクトリにはファイルは存在しません。\n" );
    else{
        printf( "ファイルのリスト\n" );     
        printf( "%-12s\n", c_file.name );

        // 残りのファイルを探します
        while( _findnext( hFile, &c_file ) == 0 ){
          
            printf( "%-12s\n", c_file.name );
        }

       _findclose( hFile );
    }
}
でファイル名だけ出すようにして
そこから
#include <stdio.h>
#include <io.h>

void main( void ){
    struct _finddata_t c_file;
    long   hFile;
    char    fname[99];
    int i = 0;
FILE *fp;
    // カレント ディレクトリ内の最初のファイルを探します。
    if( (hFile = _findfirst( "*.c", &c_file )) == -1L )
       printf( "カレント ディレクトリにはファイルは存在しません。\n" );
    else{

        printf( "ファイルのリスト\n" );     
        printf( "%s\n", c_file.name );/*ファイル名を出力しなさい*/
        sprintf(fname,"%s",c_file.name);/*ファイル名をfnameに文字データとして代入させなさい*/
        fp = fopen(fname, "r");/*ファイルを開きなさい*/
         i++;
        // 残りのファイルを探します
        while( _findnext( hFile, &c_file ) == 0 ){
          
        printf( "%s\n", c_file.name );/*ファイル名を出力しなさい*/
        sprintf(fname,"%s",c_file.name);/*ファイル名をfnameに文字データとして代入させなさい*/
        fp = fopen(fname, "r");/*ファイルを開きなさい*/
         i++;
        }

       _findclose( hFile );
    }
}

と改造したのですが・・・(やっぱりsprintfが無理がある?)
回答のほうよろしくお願いします。

たいちう

Re:カレントディレクトリ内の検索

#2

投稿記事 by たいちう » 15年前

> 回答のほうよろしくお願いします。

何を答えてほしいのですか?
途中までのソースコードを貼っているみたいですが、
それがどこまでできていて、どこで躓いているかの説明は無し?


> perl言語で書かれた次のスクリプトmygrep.plと
> 同等以上のコマンドをC言語として書きなさい

...

> つまり.cファイル内にある例えばprintfと検索かけたら
> カレントディレクトリ内にあるファイルの中にある
> printfと書いてある文字列を全部書き出しなさいということです

間違いないですか?Perlのプログラムは別のことをやっていますよ?
(Perlの動く環境がないので、もしかしたら間違っているかもしれません)

・検索対象はカレントディレクトリの全ファイルではなく、
コマンドライン引数で、検索パターンの後に指定されたファイル。
・検索パターンは正規表現で書かれているので、
例えばパターンが"strn?cpy"とかの場合は、strcpyとstrncpyの
両方が抽出される。(もっと複雑な検索もできます)

天和

Re:カレントディレクトリ内の検索

#3

投稿記事 by 天和 » 15年前

>たいちうさん
まず躓いている場所は
#include <stdio.h>
#include <io.h>

void main( void ){
struct _finddata_t c_file;
long hFile;
char fname[99];
int i = 0;
FILE *fp;
// カレント ディレクトリ内の最初のファイルを探します。
if( (hFile = _findfirst( "*.c", &c_file )) == -1L )
printf( "カレント ディレクトリにはファイルは存在しません。\n" );
else{

printf( "ファイルのリスト\n" );
printf( "%s\n", c_file.name );/*ファイル名を出力しなさい*/
sprintf(fname,"%s",c_file.name);/*ファイル名をfnameに文字データとして代入させなさい*/
fp = fopen(fname, "r");/*ファイルを開きなさい*/
i++;
// 残りのファイルを探します
while( _findnext( hFile, &c_file ) == 0 ){

printf( "%s\n", c_file.name );/*ファイル名を出力しなさい*/
sprintf(fname,"%s",c_file.name);/*ファイル名をfnameに文字データとして代入させなさい*/
fp = fopen(fname, "r");/*ファイルを開きなさい*/
i++;
}

_findclose( hFile );
}
}
とやると(実際には_findfirst( "*.c", &c_file )はGCC用に書いてあるので
VISUAL c++だと*.cppなのですが)
そうするとエラーが出て強制終了してしまうのですですのでまずは
上のソースコードを何とかしたいというところです(もちろんいきなり課題の回答書いていただけてもありがたいですが・・・・)
>perl言語に間違いはありませんか?
自分はperl言語なんてやったことなく先生が「ほかの言語にも触れる機会を作ろう」ということでこういう課題
をとったみたいですだから間違いかどうかは・・・・
課題のプリントには$ perl mygrep. pl while ./*.cで~.cファイルから"while"という文字列を含むすべての行を行番号つきで画面に表示できます。
mygrep.plはUNIXが標準装備している grep コマンドの簡易版になっています。
grepコマンドで同じような結果を得るには、次のようにコマンド入力します。
$ grep -n while ./*.c
ここでスイッチ -nが行番号付加になります。grepコマンドの詳しい使用法は$ man grepで確認できます
つまり、スクリプトmygrep.plは perlという言語で書かれた簡易版のgrepだったわけです。
これが今日の課題です。
と書いてあるので
行番号つけるにしてもまずカレントディレクトリ内にある.cファイル名を検索などしてファイル名をだし
そのファイルを検索したい文字を含む文字列を出しなさいという課題かと思ったのですが・・・・

たいちう

Re:カレントディレクトリ内の検索

#4

投稿記事 by たいちう » 15年前

char fname[99]; は、文字列が長さ98文字の文字列が1つ分です。
複数のファイル名を保持したいならば、
char fname[10][99]; // 10個のファイルまでの場合
のようにする必要があります。

使う部分も fopen(fname, "r") のように変更します。
意味を考えてください。


> と書いてあるので
> 行番号つけるにしてもまずカレントディレクトリ内にある.cファイル名を検索などしてファイル名をだし
> そのファイルを検索したい文字を含む文字列を出しなさいという課題かと思ったのですが・・・・

Perlはそれほど詳しくないので、"$ perl mygrep. pl while ./*.c"というコマンドが
どのように処理されるのか、私には実行してみないと判りません。早くても今夜帰宅後です。
# Usage: mygrep pattern file1 file2 ...
というようなコメントからも、ファイルを指定するものと判断したのですが。

天和

Re:カレントディレクトリ内の検索

#5

投稿記事 by 天和 » 15年前

>たいちうさん

>char fname[99]; は、文字列が長さ98文字の文字列が1つ分です
やはりここのsprintfとは違うのでしょうか
http://www.play21.jp/board/formz.cgi?ac ... &rln=44086
上のURLだと
int set_word(int argc, char **argv, WORD *word)
{
    int i;
    for (i = 0; i < argc - 1; i++)
        word.lenght = sprintf(word.letter, "%s", argv[i + 1]);
    return argc - 1;
}

だと例えば this is a penだと配列ひとつひとつ「this」 「is」 「a」 「pen」
と入って「t」「h」「i」「s」と一文字一文字はいってるということはないと思ったのですが。
>Perlはそれほど詳しくないので、"$ perl mygrep. pl while ./*.c"というコマンドが
どのように処理されるのか、私には実行してみないと判りません。早くても今夜帰宅後です。
# Usage: mygrep pattern file1 file2 ...
というようなコメントからも、ファイルを指定するものと判断したのですが。

いろいろほんとにどうもすいませんしかしなぜ普通にc言語でこれしなさいと先生はしなかったのか・・・
(javaならともかくとして)
プログラム習う上で重要な言語またはほかの言語を理解するのも大切なことなんですかね?

たいちう

Re:カレントディレクトリ内の検索

#6

投稿記事 by たいちう » 15年前

> だと例えば this is a penだと配列ひとつひとつ「this」 「is」 「a」 「pen」
> と入って「t」「h」「i」「s」と一文字一文字はいってるということはないと思ったのですが。

配列の定義を比べてください。何の配列なのかが違います。


> プログラム習う上で重要な言語またはほかの言語を理解するのも大切なことなんですかね?

工学系の学生とかが、研究に必要な計算のためだけにプログラムを習うのならば、
それほど重要ではないでしょう。

情報系や専門学校の学生の場合だと、1つしか言語を知らないというのは、
致命的だと私は考えます。(天和さんの場合はCすら知らないレベルね。今は。)

天和

Re:カレントディレクトリ内の検索

#7

投稿記事 by 天和 » 15年前

>たいちうさん
>情報系や専門学校の学生の場合だと、1つしか言語を知らないというのは、
致命的だと私は考えます。(天和さんの場合はCすら知らないレベルね。今は。)
うちは情報系ですのでc言語c++javaですから実質2つですね。
メジャーな言語だけって感じもしますが・・・・

閉鎖

“C言語何でも質問掲示板” へ戻る