代码之家  ›  专栏  ›  技术社区  ›  Atieh

处理C中的POSIX-错误消息:分段故障(核心转储)

  •  1
  • Atieh  · 技术社区  · 11 年前

    我是C编程的新手,我被指派创建命令行方法,以便在UNIX中使用终端。到目前为止,我已经实现了读取文件和按相反顺序读取文件的方法。最后一部分需要指定行号并显示它(例如:./showfile-l(2)文本文件)。

    我关心的是识别输入,我决定使用Regex来完成这项任务,但我似乎找不到在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时遇到这个错误。

    注意: 我已经在main上面包含了我需要的lib。

    代码说明: ./showfile-r文本.txt>>反向视图

    指定行的第二个if语句

    否则:正常打印。

    2 回复  |  直到 11 年前
        1
  •  2
  •   Crowman    11 年前

    这将对您有效:

    #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;
      

      和更改:

      f损失(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$
    

    使用时要注意 getc() 和朋友,他们使用 int s、 不是 char s。为了能够存储,这是必要的 EOF .

    编辑2:根据你评论中的问题,你需要做四件事来匹配一个子组,在这种情况下,是匹配的数字部分。

    1. 设置类型为的数组 regmatch_t 。您至少需要两个元素,因为第一个元素将与整个正则表达式匹配,而一个子组至少需要第二个元素。在下面的代码中,我添加了:

      #define MAX_MATCHES 10
      regmatch_t m_group[MAX_MATCHES];
      
    2. 在正则表达式中要提取的部分加上括号。在下面的代码中,我更改了:

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

      收件人:

      "-l([[:digit:]]+)"
      
    3. 通过您的 规则匹配_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 成员 规则匹配_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$
    
        2
  •  0
  •   Community CDub    8 年前

    如果您需要模式方面的帮助,这可能会有所帮助: http://www.cheatography.com/davechild/cheat-sheets/regular-expressions/

    但关于分割故障,还需要更多的细节。

    这也是一个工作示例,您只需要替换模式: Regular expressions in C: examples?