函数如何处理多个结构?

时间:2014-09-21 21:38:49

标签: c structure

我有一台设备。它需要命令。我得到了结果,并希望将它们放到更有用的形式中。

示例:

issue_command()应该将一个结构作为请求和指向结果结构的指针...但结构可以是我传递的任何内容。所有人都有大约50个结构。

issue_command(read_request, &result_struct);

我觉得C不能这样做,我无法想出一个可能的解决方案(它是我的程序中唯一未完成的方面)。

用外行人的话说,我想传递一个命令结构,该结构被炸成设备,结果结构参数从字节结果中传递memcpy()'。

1 个答案:

答案 0 :(得分:0)

这是一个做我认为你想要的示例程序:

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


/*  Enumeration, structs, and union for requests  */

enum request_type {
    REQUEST_ONE,
    REQUEST_TWO
};

struct request_one {
    int something;
    char data[10];
};
struct request_two {
    double something_else;
    char data[20];
};

struct request {
    enum request_type type;
    union {
        struct request_one one;
        struct request_two two;
    } request_struct;
};


/*  Enumeration, structs, and union for responses  */

enum response_type {
    RESPONSE_ONE,
    RESPONSE_TWO
};

struct response_one {
    char data[10];
};
struct response_two {
    char data[20];
};

struct response {
    enum response_type type;
    union {
        struct response_one one;
        struct response_two two;
    } response_struct;
};


/*  Constructor functions for request structs  */

struct request * make_request_one(const int something,
                                  char * data) {
    struct request * new_request = malloc(sizeof *new_request);
    if ( !new_request ) {
        perror("Couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    new_request->type = REQUEST_ONE;
    new_request->request_struct.one.something = something;
    strcpy(new_request->request_struct.one.data, data);

    return new_request;
}

struct request * make_request_two(const double something_else,
                                  char * data) {
    struct request * new_request = malloc(sizeof *new_request);
    if ( !new_request ) {
        perror("Couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    new_request->type = REQUEST_TWO;
    new_request->request_struct.two.something_else = something_else;
    strcpy(new_request->request_struct.two.data, data);

    return new_request;
}


/*  Constructor functions for response structs  */

struct response * make_response_one(char * data) {
    struct response * new_response = malloc(sizeof *new_response);
    if ( !new_response ) {
        perror("Couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    new_response->type = RESPONSE_ONE;
    strcpy(new_response->response_struct.one.data, data);

    return new_response;
}

struct response * make_response_two(char * data) {
    struct response * new_response = malloc(sizeof *new_response);
    if ( !new_response ) {
        perror("Couldn't allocate memory");
        exit(EXIT_FAILURE);
    }

    new_response->type = RESPONSE_TWO;
    strcpy(new_response->response_struct.two.data, data);

    return new_response;
}


/*  Issue command function  */

struct response * issue_command(struct request * request) {
    struct response * response;

    switch ( request->type ) {
        case REQUEST_ONE:
            response = make_response_one("resp 1");
            break;

        case REQUEST_TWO:
            response = make_response_two("response 2 stuff");
            break;

        default:
            assert(0);
    }

    return response;
}

int main(void) {

    /*  Call issue_command() with request and response one  */

    struct request * req1 = make_request_one(666, "req 1");
    struct response * resp1 = issue_command(req1);

    printf("Request: %s, Response: %s\n",
           req1->request_struct.one.data,
           resp1->response_struct.one.data);

    free(req1);
    free(resp1);


    /*  Call issue_command() with request and response two  */

    struct request * req2 = make_request_two(3.14159, "request 2 stuff");
    struct response * resp2 = issue_command(req2);

    printf("Request: %s, Response: %s\n",
           req2->request_struct.two.data,
           resp2->response_struct.two.data);

    free(req2);
    free(resp2);

    return 0;
}

和输出:

paul@local:~/src/sandbox$ ./reqresp
Request: req 1, Response: resp 1
Request: request 2 stuff, Response: response 2 stuff
paul@local:~/src/sandbox$ 

正如您所看到的,issue_command()函数通过单个输入参数有效地接受两种不同类型的结构,并使用单个返回值有效地返回两种不同类型的结构。这是通过在两种情况下将不同的结构包装在一个联合中来实现的,但是你可以通过void指针实现类似的结果,并且实际上传递和返回完全不同的结构(而不​​是包含不同结构的联合的单个结构) )。

我在issue_command()所做的一切都是阅读类型并构建适当的回复,但在switch区块中,一旦您确定了自己的类型,就可以做你喜欢的事,访问请求的个别成员,或memcpy()整个事情,或其他什么。同样,对于回复,一旦您知道您的请求类型,您就可以阅读并填写您喜欢的回复成员。