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

时间:2017-01-02 15:21:01

标签: c file parsing fgets strncmp

我想从一个看起来像这样的文件中读取每一行:

readEveryLine
{       
  "Bart [m]" -> "Marge [f]";  
  "Lisa [f]" -> "Homer [m]"; 
  ...      
}

我想用:

  1. fgets()逐行读取文件
  2. strncmp()将每一行与给定字符串进行比较或看到它的格式正确
  3. 我有什么:

    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");
        } 
    }
    

    所以问题是它只是给我一个Error Parsing而且我不知道我在这里做错了什么。

    非常感谢帮助我!

    这里我现在做了一些事情(现在解析前两行): 也许任何人都有一个很好的提示,我可以做得更好。 非常感谢。

    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

1 个答案:

答案 0 :(得分:0)

您的算法已经破解。 您使用*file_string的相同内容将其与tweo不同的字符串进行比较。 如果您找到"readEveryLine"的匹配项,则需要先阅读文件中的下一行,然后才能获得strncmp()的下一个匹配项。 否则,文件中的行必须与"readEveryLine" "{"匹配才能传递您的第二个if条件,这是不可能的。

编辑: 现在,由于您已经做了一些改进,我仍然认为它不适用于您的方法。循环将不会退出它们应该和你的if-else-cascade似乎也不是一个好主意。 在你的方法中,你会因为读取太多行而搞砸了,而只需要解析一行。

也许你应该阅读一下状态机。

以下是我如何解决问题的快速方法:

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.

我还没有编译它,但你应该明白这个想法。