繁体   English   中英

如何使用fscanf或fgets在结构内动态分配字符串?

[英]How to Dynamically Allocate a string within a struct with fscanf or fgets?

我正在尝试使用fscanf在结构中分配字符串,我尝试了以下方法:

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

typedef struct _SPerson {
  char *name;
  char *surname;
  char *id;
  char *telephone;
}SPerson;

void main (void) {
  unsigned int ne;
  SPerson Archive[1000];
  Load(Archive,&ne);
}

int Load(SPerson Archive[],unsigned int *ne) {
  int k,i=0;
  char s[4][20];
  FILE *f;
  f = fopen("archive.txt","r");
  if(f==0) return 0;

  while((k=fscanf(f,"%s %s %s %s",s[0],s[1],s[2],s[3]))==4) {
    Archive[i].id = (char*) malloc( sizeof(char) *strlen(s[0])); 
    Archive[i].id =s[0];
    Archive[i].name = (char*) malloc( sizeof(char) *strlen(s[1])); 
    Archive[i].name = s[1];
    Archive[i].surname = (char*) malloc( sizeof(char) *strlen(s[2])); 
    Archive[i].surname = s[2];
    Archive[i].telephone = (char*) malloc( sizeof(char) *strlen(s[3])); 
    Archive[i].telephone =s[3];
    i++;    
  }

  *ne = i;
  fclose(f);
  return 1;
}

也许在我的脑海中是正确的,但是在加载数据时出了点问题,所以这是动态读取字符串的正确而清晰的方法吗? 我以为使用fgets ,但是我的字符串用空格隔开,所以我需要实现另一个功能,即split。 谁能帮我?

 while((k=fscanf(f,"%s %s %s %s",s[0],s[1],s[2],s[3]))==4) {
     //your code
     i++;    
 }

而不是使用fgets读取完整的数据,然后使用strtok将其标记化-

char data[1024],*token;
 int j=0;
while(fgets(data,sizeof data,f)!=NULL){         //read from file
       token=strtok(data," ");                  //tokenize data using space as delimiter
       while(token!=NULL && j<4){
            j=0;
            sprintf(s[j],"%s",token);          //store it into s[i]
            j++;
            token=strtok(NULL," ");
       }
       Archive[i].id = malloc(sizeof *Archive[i].id * (strlen(s[0])+1));    //allocate memory 
       strcpy(Archive[i].id,s[i]);          //copy at that allocated memory
         //similar for all
       i++;
}

可以使用它代替循环。

注意 - 请勿这样做 -

 Archive[i].id = (char*) malloc( sizeof(char) *(strlen(s[0])+1)); 
 Archive[i].id =s[0];         <-- 2.

2.语句之后一样,您将失去对先前分配的内存的引用,并且将无法free它-导致内存泄漏。

对于以下所有此类语句,都是相同的。

有几个快速建议可以改进:

1) void main(void)确实不是 main的良好原型。 采用:

int main(void);

要么:

int main(int argc, char **argv);

2)无需在C中强制转换[m] [c] [re] alloc的返回值
您代码中的这一行:

Archive[i].id = (char*) malloc( sizeof(char) *strlen(s[0]));
                ^^^^^^^         ^^^^^^^^^^^^^^              //^^^ == remove

应该写成:

Archive[i].id = malloc( strlen(s[0]) + 1);//no cast, and sizeof(char) is always == 1
                                          //"+ 1" for NULL termination

3)建议使用fgets()strtok()strcpy()作为从文件读取,解析和复制字符串到struct成员的最小方法:

注意:这里将有许多对malloc()的调用,每个调用都必须在某个时候释放。 为了避免所有这些,最好是您的结构包含具有硬编码堆栈内存的成员:

typedef struct
{
    char name[80];
    char surname[80];
    char id[80];
    char telephone[80];
}SPerson;

但是,假设您有使用内存的理由,这是一种使用定义的结构来进行处理的方法:

char line[260];//line buffer (hardcoded length for quick demo)
char *tok={0};//for use with strtok()
int len = 0;//for use with strlen()
FILE *f;

f = fopen("archive.txt","r");//did not have example file for this demo
                             //therefore do not have delimiters, will guess
if(f==0) return 0;

i = 0;//initialize your index
while(fgets(line, 260, f))
{
    tok = strtok(line, " ,\n\t");// will tokenize on space, newline, tab and comma
    if(tok)
    {
        len = strlen(tok);
        Archive[i].id = malloc(len + 1);//include space for NULL termination
        strcpy(Archive[i].id, tok);//note correct way to assign string
        //(Archive[i].id = tok is incorrect!!)
    }
    else {//handle error, free memory and return}
    tok = strtok(NULL, " ,\n\t");//note NULL in first arg this time 
    if(tok)
    {
        len = strlen(tok);
        Archive[i].name= malloc(len + 1);//include space for NULL termination
        strcpy(Archive[i].name, tok);

    }
    else {//handle error, free memory and return}
    //...And so on for rest of member assignments
    //
    i++;//increment index at bottom of while loop just before reading new line
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM