Float打印为NaN,但之后会立即打印正确的值

时间:2016-08-14 04:10:34

标签: c printing nan

我一直有一些奇怪的问题,根据我的代码中我打印它们的位置打印为NaN浮点数。对于上下文,代码使用BST对地震数据列表进行排序,然后循环排序数据以找出两次连续地震之间的最大间隙。这两个地震然后打印在这里:

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* timestamp;
    float latitude;
    float longitude;
    float magnitude;
    float x;
    float y;
} eq_t;

出于某种原因,第一个EQ的纬度在首次打印时为nan,但第二次打印正确。

有很多代码,所以我不能在这里全部包含它。 sorted_arr数组充满了指向eq_t类型的指针。

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

timestamp_t只是一个整数结构(年,月,日,小时等),而eq_print只是打印fqf的包装器,它打印eq_t和timestamp_t的每个字段。

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

eq_print根本没有修改eq_t,那么当两个fprintf之间没有代码时,为什么打印值会有所不同?

浮点数具有NaN值的原因是什么,然后在具有正确值之后立即?

编辑:使用GDB逐步浏览每一行并在每行打印纬度打印正确的值。

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

有一个警告,我不确定如何解释。

eq_t q被赋予此功能

 CREATE TABLE CUSTOMER1
  (
   CUSTOMERID          VARCHAR2(2) NOT NULL,
   FIRSTNAME           VARCHAR2(50) NOT NULL,
   LASTNAME            VARCHAR2(50) NOT NULL,
   PHONENUMBER         VARCHAR2(50) NOT NULL,
   BIRTHDATE           DATE NOT NULL,
   DRIVERLICENSENUMBER NUMBER,
   STATUS              VARCHAR2(50),
   CREDITCARENUMBER    NUMBER,
   CONSTRAINT CustomerID_PK PRIMARY KEY(CUSTOMERID)
  );



CREATE TABLE CCATEGORY
 (
  CATEGORYID   INT NOT NULL,
  CATEGORYNAME VARCHAR2(50) NOT NULL,
 CONSTRAINT categoryID_pk PRIMARY KEY (CATEGORYID)
);


CREATE TABLE TAPE
 (
TAPEID         NUMBER(5) NOT NULL,
TAPETITLE      VARCHAR2(200) NOT NULL,
RELEASEYEAR    NUMBER(5) NOT NULL,
DATEPURCHASED  DATE NOT NULL,
PRICE          NUMERIC(5) NOT NULL,
RENTEDOUT      VARCHAR2(20) NOT NULL,
RATING         VARCHAR2(10) NOT NULL,
ACTIONONRETURN VARCHAR2(50) NOT NULL,
PRIMARY KEY(TAPEID),
CONSTRAINT FK_CATEGORYID FOREIGN KEY(CATEGORYID) REFERENCES CCATEGORY(CATEGORYID),
CONSTRAINT FK_RESERVEDBY FOREIGN KEY(CUSTOMERID) REFERENCES CUSTOMER(CUSTOMERID)
); 

这里没有任何问题。这似乎是印刷的一个问题。

1 个答案:

答案 0 :(得分:3)

以下是将代码复制为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;
}

我称之为nan11.c,它在Mac OS X 10.11.6上的GCC 6.1.0下完全编译,运行并产生两次相同的输出:

$ 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
$

当事情意外地发生变化时,通常意味着内存管理存在问题,并且通常意味着在某处返回本地变量。不过,在第二次打印操作中,错误“自我修复”有点出乎意料。

你需要处理类似于我所展示的MCVE,它实际上是读取,内存分配等,但仍然会遇到问题。您应该考虑在valgrind下运行该代码,以查看它是否可以发现内存滥用。