2016-08-14 5 views
4

Ich habe einige seltsame Probleme mit Floats bekommen, die als NaN gedruckt wurden, je nachdem, wo in meinem Code ich sie drucke. Für den Kontext sortiert der Code eine Liste von Erdbebendaten mithilfe einer BST und durchläuft dann die sortierten Daten, um die größte Lücke zwischen zwei aufeinander folgenden Erdbeben zu finden. Diese beiden Erdbeben werden dann hier gedruckt:Float druckt als NaN, druckt aber direkt danach den richtigen Wert

FILE* output_file = safe_open_file("task_1_bst.csv", "w"); 
fprintf(output_file, "timestamp,latitude,longitude,magnitude\n"); 
eq_print(output_file, sorted_arr[longest_index-1]); 
fprintf(output_file, "\n"); 
eq_print(output_file, sorted_arr[longest_index-1]); 
fprintf(output_file, "\n"); 
eq_print(output_file, sorted_arr[longest_index]); 
fclose(output_file); 

Wie Sie sehen können, bin ich den Druck eines der Erdbeben zweimal, und das ist das Ergebnis:

timestamp,latitude,longitude,magnitude 
2009-06-13T06:02:52.500Z,nan,-115.392,3.4 
2009-06-13T06:02:52.500Z,31.315,-115.392,3.4 
2009-06-13T16:04:06.650Z,3.930,126.648,4.4 

Aus irgendeinem Grund die Breite des ersten EQ ist beim ersten Druck ein Nanometer, wird aber beim zweiten Mal richtig gedruckt.

Es gibt ziemlich viel Code, also kann ich hier nicht alles einbeziehen. Das sorted_arr-Array ist voll von Zeigern auf eq_t-Typen.

typedef struct { 
    timestamp_t* timestamp; 
    float latitude; 
    float longitude; 
    float magnitude; 
    float x; 
    float y; 
} eq_t; 

timestamp_t ist nur eine Struktur von ganzen Zahlen (Jahr, Monat, Tag, Stunde usw.) und eq_print ist nur ein Wrapper um ein fprintf, die jeden Bereich des eq_t und timestamp_t druckt.

void eq_print(FILE* fp, eq_t* q) 
{ 
    fprintf(fp, "%d-%02d-%02dT%02d:%02d:%02d.%03dZ,%.3f,%.3f,%.1f", 
     q->timestamp->year, 
     q->timestamp->month, 
     q->timestamp->day, 
     q->timestamp->hour, 
     q->timestamp->min, 
     q->timestamp->sec, 
     q->timestamp->msec, 
     q->latitude, 
     q->longitude, 
     q->magnitude); 
} 

eq_print verändert nicht die eq_t überhaupt, also warum ist der gedruckte Wert anders, wenn kein Code zwischen den beiden fprintfs ist?

Was könnte die Ursache für einen Float mit einem NaN-Wert sein, und dann sofort nach dem richtigen Wert?

Bearbeiten: Wenn Sie jede dieser Zeilen mit GDB durchlaufen und den Breitengrad für jede Zeile drucken, wird der richtige Wert ausgegeben.

Breakpoint 1, task_1_find_longest_break_after_2k_bst (
    eq_csv_file=0x28cc87 "eq_data.csv") at tasks.c:128 
128    FILE* output_file = safe_open_file("task_1_bst.csv", "w"); 
(gdb) warning: cYgFFFFFFFF 611B75D0 0 
warning: cYgstd 0x28cbdf d 3 
print sorted_arr[longest_index-1]->latitude 
$1 = 31.3150005 
(gdb) next 
129    fprintf(output_file, "timestamp,latitude,longitude,magnitude\n"); 
(gdb) print sorted_arr[longest_index-1]->latitude 
$2 = 31.3150005 
(gdb) next 
130    eq_print(output_file, sorted_arr[longest_index-1]); 
(gdb) print sorted_arr[longest_index-1]->latitude 
$3 = 31.3150005 
(gdb) next 
131    fprintf(output_file, "\n"); 
(gdb) print sorted_arr[longest_index-1]->latitude 
$4 = 31.3150005 
(gdb) next 
132    eq_print(output_file, sorted_arr[longest_index-1]); 
(gdb) print sorted_arr[longest_index-1]->latitude 
$5 = 31.3150005 

Es gibt eine Warnung, dass ich nicht sicher bin, wie man interpretiert.

Die eq_t q wird mit dieser Funktion belegt

eq_t* read_quake(FILE* fp) 
{ 
    char buf[1024]; 
    float latitude, longitude, magnitude; 
    if (fscanf(fp, "%[^,],%f,%f,%f\n", buf, &latitude, &longitude, &magnitude) == 4) { 
     eq_t* eq = (eq_t*)safe_malloc(sizeof(eq_t)); 
     eq->timestamp = parse_time(buf); 
     eq->latitude = latitude; 
     eq->longitude = longitude; 
     eq->magnitude = magnitude; 
     map_coordinates(eq); 
     return eq; 
    } 
    return NULL; 
} 

