1

私は C プログラミングの初心者であり、UNIX でターミナルを使用して使用するコマンドライン メソッドを作成するように割り当てられました。これまでのところ、ファイルを読み取る方法と逆の順序で読み取る方法を実装してきました。最後の部分では、行番号を指定して表示する必要があります (例: ./showfile -l(2) textfile)。

私の懸念は入力を識別することであり、このタスクに正規表現を使用することにしましたが、argv[1] でパターン -l(i) を識別する方法を見つけることができないようです。

編集:私がしたすべて:

void reversetext(FILE * f);
void main(int argc, char * argv[]) {
    regex_t regex;
    int i;
    FILE * f;
    char c;

    if (regcomp( & regex, "-l[[digit:]]+", 0)) {
        printf("Could not compile\n");
        return;
    }

    if (strcmp(argv[1], "-r") == 0) {
        f = fopen(argv[2], "r");
        reversetext(f);
    } else if (regexec( & regex, argv[1], 0, NULL, 0) == 0) {
        printf("%s", argv[1]);
    } else {
        f = fopen(argv[1], "r");
        c = getc(f);

        while (c != EOF) {
            printf("%c", c);
            c = getc(f);
        }
    }

    fclose(f);
}

void reversetext(FILE * f) {
    char c = getc(f);
    if (c == EOF) {
        return;
    }

    reversetext(f);
    printf("%c", c);
}

セグメンテーション違反エラーが発生するのはなぜですか? 以前の投稿をいくつか読みましたが、POSIX でこのエラーに直面したユーザーはいませんでした。

注:メインの上に必要なライブラリを含めました。

コードの説明: ./showfile -r text.txt >> 逆方向のビュー

行を指定する 2 番目の if ステートメント

それ以外の場合: 通常どおりに印刷します。

4

2 に答える 2

2

これはあなたのために働くでしょう:

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <regex.h>

int main(void) {
    const char tests[2][4] = {"-l4", "-lm"};
    const char match[] = "-l[[:digit:]]+";
    regex_t rmatch;

    if ( regcomp(&rmatch, match, REG_EXTENDED) != 0 ) {
        perror("Error compiling regex");
        return EXIT_FAILURE;
    }

    for ( int i = 0; i < 2; ++i ) {
        if ( regexec(&rmatch, tests[i], 0, NULL, 0) != 0 ) {
            printf("No match for '%s'.\n", tests[i]);
        } else {
            printf("Matched '%s'.\n", tests[i]);
        }
    }

    return 0;
}

出力:

paul@local:~/src/c/scratch$ ./regex
Matched '-l4'.
No match for '-lm'.
paul@local:~/src/c/scratch$

