从C中的文件读入后,指针数组中的每个指针都存储相同的值

时间:2017-05-30 15:35:54

标签: c pointers

这是我从代码片段中读取文件和createClient的值的代码片段。我有一组客户端,我给不同的数组元素赋予不同的值。

FILE *clientFile;
clientFile = fopen("clients.txt", "r");
char id[256];
char name[256]; 
char phone[256];
char email[256];
Client cptrs[10];
int i=0;
while(fgets(id, sizeof(id), clientFile)){
    //fscanf(clientFile, "%s", name);
    fgets(name, sizeof(name), clientFile);
    fgets(phone, sizeof(phone), clientFile);
    fgets(email, sizeof(email), clientFile);
    /*fscanf(clientFile, "%s", phone);
    fscanf(clientFile, "%s", email);*/
    //printf("%s %s %s %s\n", id,name,phone,email);
    cptrs[i] = createClient(id,name,phone,email);
    //printc(cptrs[i]);
    //printf("%d\n", i);
    i++;

}
printc(cptrs[0]);
printc(cptrs[1]);
printc(cptrs[2]);

所有3个打印功能输出的结果与文件中的最后一个数据相同。

这是struct client,createClient方法和printc方法。我已经包含了client.h和client.c文件。

client.h

#ifndef CLIENT_H
#define CLIENT_H

typedef struct client *Client;

Client createClient(char* id, char* name, char* phone, char* email);
void destroyClient(Client cP);
void printc(Client cP);

#endif

client.c

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

struct client {
  char* id;
  char* name;
  char* phone;
  char* email;
};


// returns the pointer to the list; NULL if list not created
Client createClient(char* id, char* name, char* phone, char* email) {
  // allocate memory for a structure variable containing all
  // list components
  Client cptr = malloc(sizeof(struct client));
  // if allocation was succesfull
  if (cptr != NULL) {
     cptr->id = id;
     cptr->name = name;
     cptr->phone = phone;
     cptr->email = email;

  }
  return cptr;
}

void destroyClient(Client cptr) {
  free(cptr);
}

void printc(Client cptr){
  printf("%s %s %s %s\n", cptr->id, cptr->name, cptr->phone, cptr->email);
}

这是clients.txt文件

1212
Joseph Miller
206-555-1212
millers@comcast.net
1313
Beatrice Pizarro Ozuna
206-111-1111
bea@uw.edu
1314
Anne Simpson
425-777-8888
a.simpson@gmail.com
1100
Emily Price
206-111-5555
priceless@yahoo.com
1289
Sharon Henderson
206-555-1289
henderson21@comcast.net
1316
Sylvia Williamson
425-123-8888
sylvia@gmail.com
1101
Michael Murphy
425-111-5555
gemini@yahoo.com

第一个代码的输出是:

1101
 Michael Murphy
 425-111-5555
 gemini@yahoo.com

1101
 Michael Murphy
 425-111-5555
 gemini@yahoo.com

1101
 Michael Murphy
 425-111-5555
 gemini@yahoo.com

我不明白为什么所有数组元素都存储相同的元素(文件中的最后一个元素)。我希望他们存储各自的元素。请帮忙。

2 个答案:

答案 0 :(得分:2)

在createClient中,您需要复制您在参数中传递的字符串,因为它们实际上是指向您在第一个片段中声明的静态字符缓冲区的指针。这些会在你的while循环中的每次迭代中被覆盖。

尝试:

  if (cptr != NULL) {
     cptr->id = strdup(id);
     cptr->name = strdup(name);
     cptr->phone = strdup(phone);
     cptr->email = strdup(email);    
  }

在destroyClient中,确保释放strdup隐式分配的内存:

void destroyClient(Client cptr) {
  free(cptr->id);
  free(cptr->name);
  free(cptr->phone);
  free(cptr->email);
  free(cptr);
}

答案 1 :(得分:1)

下面

Client createClient(char* id, char* name, char* phone, char* email) {
  // allocate memory for a structure variable containing all
  // list components
  Client cptr = malloc(sizeof(struct client));
  // if allocation was succesfull
  if (cptr != NULL) {
     cptr->id = id;
     cptr->name = name;
     cptr->phone = phone;
     cptr->email = email;

  }
  return cptr;
}

您只需指定输入指针值,例如id,给新客户。由于createClient的所有调用都传递了来自main的相同指针,因此结果是所有创建的客户端都包含指向main中相同变量的指针。

您需要为每个内存分配新内存并将数据复制到已分配的内存中。类似的东西:

Client createClient(char* id, char* name, char* phone, char* email) {
  // allocate memory for a structure variable containing all
  // list components
  Client cptr = malloc(sizeof(struct client));
  // if allocation was succesfull
  if (cptr != NULL) {
     cptr->id = malloc(256);  // Allocate memory
     strcpy(cptr->id, id);    // Copy data to the new memory
     // ... and so on
  }
  return cptr;
}

注意:为了使示例简单,我跳过检查malloc返回NULL。您应该在strcpy

之前添加

另请注意,您需要更改destroyClient,以便释放所有内存,例如free(cptr->id)

另一种方法:

当您处理相当少量的内存时,可能值得考虑避免struct client中的指针,而是:

struct client {
  char id[256];
  char name[256];
  char phone[256];
  char email[256];
};

然后你可以使用malloc中的一个createClient,然后strcpy(甚至是memcpy)。