Es gibt keine Probleme hier. Es scheint ein Problem mit dem Drucken zu sein.

+2

Es gibt keine Möglichkeit zu sagen, basierend auf den von Ihnen bereitgestellten Informationen. Fragen zur Fehlersuche ("Warum funktioniert dieser Code nicht?") muss das gewünschte Verhalten, ein bestimmtes Problem oder einen Fehler und den kürzesten Code enthalten, der für die Reproduktion in der Frage selbst erforderlich ist. Siehe: [** Erstellen eines minimalen, vollständigen und überprüfbaren Beispiels **] (http: // stackoverflow.com/help/mcve). –

+0

Grundsätzlich, wie füllen Sie 'q ->' Mitglieder ist wichtig –

+1

Können Sie einen Debugger verwenden, um die Werte im Array vor dem Schreiben in die Datei zu überprüfen? Auf diese Weise zumindest werden Sie kann herausfinden, ob das Problem mit Datei schreiben oder mit Daten ist. Ist auch das Programm Multithread? – taskinoor

Antwort

3

Hier ist eine Replikation Ihres Codes als MCVE (How to create a Minimal, Complete and Verifiable example).

#include <math.h>  /* NAN */ 
#include <stdio.h> 

/* 
timestamp,latitude,longitude,magnitude 
2009-06-13T06:02:52.500Z,nan,-115.392,3.4 
2009-06-13T06:02:52.500Z,31.315,-115.392,3.4 
2009-06-13T16:04:06.650Z,3.930,126.648,4.4 
*/ 

typedef struct timestamp_t 
{ 
    int year; 
    int month; 
    int day; 
    int hour; 
    int min; 
    int sec; 
    int msec; 
} timestamp_t; 

typedef struct 
{ 
    timestamp_t* timestamp; 
    float latitude; 
    float longitude; 
    float magnitude; // x, y unused so removed 
} eq_t; 

static timestamp_t times[] = 
{ 
    { 2009, 6, 13, 6, 2, 52, 500 }, 
    { 2009, 6, 13, 16, 4, 6, 650 }, 
}; 

static eq_t quakes[] = 
{ 
    { &times[0],  NAN, -115.392F, 3.4F }, 
    { &times[1], +3.930F, +126.648F, 4.4F }, 
}; 

static eq_t *sorted_arr[] = { &quakes[0], &quakes[1] }; 

static void eq_print(FILE* fp, eq_t* q) 
{ 
    fprintf(fp, "%d-%02d-%02dT%02d:%02d:%02d.%03dZ,%.3f,%.3f,%.1f", 
      q->timestamp->year, 
      q->timestamp->month, 
      q->timestamp->day, 
      q->timestamp->hour, 
      q->timestamp->min, 
      q->timestamp->sec, 
      q->timestamp->msec, 
      q->latitude, 
      q->longitude, 
      q->magnitude); 
} 

int main(void) 
{ 
    int longest_index = 1; 
    FILE *output_file = stdout; 
    fprintf(output_file, "timestamp,latitude,longitude,magnitude\n"); 
    eq_print(output_file, sorted_arr[longest_index-1]); 
    fprintf(output_file, "\n"); 
    eq_print(output_file, sorted_arr[longest_index-1]); 
    fprintf(output_file, "\n"); 
    eq_print(output_file, sorted_arr[longest_index]); 
    fprintf(output_file, "\n"); 
    fclose(output_file); 

    return 0; 
} 

rief ich es nan11.c, und es kompiliert sauber unter GCC 6.1.0 unter Mac OS X 10.11.6, und läuft und die gleiche Ausgabe zweimal:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes \ 
    -Wold-style-definition nan11.c -o nan11 
$ ./nan11 
timestamp,latitude,longitude,magnitude 
2009-06-13T06:02:52.500Z,nan,-115.392,3.4 
2009-06-13T06:02:52.500Z,nan,-115.392,3.4 
2009-06-13T16:04:06.650Z,3.930,126.648,4.4 
$ 

Wenn die Dinge unerwartet ändern, Das bedeutet normalerweise, dass ein Problem mit der Speicherverwaltung vorliegt, und bedeutet häufig, dass eine lokale Variable irgendwo zurückgegeben wird. Es ist ein wenig unerwartet, dass sich der Fehler bei der zweiten Druckoperation "selbst repariert".

Sie müssen ein MCVE analog zu dem, was ich zeige, das Lesen, Speicherzuweisung usw. ausführt, und dennoch Probleme auftreten. Sie sollten diesen Code unter valgrind ausführen, um festzustellen, ob Speichermissbrauch festgestellt werden kann.

Verwandte Themen