如何初始化结构

时间:2019-11-28 21:40:49

标签: c struct dynamic-arrays

我不确定这是否是使用值创建和初始化结构的正确方法:

#define LINES 4
#define LENGHT 30

typedef struct
{
  char *name;
  char *phoneNumber;
  char *location;
  char *traveltype;
} Client;

void readClientData(char *filename, char *clientData[]);
Client *createClient(char *name, char *phoneNumber, char *location, char *traveltype);

int main(int argc, char *argv[])
{
  char *filename = argv[1];
  char *clientData = (char *)malloc(LINES * sizeof(char)*LENGHT);
  readClientData(filename, &clientData);
  Client *client = createClient(clientData[0], clientData[1], clientData[2], clientData[3]);
  return 0;
}

Client *createClient(char *name, char *phoneNumber, char *location, char *traveltype)
{
  Client *client = malloc(sizeof(Client));
  client->name = strdup(name);
  client->phoneNumber = strdup(phoneNumber);
  client->location = strdup(location);
  client->traveltype = strdup(traveltype);
  return client;
}

我正在尝试创建自己的结构,但出现以下错误:

error: invalid conversion from 'char' to 'char*' [-fpermissive]
   Client *client = createClient(clientData[0], clientData[1], clientData[2], clientData[3]);

error: invalid conversion from 'void*' to 'Client*' [-fpermissive]
   Client *client = malloc(sizeof(Client));

我在这里想念什么?

2 个答案:

答案 0 :(得分:1)

由于workingclientData,所以char *是一个简单字符。这与clientData[i]原型(期望使用指向以NULL结尾的字符串的char的指针)相冲突。

请注意,在分配它们之后,您永远不会初始化它们。这在运行时将是一个问题,因为createClient ()需要复制一些内容(至少要包含一个空字符串!)。

第二个错误要求您将malloc的结果强制转换为strdup ()(即使在很多情况下也可能会告诉您避免这样做,许多编译器都需要它)。

答案 1 :(得分:1)

读取和创建操作可以合并。然后,在读取文件时,可以使用realloc增加客户端的数量。分配一个额外的结构以充当哨兵。或跟踪分配的结构数。
对于每种结构,请尝试从文件中读取四行,然后strdup行到结构指针。

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

typedef struct
{
    char *name;
    char *phoneNumber;
    char *location;
    char *traveltype;
} Client;

char *linefree ( char *line) {
    free ( line);
    return NULL;
}

Client *clientfree ( Client *client) {
    size_t count = 0;
    //the sentinel element will have name as NULL
    while ( client && client[count].name) {
        client[count].name = linefree ( client[count].name);
        client[count].phoneNumber = linefree ( client[count].phoneNumber);
        client[count].location = linefree ( client[count].location);
        client[count].traveltype = linefree ( client[count].traveltype);
        count++;
    }
    free ( client);
    return NULL;
}

void showclient ( Client *client) {
    size_t count = 0;
    //the sentinel element will have name as NULL
    while ( client && client[count].name) {
        printf ( "%s\n", client[count].name);
        if ( client[count].phoneNumber) {
            printf ( "   %s\n", client[count].phoneNumber);
        }
        if ( client[count].location) {
            printf ( "   %s\n", client[count].location);
        }
        if ( client[count].traveltype) {
            printf ( "   %s\n", client[count].traveltype);
        }
        count++;
    }
}

Client *readClientData ( char *filename) {
    size_t count = 0;
    FILE *pf = NULL;
    Client *client = NULL;
    Client *temp = NULL;
    if ( NULL == ( pf = fopen ( filename, "r"))) {
        perror ( filename);
        exit ( EXIT_FAILURE);
    }
    while ( 1) {
        // count + 2 to have sentinel element
        if ( NULL == ( temp = realloc ( client, sizeof *client * ( count + 2)))) {
            fprintf ( stderr, "realloc problem\n");
            return client;
        }
        client = temp;
        //set current element to NULL
        client[count].name = NULL;
        client[count].phoneNumber = NULL;
        client[count].location = NULL;
        client[count].traveltype = NULL;
        count++;
        //following serves as sentinel element
        client[count].name = NULL;
        client[count].phoneNumber = NULL;
        client[count].location = NULL;
        client[count].traveltype = NULL;

        char line[1024] = "";

        if ( ! fgets ( line, sizeof line, pf)) {
            fprintf ( stderr, "fgets EOF\n");
            break;
        }
        if ( NULL == ( client[count - 1].name = strdup ( line))) {
            fprintf ( stderr, "strdup name problem\n");
            break;
        }
        if ( ! fgets ( line, sizeof line, pf)) {
            fprintf ( stderr, "fgets EOF\n");
            break;
        }
        if ( NULL == ( client[count - 1].phoneNumber = strdup ( line))) {
            fprintf ( stderr, "strdup phoneNumber problem\n");
            break;
        }
        if ( ! fgets ( line, sizeof line, pf)) {
            fprintf ( stderr, "fgets EOF\n");
            break;
        }
        if ( NULL == ( client[count - 1].location = strdup ( line))) {
            fprintf ( stderr, "strdup location problem\n");
            break;
        }
        if ( ! fgets ( line, sizeof line, pf)) {
            fprintf ( stderr, "fgets EOF\n");
            break;
        }
        if ( NULL == ( client[count - 1].traveltype = strdup ( line))) {
            fprintf ( stderr, "strdup traveltype problem\n");
            break;
        }
    }
    fclose ( pf);
    return client;
}

int main ( void) {
    char filename[1024] = "";
    printf ( "Enter a filename\n");
    if ( ! fgets ( filename, sizeof filename, stdin)) {
        fprintf ( stderr, "fgetline filename problem\n");
        exit ( EXIT_FAILURE);
    }
    filename[strcspn ( filename, "\n")] = 0;//remove trailing newline
    Client *client = readClientData ( filename);

    showclient ( client);

    client = clientfree ( client);

    return 0;
}