如何return构造值?

How to return structure value?

我正在尝试 return 值并将它们打印到文件中...我声明了结构并读取文件获取值并将它们保存到指针中,但我做不到设法 return 他们发挥作用...

你能帮我吗?我只能 return 一个变量然后它给了我 (null) 而我不能 return 其他变量比如 .age .efternamn.

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10000
int elever = 1;

struct likaprogramms {
  char civilekonom[50];
  char högskoleingenjör[50];
  char civilingenjör[50];
  char systemutvecklare[50];
};

struct student {
  char personnummer[32];
  char förnamn[32];
  char efternamn[32];
  char gender[32];
  char programmdife[32];
  char age[32];
  char email[32];
  struct likaprogramms *likaprogramm;
};

struct student *personer;

struct programms {
  char namnen;
  char mcode;
  char responsible;
  char email;
};

void (*display[5])();

void* base(char *display[5]) {
  //char fileA[MAX];
  char tal;
  int columns;
  FILE *f;
  f = fopen("elever.txt", "r");
  personer = (struct student*) malloc(elever * sizeof(struct student));
  personer->likaprogramm = malloc(sizeof(struct likaprogramms) * elever);
  display = malloc(sizeof *display);
  for (elever = 0; !feof(f);) {
    tal = fgetc(f);
    if (tal == '\n')
      printf("\n");
    {
      elever++;
      columns = 0;
      if (tal == ' ') {
        columns++;
      }

      if (columns == 0) {
        fscanf(f, " %s", &personer[elever].personnummer);
        //printf("%s",personer[elever].personnummer);
        // return (personer[elever].personnummer);  
        //columns++;                       
      }
      columns++;
      if (columns == 1) {
        fscanf(f, " %s", &personer[elever].förnamn);
        //  return (personer[elever].förnamn); 
      }
      columns++;
      if (columns == 2) {
        fscanf(f, " %s", &personer[elever].efternamn);
        //return (personer[elever].efternamn);                      
      }
      columns++;
      if (columns == 3) {
        fscanf(f, " %s", &personer[elever].gender);
        // return( personer[elever].gender);
      }
      columns++;
      if (columns == 4) {
        fscanf(f, " %s ", &personer[elever].programmdife);
        // return( personer[elever].programmdife);
      }
      columns++;
      if (columns == 5) {
        fscanf(f, " %s", &personer[elever].age);
        // return(personer[elever].age);
      }
      columns++;
      if (columns == 6) {
        fscanf(f, " %s", &personer[elever].email);
        // return(personer[elever].email);                   
      }
      return &personer[elever];
    }
    //free(personer);
  }
  // return 0;
  //fclose("elever.txt");     
}

int i;
int main() {
  display[i] = base(*display[i]);

  FILE *h;
  h = fopen("Filedatabase.txt", "w");
  if (h == NULL) {
    printf("Could not write the file!\n");
    exit(1);
  } else {
    for (int i = 0; i < 7;) {
      fprintf(h, "%s\n", display[i]);

      printf("\n");
      i++;
    }

    printf("open the file");
  }
  fclose(h);
  free(display);

  return 0;
}

你的代码中有一个很大的网格,我会尝试解码它,向你展示错误:

#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#define MAX 10000
int elever = 1;

struct likaprogramms {
  char civilekonom[50];
  char högskoleingenjör[50];
  char civilingenjör[50];
  char systemutvecklare[50];
};

struct student {
  char personnummer[32];
  char förnamn[32];
  char efternamn[32];
  char gender[32];
  char programmdife[32];
  char age[32];
  char email[32];
  struct likaprogramms *likaprogramm;
};

struct student *personer;

struct programms {
  char namnen;
  char mcode;
  char responsible;
  char email;
};

void (*display[5])();

display 是一个包含 5 个指向 void 函数的数组,这些函数采用未确定数量的参数(不完整的类型定义,因为要存储的函数的参数类型和数量是not specified in the definition) 这在 C 中维护以实现遗留代码兼容性,但今天不推荐使用。虽然这不是错误,但我不明白你为什么要为数组设计如此复杂的声明。


