c - 函数似乎返回正确的值,但外部调用者永远不会在 C 中获取它

标签 c function queue printf getter

我使用链表实现了一个队列。我还创建了一个 getter 来读取此队列中任何条目的数据。当我从测试器调用此函数时,我发现作为队列内条目的值返回的值与在 getter 中读取的值不同。

struct entry{
    double data;
    attribute_value time_stamp;
    struct entry* next;
};


typedef struct queue_struct{
    struct entry* front;
    struct entry* end;
    int size;
} queue;

下面的 getter 接受队列的条目,如果当前条目不为空,则返回数据结构变量的值:

double get_data(struct entry *current){
    // The value is correct here
    printf("!!!!!!!!!!!!! %lf\n", current->data);
    if(current) return current->data; 
    return 0;
}

我使用这个助手来获取队列的第一个条目:

struct entry* get_front(queue *Q){
    return Q->front;
}

这是测试仪。它创建一个队列(只是为其分配空间并分配first = NULL、end = NULL 和size = 0)。然后它将值 10 推送到队列中。 (忽略零!它与数据没有任何关系)。然后,它通过从第一个元素开始并打印“data”变量直到遇到 NULL 元素来成功打印队列。然后,我要求它打印队列中第一个条目/元素的数据。这就是我得到错误值的地方。

void test_queue_push(bool enable_print){
    printf(TESTING, "Testing push in queue.c");
    queue* Q = construct_queue();

    push(Q, 10, 0);
    if(enable_print) print_queau(Q); // This prints the queue correctly!

    // The wrong value is printed here!
    printf("GET DATA: %lf\n", get_data(get_front(Q))); 
}

此测试打印出以下内容:

10.000000 ->                        // This is result of print_queue
!!!!!!!!!!!!! 10.000000             // This is data of first entry printed INSIDE the getter function itself
GET DATA: 0.000000                  // This is the returned data of first entry, printed inside the tester

我不明白为什么我没有获得第二行和第三行的值“10.0000”。

I just tried using "long long int" instead of "double" for the entry's data variable and all of the other functions. The error disappears if I use a different data type. No idea why.

打印队列也使用了get_data函数,打印输出的第一行反射(reflect)了print_queue中的get_data工作得很好。这是函数:

void print_queau(queue* Q) {
    struct entry* temp = get_front(Q);
    while(temp != NULL) {
        printf("%lf -> ", get_data(temp));
        temp = get_next(temp);
    }
    printf("\n");
}

以防万一,推送功能如下所示:

void push(queue* Q, double input, attribute_value time_stamp){
    if(Q){ //if Queue exists
    struct entry* in;   //create a new entry object
        if(in = calloc(1, sizeof(struct entry))){ //if allocating space for the entry object succeeds
            Q->size = Q->size + 1;
            in->data = input; //enter the input as its current data
            in->next = NULL; //set next to null because the end of the queue can have no next entry that follows it
            in->time_stamp = time_stamp; //set the time stamp to the Power On Hours on the system

            if(get_front(Q) == NULL && get_end(Q) == NULL){  //if front and end of the queue have not yet been set
                set_front(Q, in); //then this entry is both the front
                set_end(Q, in); //and the end
                return;
            }
            set_next(get_end(Q), in); //next value of the entry at the end is now our new entry
            set_end(Q, in);
            //printf("The End is: %i\n", Q->size);
        }
    }
}

构造队列如下所示:

/*Constructor for the Queue structure instance
    @param none
    @return pointer to queue or NULL pointer in case of memory allocaion failure
*/
queue* construct_queue(){
    queue* Q;
    if(Q = calloc(1, sizeof(queue))){ 
        Q->front = NULL;  //at first the queue does not have any entries
        Q->end = NULL;    //therefore it has no front and no end
        Q->size = 0;      //its size starts off at zero to indicate that there are no entries.
    }
    if(Q == NULL){
        fprintf(stderr, "Ran out of memory when allocating memory for queue in construct_queue in queue.c\n");
    }
    return Q;
}

我使用以下代码来构建上面的代码:https://gist.github.com/mycodeschool/7510222

最佳答案

有很多缺失的代码需要重建。这段代码仔细确保所有函数在使用之前都已声明,似乎可以正常工作:

#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef int attribute_value;

#define TESTING "%s\n"

struct entry
{
    double data;
    attribute_value time_stamp;
    struct entry *next;
};

typedef struct queue_struct
{
    struct entry *front;
    struct entry *end;
    int size;
} queue;

