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

标签 c file parsing fgets strncmp

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

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

我想使用:

  1. fgets() 逐行读取文件
  2. 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 级联似乎也不是一个好主意。 在你的方法中,你会因为读取太多行而只需要解析 1 行而陷入困境。

也许您应该阅读一些有关状态机的内容。

这是我解决问题的快速方法:

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.

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

关于c - 使用 fgets 从文件中读取行并将每一行与 c 中的 strncmp 进行比较,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41429332/

相关文章:

c - Linux 内核字符设备驱动程序向用户空间返回空字符串

c - 我如何从函数返回两个整数

c - libssh2 channel SSL BIO 使用

c - 访问嵌套结构的字段

python - 打开一个文件,写入它而不是关闭它是否安全?

java - jStyleParser 无法解析我的 html 文件

c - 在 C 中使用 cmd 替换文件的单词时出现问题

c++ - 从文件中读取数据到数组中

javascript - 根据特定标准从字符串中提取子字符串的有效方法?

parsing - Go: time.Parse() 问题