void* base(char *display[5]) {

这里,display 是一个包含 5 个指向 char 的指针的数组(或者字符串,如果它们要被 '[=21=]' 终止)问题是你已经命名了 display 局部变量与全局数组同名(也有 5 个指向函数的指针)所以我现在唯一能说的是你以后 运行 会遇到麻烦。

  //char fileA[MAX];
  char tal;
  int columns;
  FILE *f;
  f = fopen("elever.txt", "r");
  personer = (struct student*) malloc(elever * sizeof(struct student));
  personer->likaprogramm = malloc(sizeof(struct likaprogramms) * elever);
  display = malloc(sizeof *display);
  for (elever = 0; !feof(f);) {

feof(f) return 仅在 之后 您尝试读取文件后才有效,而不是在检查之前。虽然这不是问题,但您将使用此 for 循环将垃圾记录添加到您的数组中,因为只有当您已经尝试读取不完整的内容时,它才会 return 您 EOF(但您已将其添加到数据库中)。

    tal = fgetc(f);

您之前可以使用 while ((tal = fgetc(f)) != EOF) 代替(因为您正在一个接一个地阅读字符)。但是为了这个目的,tal 必须声明为 int(而不是 char),因为 EOF 是一个整数常量,不在任何可能的字符值之外,你可以存储在 char变量。无论如何,您都可以在后续代码中对 int 变量进行操作,但这样一来,它允许您在处理任何无效数据之前检测文件结束条件。

    if (tal == '\n')
      printf("\n");
    {
      elever++;
      columns = 0;
      if (tal == ' ') {
        columns++;
      }

      if (columns == 0) {
        fscanf(f, " %s", &personer[elever].personnummer);
        //printf("%s",personer[elever].personnummer);
        // return (personer[elever].personnummer);  
        //columns++;                       
      }
      columns++;
      if (columns == 1) {
        fscanf(f, " %s", &personer[elever].förnamn);
        //  return (personer[elever].förnamn); 
      }
      columns++;
      if (columns == 2) {
        fscanf(f, " %s", &personer[elever].efternamn);
        //return (personer[elever].efternamn);                      
      }
      columns++;
      if (columns == 3) {
        fscanf(f, " %s", &personer[elever].gender);
        // return( personer[elever].gender);
      }
      columns++;
      if (columns == 4) {
        fscanf(f, " %s ", &personer[elever].programmdife);
        // return( personer[elever].programmdife);
      }
      columns++;
      if (columns == 5) {
        fscanf(f, " %s", &personer[elever].age);
        // return(personer[elever].age);
      }
      columns++;
      if (columns == 6) {
        fscanf(f, " %s", &personer[elever].email);
        // return(personer[elever].email);                   
      }
      return &personer[elever];
    }
    //free(personer);
  }
  // return 0;
  //fclose("elever.txt");     
}

