2017-01-02 2 views
0

я хочу, чтобы прочитать каждую строку из файла, который выглядит примерно так:читать строки из файла с 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++; 

} 

// и самый последний знак должен быть} \ п

+0

1) Пост-определение 'string' и' changeLastC() ', 2) Предотвращение предупреждений компилятора полностью включено. 3) Зачем ожидать '' readEveryLine \ n "' равным '' readEveryLine''? Иначе проблема не определена. – chux

+2

Почему вы хотите использовать 'strncmp'? Правильной функцией для этой цели является 'strcmp'. – rici

+0

@chux, в конце строки нет '\ n'. Согласно комментарию, '\ n' заменяется на' \ 0' функцией 'changeLastC()' – Gerhardh

ответ

0

Ваш алгоритм уже сломана. Вы используете тот же контент *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. 

Я не компилировать его еще, но вы должны получить идею.

+0

звучит ясно. проблема в том, что я не знаю, как анализировать следующую строку, делать другое условие if, затем анализировать третью строку, делать следующее условие if и так далее. Большое спасибо за вашу помощь. – MBD

+0

Например, если я использую цикл while следующим образом: while (fgets (file_string, 19, file)) и используйте этот буфер для первой строки, то я не уверен, что я должен использовать цикл для каждой строки и нового буфера. Я думаю, что я ошибаюсь. Большое спасибо за вашу помощь. – MBD

+0

Попробуйте его с помощью некоторого псевдокода. Попытайтесь объяснить это своей резиновой утке или вашему питомцу, что вы хотите сделать. Вы также можете попробовать сделать это на бумаге. Если есть фразы типа «сначала ..., тогда ...», вам нужна последовательность отдельных действий. Нет петли. Если есть фразы типа «Для каждой строки ....», то вам нужен цикл. При этом должно быть ясно, что вам не нужен цикл для первых двух строк вашего файла. Но вам нужна петля для любой следующей строки. И некоторые handlnig для последней строки ("} \ n"). Я бы посоветовал вам снова заглянуть в ваш учебник текста и переварить немного больше _when_ и _how_ loops. – Gerhardh

Смежные вопросы