如何初始化结构

How to initialize struct

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

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

我在这里错过了什么?

因为clientData是一个char *clientData[i]是一个简单的字符。这与 createClient () 原型冲突,后者需要指向字符的指针,即以 NULL 结尾的字符串。

请注意,在对它们进行 malloc 之后,您永远不会对它们进行初始化。这在 运行 时间会是一个问题,因为 strdup () 需要复制一些东西(至少是一个空字符串!)。

第二个错误要求您将 malloc 的结果转换为 Client *(即使在这里很多人可能会告诉您避免它,许多编译器都需要它)。

可以合并读取和创建操作。然后在读取文件时,可以使用 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;
}