int i;
int main() {
  display[i] = base(*display[i]);

为什么你混淆了 reader 分配给 display[i] 与未初始化的 i 变量(作为全局变量,它是零)而不是说 display[0] = base(*display[0]);

更重要的是,为什么你要为 base() 的结果赋一个函数指针单元格,它应该是一个结构。对一个函数指针你唯一能做的就是给它赋值并执行它指向的函数。但是您正在分配一个指向结构的指针(该信息隐藏在您将其定义为 returning void * 的事实之下,我不知道您从哪里学到的,但不值得在这里使用)如果你的功能是为数组动态分配内存,数组应该被定义为struct student * display[5];或更好的struct student **display;(因为动态内存分配的性质,您可以处理数组中可变数量的结构。


  FILE *h;
  h = fopen("Filedatabase.txt", "w");
  if (h == NULL) {
    printf("Could not write the file!\n");
    exit(1);
  } else {
    for (int i = 0; i < 7;) {

如果您已经为包含五个条目的数组编写了所有内容,为什么还要在这里增加七个?在代码中使用常量很重要,因此您永远不会因为这个错误而失败。

      fprintf(h, "%s\n", display[i]);

      printf("\n");
      i++;
    }

    printf("open the file");
  }
  fclose(h);
  free(display);

  return 0;
}

如果你想学习 return 一个完整的结构,这里有一个示例代码可以完成我猜你想做的事情,return 构建一个结构并将其复制回在作业中的适当位置(但在这种情况下没有使用 malloc,因此,程序中没有动态内容,您将始终为 5 个学生设置 space --- 或常量---和一个适当的 struct student 数组已经为你分配了)这是一个比你的更简单的例子,基于你的代码来说明 C 函数中的结构 return (我认为它会更容易理解并更好地在您的代码中使用):

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

/* the two macros below allow pretty printing of error,
 * including the file and the line where the error
 * was detected. */
#define F(_fmt) "%s:%d:"_fmt,__FILE__,__LINE__
#define ERR(_cod, _fmt, ...) do{ \
            fprintf(stderr, F(_fmt),##__VA_ARGS__); \
            if(_cod) \
                exit(_cod); \
        }while(0)

struct student {
  char personnummer[32];
  char förnamn[32];
  char efternamn[32];
  char gender[32];
  char programmdife[32];
  char age[32];
  char email[32];
  struct likaprogramms *likaprogramm; /* I don;t use this field in my code */
};

/* use a constant, so if you want to change it later,
 *  you need only to change it here. */
#define N_STUDENTS      (5)
#define MAX_LINE        1000

/* static allocation done by the compiler */
struct student display[N_STUDENTS]; 

/* the function now reads a single student from the already
 * open FILE descriptor f, and returns a struct student,
 * filled with the read data, ready for assignment in the
 * proper place. */
struct student base(FILE *f)
{
    //char fileA[MAX];
    int tal;
    int columns;

    /* use a local structure that will be copied back to
     * the proper place in the return statement */
    struct student return_value = {0};

    char line[MAX_LINE];
    char *p = fgets(line, sizeof line, f);
    if (!p) { /* EOF */
        return return_value; /* return it as it is to
                              * indicate nothing was
                              * returned */
    }
    /* process the fields */
    p = strtok(p, " \t\n");
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.personnummer, p,
            sizeof return_value.personnummer);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.förnamn, p,
            sizeof return_value.förnamn);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.efternamn, p,
            sizeof return_value.efternamn);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.gender, p,
            sizeof return_value.gender);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.programmdife, p,
            sizeof return_value.programmdife);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.age, p,
            sizeof return_value.age);
    p = strtok(NULL, " \t\n"); /* next field */
    if (!p) { /* no more fields */
        return return_value; /* same as above */
    }
    strncpy(return_value.email, p,
            sizeof return_value.email);
    /* the full reading process for each field could have
     * been condensed in a macro call for each field, as it
     * is done in the macro definition below to print entries.
     * I preferred to shorten one and not the other to show
     * the better readability of the macro code. */
    return return_value;
}

void print_entry(struct student *entry, FILE *out)
{
/* print the result for field _fn of entry variable */
#define PR(_fn) fprintf(out, #_fn ": %s\n", entry->_fn)
    PR(personnummer);
    PR(förnamn);
    PR(efternamn);
    PR(gender);
    PR(programmdife);
    PR(age);
    PR(email);
#undef PR /* not needed anymore */
}

int main()
{
    int i;
    char *students_filename = "elever.txt";
    FILE *in = fopen(students_filename, "r");
    if (!in) {
        ERR(1, "Cannot open %s: %s (errno = %d)\n",
            students_filename, strerror(errno), errno);
        /* NOTREACHED */
    }
    for (i = 0; i < N_STUDENTS; i++) {
        display[i] = base(in); /* assign to display[i] the read
                               * data from next student in in
                               * FILE descriptor */
    }
    fclose(in); /* close file */

    char *database_filename = "Filedatabase.txt";
    FILE *out = fopen(database_filename, "w");
    if (!out) {
        ERR(1, "Cannot create %s: %s (errno = %d)\n",
            database_filename, strerror(errno), errno);
        /* NOTREACHED */
    }

    for (i = 0; i < N_STUDENTS; i++) {
        print_entry(&display[i], out); /* we pass it by
                                        * reference to
                                        * minimice copying
                                        */
    }
    fclose(out); /* again, flush buffer and close file */
    return 0;
}