2015-05-31 2 views
0

Я создал структуру с именем Utype, которая содержит разные переменные. Если я хочу t, тогда позвоню Utype->t.Значение, исчезающее вне цикла while, хотя сохранение в переменной malloc

Теперь я использую fgets для извлечения данных из входного файла.

Код:

#include "read_file.h" 

int read_file(int argc, char* argv[], Utype* u_coarse){ 
    int i; 
    int num_length = 1024; 
    FILE *input_file; 
    char buffer[num_length]; 
    char *end_of_file; 
    char *lines = NULL; 
    char *lines_temp; 
    int num_time_segments=0; 
    double testest=0; 

    for (i=0; i<num_length; i++){ 
     buffer[i]=' '; 
    } 
    input_file = fopen(argv[1], "r"); 
    end_of_file = fgets(buffer, num_length, input_file); 
    while (end_of_file != NULL){ 

     if (end_of_file[0]!= '\n' && end_of_file[0]!='%'){ 
      lines = strtok(end_of_file, "="); 
      if (lines[strlen(lines)-1] == ' '){ 
       lines[strlen(lines)-1] = '\0'; 
      } 
      lines_temp = strtok(NULL, "="); 
      if (lines_temp[0] == ' '){ 
       for (i=1; i<strlen(lines_temp); i++){ 
        lines_temp[i-1] = lines_temp[i]; 
       } 
       lines_temp[strlen(lines_temp)-2] = '\0'; 
      }else{ 
       lines_temp[strlen(lines_temp)-1] = '\0'; 
      } 
      if (strcmp(lines, "T") == 0){ 
       u_coarse->ultimateT = atof(lines_temp); 
      } 
     // printf("%g\n", testest);                               
     } 

    } 
// printf("%g\n", testest);                                 
// u_coarse->burn_time = testest;                                

    fclose(input_file); 

    return num_time_segments; 

После того как я называю эту read_file функцию, я пытаюсь напечатать

u_coarse->ultimateT 

Но это говорит

Conditional jump or move depends on uninitialised value(s) 

, когда я использую Valgrind. Я пытался выяснить, почему это дает мне эту ошибку памяти на некоторое время. Любая помощь будет высоко ценится.

Редактировать 31 мая 2015:

Спасибо всем за ваш вклад. Я прилагаю скорректированный код, который я сделал с улучшениями. Я по-прежнему получаю ту же ошибку, что и раньше. Valgrind говорит:

==6485== Memcheck, a memory error detector 
==6485== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al. 
==6485== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info 
==6485== Command: ../bin/main.x ../ ../example_input.inp 
==6485== 
==6485== Conditional jump or move depends on uninitialised value(s) 
==6485== at 0x3BFE249CF0: __printf_fp (in /lib64/libc-2.12.so) 
==6485== by 0x3BFE24589F: vfprintf (in /lib64/libc-2.12.so) 
==6485== by 0x3BFE24F189: printf (in /lib64/libc-2.12.so) 
==6485== by 0x406CF1: main (main.c:23) 

где:

main.c:23 

где я печатаю:

u_coarse->ultimateT 

Отредактировано Код:

#include "read_file.h" 

int read_file(int argc, char* argv[], Utype* u_coarse){ 

    int i; 
    int num_length = 1024; 
    FILE *input_file; 
    char buffer[num_length]; 
    char *current_line; 
    char *lines = NULL; 
    char *lines_temp; 
    int num_time_segments=0; 
    size_t length; 
    size_t length_temp; 

    memset(buffer, ' ', sizeof(buffer) -1); 
    buffer[sizeof(buffer) - 1] = '\0'; 
    input_file = fopen(argv[1], "r"); 
    if (input_file == NULL){ 
     perror("Error"); 
     exit(EXIT_FAILURE); 
    }else{ 
     while (current_line = fgets(buffer, sizeof(buffer), input_file)){ 
      if (current_line[0]!= '\n' && current_line[0]!='%'){ 
       lines = strtok(current_line, "="); 
       if (lines == NULL){ 
        perror("Error"); 
        exit(EXIT_FAILURE); 
       } 
       length = strlen(lines); 
       if (lines[length-1] == ' '){ 
        lines[length-1] = '\0'; 
       } 
       lines_temp = strtok(NULL, "="); 
       if (lines_temp == NULL){ 
        perror("Error"); 
        exit(EXIT_FAILURE); 
       } 
       length_temp = strlen(lines_temp); 
       if (lines_temp[0] == ' '){ 
        memmove(lines_temp, lines_temp +1, length_temp); 
       }else{ 
        lines_temp[length_temp-1] = '\0'; 
       } 
       if (strcmp(lines, "T") == 0){ 
        u_coarse->ultimateT = atof(lines_temp); 
       } 
      } 
     } 
    } 
    return num_time_segments; 
} 

Мой файл main.c является:

int main(int argc, char *argv[]) { 

    Utype *u_coarse = (Utype*)malloc(sizeof(Utype));       

    int num_time_segments = read_file(argc, argv, u_coarse); 
    printf("%g\n", u_coarse->ultimateT); 

Моя структура является:

typedef struct { 
    double ultimateT; 
}Utype; 

К сожалению, я пытался не показывать слишком много, так как это для исследований.

+0

Valgrind может сказать вам номер строки, где проблема возникает. Кроме того, не вызывайте 'strlen()' столько раз, он итерации через байты, чтобы найти завершающий 'nul'. –

+0

Да, valgrind говорит мне, что есть проблема, когда я печатаю u_coarse-> ultimateT в main.c, который у меня есть. – Yue

+0

Вы должны отправить код вызова. –

ответ

4

Ваш код имеет несколько проблем

  1. Вы никогда не проверить, если strtok() не удалось или нет, что может привести к Valgrind, чтобы сообщить, что он сообщает, или что-то еще, так как это приводит к неопределенному поведению.

  2. Вы используете strlen() очень плохо, strlen() петли через строку, что означает, что на каждой итерации вы повторяетесь столько же раз. Вы должны сохранить значение и использовать сохраненное значение, оно не только более эффективно, но и делает ваш код более красивым.

  3. Цикл никогда не заканчивается, потому что вы не переназначить end_of_file, который, кстати хуже имя для этой переменной, вы должны сделать это так

    while (current_line = fgets(buffer, sizeof(buffer), input_file)) ... 
    
  4. Вы заполняете buffer массив с вручную написан цикл, когда вы можете использовать memset()

    memset(buffer, ' ', sizeof(buffer) - 1); 
    buffer[sizeof(buffer) - 1] = '\0'; 
    

    бы сделать лучшую работу, синтаксически, а также было бы более эффективным, а также будет nul TERMI nate buffer, которого вы не делали.

  5. Вы никогда не проверяете, удалось ли выполнить fopen(), что приведет к неопределенному поведению, вы должны проверить, что каждый вызов функции работал должным образом, большинство из них возвращают специальные значения или устанавливают специальные переменные, чтобы указать, когда возникает проблема, проверьте на наличие ошибок, делает ваш код очень неустойчивым, и если бы я был вашим начальником, я бы уволил вас. Не ошибетесь, я говорю это, потому что, если вы последуете моему совету, вы напишете более надежный код, и у вас будет меньше проблем.

  6. Это

    for (i = 1 ; i < strlen(lines_temp) ; i++) 
    { 
        lines_temp[i - 1] = lines_temp[i]; 
    } 
    lines_temp[strlen(lines_temp) - 2] = '\0'; 
    

    плохо по нескольким причинам

    1. Вы не должны цикл самостоятельно, использовать memmove() вместо этого.

      size_t length = strlen(lines_temp); 
      memmove(lines_temp, lines_temp + 1, length); 
      
    2. Если вы пишете петлю на себя, эффективный способ будет

      for (i = 1 ; lines_temp[i] != 0 ; i++) 
      { 
          lines_temp[i - 1] = lines_temp[i]; 
      } 
      lines_temp[i - 1] = '\0'; 
      
+0

k Благодарю вас за ответ. Позвольте мне попытаться понять и реализовать ваши предложения. Я очень ценю вашу помощь и вернусь к вам. – Yue

+0

Для memmove, почему бы и нет 'memmove (lines_temp, lines_temp + 1, length-1);'? – Yue

+0

Потому что вы также хотите скопировать терминатор 'nul'. –

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