double get_data(struct entry *current);
queue *construct_queue(void);
struct entry *get_front(queue *Q);
struct entry *get_end(queue *Q);
void print_queau(queue *Q);
void push(queue *Q, double input, attribute_value time_stamp);
void test_queue_push(bool enable_print);
struct entry *get_next(struct entry *curr);
void set_front(queue *Q, struct entry *in);
void set_end(queue *Q, struct entry *in);
void set_next(struct entry *E, struct entry *in);

void set_front(queue *Q, struct entry *in)
{
    if (Q != 0)
        Q->front = in;
}

void set_end(queue *Q, struct entry *in)
{
    if (Q != 0)
        Q->end = in;
}

void set_next(struct entry *E, struct entry *in)
{
    if (E != 0)
        E->next = in;
}

struct entry *get_next(struct entry *curr)
{
    if (curr != 0)
        return curr->next;
    return 0;
}

double get_data(struct entry *current)
{
    if (current)
    {
        printf("!!!!!!!!!!!!! %lf\n", current->data);
        return current->data;
    }
    return 0;
}

struct entry *get_end(queue *Q)
{
    return Q->end;
}

struct entry *get_front(queue *Q)
{
    return Q->front;
}

void test_queue_push(bool enable_print)
{
    printf(TESTING, "Testing push in queue.c");
    queue *Q = construct_queue();

    push(Q, 10, 0);
    if (enable_print)
        print_queau(Q);


    printf("GET DATA: %lf\n", get_data(get_front(Q)));
}

void print_queau(queue *Q)
{
    struct entry *temp = get_front(Q);
    while (temp != NULL)
    {
        printf("%lf -> ", get_data(temp));
        temp = get_next(temp);
    }
    printf("\n");
}

void push(queue *Q, double input, attribute_value time_stamp)
{
    if (Q)
    {
        struct entry *in;
        if ((in = calloc(1, sizeof(struct entry))) != 0)
        {
            Q->size = Q->size + 1;
            in->data = input;
            in->next = NULL;
            in->time_stamp = time_stamp;

            if (get_front(Q) == NULL && get_end(Q) == NULL)
            {
                set_front(Q, in);
                set_end(Q, in);
                return;
            }
            set_next(get_end(Q), in);
            set_end(Q, in);
        }
    }
}

queue *construct_queue(void)
{
    queue *Q;
    if ((Q = calloc(1, sizeof(queue))) != 0)
    {
        Q->front = NULL;
        Q->end = NULL;
        Q->size = 0;
    }
    if (Q == NULL)
    {
        fprintf(stderr, "Ran out of memory when allocating memory for queue in construct_queue in queue.c\n");
    }
    return Q;
}

int main(void)
{
    test_queue_push(true);
    return 0;
}

编译:

$ gcc -O3 -g -std=c11 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>     -Werror queue.c -o queue
$

这是 Mac OS X 10.10.4 上的 GCC 5.1.0,选项设置繁琐且没有警告。 “prototypes”选项确保函数在定义或使用之前进行声明,或者是静态函数。我在这里没有做任何静态的事情;当只有一个源文件时我通常会这样做。

示例输出:

Testing push in queue.c
!!!!!!!!!!!!! 10.000000
10.000000 -> 
!!!!!!!!!!!!! 10.000000
GET DATA: 10.000000

有理由认为问题要么是缺少一个或多个函数原型(prototype),要么是忽略的函数之一存在错误。请注意,我修复了 get_data() 中的代码,因此如果 current 指针为 NULL,它不会崩溃 - 您的代码尝试打印 current-> 中的值data 无论 current 是否为空(即使它随后检查了值 current - 只是有点太晚了)。

关于c - 函数似乎返回正确的值,但外部调用者永远不会在 C 中获取它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31955624/

相关文章:

java - 数组队列 - 使用 -xlint : unchecked/unsafe operations 重新编译

PHP警告: Module 'Phar' already loaded in Unknown on line 0

C - 列出当前目录中的所有文件,然后移动到上面的目录,列出文件,依此类推,直到到达根目录

c - 你如何以可重入的方式 InitializeCriticalSection?

c - 这个C函数有什么问题? (printf() 和 getchar())

无法将两个作为文件名的命令行参数传递给函数

c# - 有没有更好的方法来等待排队的线程?

C 中的常量 : declaration separate from definition

javascript - 当变量等于函数时,这意味着什么?

performance - 为什么 PostgreSQL 多次调用我的 STABLE/IMMUTABLE 函数?