使用fgets从文件中读取行,并将每行与c中的strncmp进行比较

使用fgets从文件中读取行,并将每行与c中的strncmp进行比较,c,file,parsing,fgets,strncmp,C,File,Parsing,Fgets,Strncmp,我想读取文件中的每一行,如下所示: readEveryLine { "Bart [m]" -> "Marge [f]"; "Lisa [f]" -> "Homer [m]"; ... } 我想使用: fgets()逐行读取文件 strncmp()将每一行与给定字符串进行比较,或查看其格式是否正确 我所拥有的: while(fgets(*file_string, MAX_INPUT_STDIN, file) != NULL) {

我想读取文件中的每一行,如下所示:

readEveryLine
{       
  "Bart [m]" -> "Marge [f]";  
  "Lisa [f]" -> "Homer [m]"; 
  ...      
}
我想使用:

  • fgets()逐行读取文件
  • strncmp()将每一行与给定字符串进行比较,或查看其格式是否正确
  • 我所拥有的:

    while(fgets(*file_string, MAX_INPUT_STDIN, file) != NULL)
    {       
      changeLastC(*file_string);  // function to change \n into \0 
    
        if (strncmp(*file_string, "readEveryLine\0", 14) == 0)
        {
          if (strncmp(*file_string, "{\0", 2) == 0)
          {
            // check the first -> relation
          }
        }
        else
        {
          printf("Error Parsing\n");
        } 
    }
    
    所以问题是,它只是给了我一个错误的解析,我不知道我在这里做错了什么

    非常感谢你帮助我

    在这里,我现在做了一些事情(解析前两行现在可以工作了): 也许有人给了我一个好的建议,我可以做得更好。 非常感谢

    if ((fp = fopen("df.dot","r")) == NULL)
    {
      printf("Error: File Open\n");
      return 1;
    }
    
    
    int row = 0; // check row 1
    
    while (fgets(buffer, MAX_PARSING, fp))
    {        
      if ((row == 0) && strncmp(buffer, "readEveryLine\n", 14) == 0)
      {
        printf("%s", buffer);
      }
      else
      {
        printf("Parsing Error 1\n");
      }
    }
    
    
    int row1 = 1; // check row 2
    
    while (fgets(buffer, MAX_PARSING, fp))
    {     
      if ((row1 == 1) && strncmp(buffer, "{\n", 2) == 0)
      {
        printf("%s", buffer);
      }
      else
      {
        printf("Parsing Error 2\n");
      }
    }
    
    
    int row2 = 2; // check other rows (dynamic, could be even more or less)
    
    while (fgets(buffer, MAX_PARSING, fp))
    { 
      if ((row2 == 2) && strncmp(buffer, "  ", 2) == 0)
      {
        const char *p1 = strstr(fp, "\"")+1;
        const char *p2 = strstr(p1, " [m]\"");
        const char *p3 = strstr(p1, " [f]\"");
    
        // extract male persons
        if (p1 && p2)
        {
          size_t len1 = p2 - p1;
          char* res1 = (char*)malloc(sizeof(char)*(len1 + 1));
          strncpy(res1, p1, len1);
    
          res1[len1] = '\0';
    
          // give res1 for functionMale() to work on that string
        }
    
        // extract female persons
        else if (p1 && p3)
        {
          size_t len2 = p3 - p1;
          char* res2 = (char*)malloc(sizeof(char)*(len2 + 1));
          strncpy(res2, p1, len2);
    
          res2[len2] = '\0';
    
          // give res2 for functionFemale() to work on that string
        }
    
        else if (strcmp(buffer, " -> ") == 0)
        {
          // work in progress (quite complicated to do this i think)
          // it has to be a realtion between two people
        }
    
        else if (strcmp(buffer, ";") == 0)
        {
          // work in progress
          // this sign can either exist like this:
          // "Bart [m]" -> "Marge [f]";
    
          // or like this:
          // "Marge [f]";
        }
    
        break;
      }
      else
      {
        printf("Parsing Error 3\n");
      }
    
      row2++;
    
    }
    

    //最后一个符号必须是}\n

    您的算法已被破坏。 您可以使用与
    *file_string
    完全相同的内容将其与两个不同的字符串进行比较。 如果您找到了与
    “readEveryLine”
    的匹配项,则需要从文件中读取下一行,然后才能获得
    strncmp()
    的下一个匹配项。 否则,文件中的行必须同时匹配
    “readEveryLine”
    “{”
    才能通过第二个
    if
    条件,这是不可能的

    编辑: 现在,由于您已经做了一些改进,我仍然认为它不适用于您的方法。循环不会在应该退出时退出,您的if-else级联似乎也不是一个好主意。 在您的方法中,您将由于读取太多行而陷入混乱,而只应解析一行

    也许你应该读一些关于状态机的书

    下面是一个快速解决问题的方法:

    enum { STATE_HEADER1, STATE_HEADER2, STATE_BODY, STATE_END} state;
    int done = 0;
    state = STATE_HEADER1;
    
    while (fgets(buffer, MAX_PARSING, fp) && !done) {        
      if (state == STATE_HEADER1) {
        if (strcmp(buffer, "readEveryLine\n") == 0) {
          printf("%s", buffer);
          state = STATE_HEADER2;
        }
        else {
          printf("Parsing Error 1\n");
          done = 1;
        }        
      }
      else if (state == STATE_HEADER2) {
        if (strcmp(buffer, "{\n") == 0) {
          printf("%s", buffer);
          state = STATE_BODY;
        }
        else {
          printf("Parsing Error 2\n");
          done = 1;
        }
      }
      else if (state == STATE_BODY) {
        if (strcmp(buffer, "  ") == 0) {
          const char *p1 = strstr(buffer, "\"");
          const char *pm = strstr(p1, " [m]\"");
          const char *pf = strstr(p1, " [f]\"");
                char *res;
          const char *ptemp;
          int is_male;
    
          if (p1 && pf)  {
            p1 ++;
            is_male = 0;
            size_t len1 = pf - p1;
            res = malloc(len1 + 1);
            strcpy(res, p1);
            ptemp = pf+3; // point after closing \"
    
            // give res for functionFemale() to work on that string
          }
          else if (p1 && pm) {
            p1 ++;
            is_male = 1;
            size_t len1 = pm - p1;
            res = malloc(len1 + 1);
            strcpy(res, p1);
            ptemp = pm+3; // point after closing \"
    
            // give res for functionMale() to work on that string
          }
          else {
            done = 1;
            printf("Parsing Error 2\n");
          }
    
          // Now we have res and is_male holding name and gender.
    
          if (!done)
          {
            if (strncmp(ptemp, " -> ", 4) == 0) {
    
      // Handle this variant:
      // this sign can either exist like this:
      // "Bart [m]" -> "Marge [f]";
    
              // Do similar stuff as above for first name
    
              // Get second name + gender
              // Also check trailing ';' here
            }
            else if (strcmp(temp, ";\n") == 0) {
    
     // Handle this variant:
     // or like this:
     // "Marge [f]";
    
            }
    
          } // found "  "
          else {
            if (strcmp(buffer, "}\n") == 0) {
              state = STATE_END;
              done = 1;
              printf("That's it folks...\n"); 
            }
            else {
              done = 1;
              printf("Parsing Error 3\n");
            }
          }
        }
      } // STATE_BODY
    } // while (fgets)
    
    if (state == STATE_END) }
      // Success. :)
    } else {
      // Something didn't match.
    }
    
    // close file, cleanup, etc.
    

    我还没有编译它,但你应该明白了。

    1)发布
    字符串的定义和
    changeLastC()
    ,2)确保编译器警告已完全启用。3)为什么期望
    “readEveryLine\n”
    等于
    “readEveryLine”
    ?否则问题没有很好地说明。你到底为什么要使用
    strncmp
    ?用于此目的的正确函数是
    strcmp
    @chux,行尾没有“\n”。根据注释,
    \n
    由函数
    changeLastC()更改为
    \0
    @Gerhardh是的,我的评论的第三部分不应该应用,但是评论不会驱动代码-只是暗示需要什么。OP的问题很可能是由
    changeLastC()引起的
    这不起作用,因为设置了错误的
    字符串
    或其他原因。发布的代码不足以进行诊断。@chux,为什么它不足以?正如我在回答中提到的,循环被破坏了。除了“错误解析”之外,你永远也得不到任何东西。对于第一行,第一个
    if
    为true,但是第二个
    if
    为false,因为任何字符串都不能匹配两个不同的文本。对于文件的每一行,第一个
    if
    为false,我们进入“错误解析”的else部分是打印的。这和他描述的错误一样。可能还有其他隐藏的错误,他还没有提到。但是他首先需要解决这个问题。听起来很清楚。问题是,我不知道如何解析下一行,生成另一个if条件,然后解析第三行,生成下一个if条件等等。谢谢非常感谢您的帮助。例如,如果我使用这样的while循环:while(fgets(file_string,19,file))第一行使用这个缓冲区,然后我不确定是否应该为每行使用一个循环和一个新的缓冲区。我认为我错了。非常感谢你的帮助。用一些伪代码尝试一下。试着向你的橡皮鸭或你的宠物解释一下,你想做什么。你也可以尝试在纸上做。如果有类似的短语“first…,then…”您需要一系列单独的操作。没有循环。如果有“For every line…”这样的短语,那么您需要一个循环。这样应该清楚,您不需要为文件的前两行创建循环。但是您需要为任何后续行创建一个循环。最后一行需要一些handlnig(“}\n”)。我建议您再次深入阅读您的C教科书,进一步了解循环的使用时间和方式。您能给我一个提示,解析每行末尾的;,并解析字符串末尾的最后两个符号}\n吗?这将对我帮助很大。谢谢。我已更新了我的答案。您的方法仍然可以读取多行,而不是应该对同一行进行分析。您可能需要进行一些调试以了解最终细节。