編集:投稿したコードには、いくつかの問題があります。

  1. この行:

    if(regcomp(&regex,"-l[[digit:]]+",0)){
    

    次のようにする必要があります。

    if( regcomp(&regex, "-l[[:digit:]]+", REG_EXTENDED) ) {
    

    拡張正規表現を使用しているためです。この行を変更すると、パターンが正常に一致します。

  2. あなたのセグメンテーション違反は、実際には正規表現とは何の関係もなく、これを呼び出すことから来ています:

    fclose(f);
    

    ファイルを正常に開いたことがない実行パス上にある場合。変更する必要があります:

    FILE *f;
    

    に:

    FILE *f = NULL;
    

    そして変更:

    fclose(f);
    

    に:

    if ( f ) {
        fclose(f);
    }
    

    gdb に慣れ親しむことは、これらのことを自分で追跡できるようになるための長い道のりです。

以下は、動作する独自のコードの修正版で、いくつかの基本的なエラー チェックが含まれています。

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>

void reversetext(FILE * f);

int main(int argc, char *argv[]) {
    regex_t rmatch;
    FILE *f = NULL;
    int c;

    if ( argc < 2 ) {
        printf("You need to enter at least one command line argument.\n");
        return EXIT_FAILURE;
    }

    if ( regcomp(&rmatch, "-l[[:digit:]]+", REG_EXTENDED) ) {
        printf("Could not compile regex.\n");
        return EXIT_FAILURE;
    }

    if ( strcmp(argv[1], "-r") == 0 && argc > 2 ) {
        printf("argv[1] is -r\n");
        if ( (f = fopen(argv[2], "r")) == NULL ) {
            fprintf(stderr, "Couldn't open file %s\n", argv[2]);
            return EXIT_FAILURE;
        }
        reversetext(f);
    } else if (regexec(&rmatch, argv[1], 0, NULL, 0) == 0) {
        printf("Matched '%s' to regex\n", argv[1]);
    } else {
        if ( (f = fopen(argv[1], "r")) == NULL ) {
            fprintf(stderr, "Couldn't open file %s\n", argv[1]);
            return EXIT_FAILURE;
        }

        while ( (c = getc(f)) != EOF) {
            printf("%c", c);
        }
    }

    if ( f ) {
        fclose(f);
    }    
}

void reversetext(FILE * f) {
    int c = getc(f);
    if (c == EOF) {
        return;
    }

    reversetext(f);
    printf("%c", c);
}

出力:

paul@local:~/src/c/scratch$ ./regex2 -l4
Matched '-l4' to regex
paul@local:~/src/c/scratch$ ./regex2 -r fakefile
argv[1] is -r
Couldn't open file fakefile
paul@local:~/src/c/scratch$ ./regex2 -tribbles
Couldn't open file -tribbles
paul@local:~/src/c/scratch$ ./regex2 testfile
This is a test.
paul@local:~/src/c/scratch$ ./regex2 -r testfile
argv[1] is -r

.tset a si sihTpaul@local:~/src/c/scratch$

あなたが and を使用している場合getc()、友人はints ではなくchars を使用することに注意してください。これは、保存できるようにするために必要EOFです。

編集 2: コメントの質問に従って、サブグループ、この場合は一致の数値部分を一致させるために 4 つのことを行う必要があります。

  1. タイプ の配列を設定しregmatch_tます。最初の要素は正規表現全体に一致するため、少なくとも 2 つの要素が必要です。また、1 つのサブグループに対して少なくとも 1 秒必要です。以下のコードでは、次を追加しました。

    #define MAX_MATCHES 10
    regmatch_t m_group[MAX_MATCHES];
    
  2. 抽出したい正規表現の部分を括弧で囲みます。以下のコードでは、次のように変更しました。

    "-l[[:digit:]]+"
    

    に:

    "-l([[:digit:]]+)"
    
  3. 配列を呼び出すときに、サイズとともにregmatch_t配列を渡します。regexec()以下のコードでは、次のように変更しました。

    } else if (regexec(&rmatch, argv[1], 0, NULL, 0) == 0) {
    

    に:

    } else if (regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0) {
    
  4. 配列を循環し、各一致を処理します。配列要素のrm_soメンバーが でない場合は常に、一致があります。ここで行っているのは、それらをバッファーにコピーして出力することだけです。regmatch_t-1

    } else if ( regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0 ) {
        printf("Matched '%s' to regex\n", argv[1]);
        for ( int i = 0; i < MAX_MATCHES && m_group[i].rm_so != -1; ++i ) {
            char buffer[1000] = {0};
            char * match_start = &argv[1][m_group[i].rm_so];
            size_t match_size = m_group[i].rm_eo - m_group[i].rm_so;
            size_t match_len = match_size > 999 ? 999 : match_size;
            strncpy(buffer, match_start, match_len);
            printf("Matched group %d was '%s'\n", i, buffer);
        }
    } 
    

更新されたコードは次のとおりです。

#define _POSIX_C_SOURCE 200809L

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <regex.h>

#define MAX_MATCHES 10

void reversetext(FILE * f);

int main(int argc, char *argv[]) {
    regex_t rmatch;
    regmatch_t m_group[MAX_MATCHES];
    FILE *f = NULL;
    int c;

    if ( argc < 2 ) {
        printf("You need to enter at least one command line argument.\n");
        return EXIT_FAILURE;
    }

    if ( regcomp(&rmatch, "-l([[:digit:]])+", REG_EXTENDED) ) {
        printf("Could not compile regex.\n");
        return EXIT_FAILURE;
    }

    if ( strcmp(argv[1], "-r") == 0 && argc > 2) {
        printf("argv[1] is -r\n");
        if ( (f = fopen(argv[2], "r")) == NULL ) {
            fprintf(stderr, "Couldn't open file %s\n", argv[2]);
            return EXIT_FAILURE;
        }
        reversetext(f);
    } else if ( regexec(&rmatch, argv[1], MAX_MATCHES, m_group, 0) == 0 ) {
        printf("Matched '%s' to regex\n", argv[1]);
        for ( int i = 0; i < MAX_MATCHES && m_group[i].rm_so && ; ++i ) {
            char buffer[1000] = {0};
            char * match_start = &argv[1][m_group[i].rm_so];
            size_t match_size = m_group[i].rm_eo - m_group[i].rm_so;
            size_t match_len = match_size > 999 ? 999 : match_size;
            strncpy(buffer, match_start, match_len);
            printf("Matched group %d was '%s'\n", i, buffer);
        }
    }  else {
        if ( (f = fopen(argv[1], "r")) == NULL ) {
            fprintf(stderr, "Couldn't open file %s\n", argv[1]);
            return EXIT_FAILURE;
        }

        while ( (c = getc(f)) != EOF) {
            printf("%c", c);
        }
    }

    if ( f ) {
        fclose(f);
    }
}

void reversetext(FILE * f) {
    int c = getc(f);
    if (c == EOF) {
        return;
    }

    reversetext(f);
    printf("%c", c);
}

出力:

paul@local:~/src/c/scratch$ ./regex2 -l4
Matched '-l4' to regex
Matched group 0 was '-l4'
Matched group 1 was '4'
paul@local:~/src/c/scratch$
于 2013-10-19T21:31:55.867 に答える
0

パターンで助けが必要な場合は、これが役立つかもしれません: http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/

ただし、セグメンテーション違反については、さらに詳細が必要です。

これは、パターンを置き換えるだけでよい実用的な例でもあります: C の正規表現: 例?

于 2013-10-19T21:32:31.920 に答える