【问题标题】:Im having a problem with reading a file, then assigning it to a struct array and printing it back out我在读取文件时遇到问题,然后将其分配给结构数组并将其打印回来
【发布时间】:2020-03-29 09:22:53
【问题描述】:

我目前必须获取一个 input.txt 文件,它的位置类似于

3

莎拉 90 40 30

约翰 23 55 33

帮助 34 99 74

作为输入文件,

并将其读入结构数组,然后创建一个 output.txt。

我的作业似乎有问题。我尝试了 fscanf、fgetc、fgets、strtok、delim 以及我在互联网上可以找到的所有内容,但由于我对指针知识的粗鲁,我似乎被卡住了。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
    char *name;
    int literature;
    int math;
    int science;
}studentT;

int main(void)
{
    printf("Start of main\n");

    FILE *fptr;
    int i;
    fptr = fopen("input.txt", "r");

//reading first line to dynamically allocate studentT
    printf("dynamically allocating studentT\n");

    char tempsize[4];
    //fgets(tempsize,1,fptr);
    //i=atoi(&tempsize[0]);
    fscanf(fptr,"%d",&i);
    struct studentT* record = malloc(i*sizeof(*record));

    printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.

    char line[24];
    char buffer[24];
    char delim[] = " ";

    char *array[4];
    int *darray[4];
    printf("entering while loop\n");

    fgets(buffer,24,fptr);

    int idx =0;

    while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
    {

        puts(line);
        char *buf = strtok(line, delim);
        int iter =0;
        while(buf!=NULL)
        {
            if(iter = 0){
                array[iter]=buf;
                buf = strtok(NULL,delim);
            }
            for(iter=1;iter<4;iter++){
            *darray[iter] =atoi(buf);//
            printf("%d,",*darray[iter]);
            buf=strtok(NULL, delim);
            }
        }


            record[idx].name=array[0];
            record[idx].literature=*darray[1];
            record[idx].math=*darray[2];
            record[idx].science=*darray[3];

        //    printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
        //    printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
        //sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
        printf("%s\n", line);

        //fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
        line[strlen(line)-1]='\0';    
        printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
        idx++;
    }

//output of file

    printf("output commencing\n\n\n");
    int tempave;
    FILE *fout;
    char *str1 = "Name Literature Math Science Ave.\n";

    char *str2 = "Ave. ";
    char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
    char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
    char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
    char *str6 = "79.67 76.67 84.00 80.11";

    fout = fopen("output.txt", "w");
    fprintf(fout,"%s\n", str1);


    for(int idx=0;idx<i;idx++){
        tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
        fwrite(&record[idx],sizeof(struct studentT),1,fout);
        fprintf(fout, "%d\n",tempave);
    }

    //fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6); 


    fprintf(fout,"%s",str2);

    float mathave,litave,sciave;

    for(int idx=0;idx<3;idx++){
        mathave+=record[idx].math;
        litave+=record[idx].literature;
        sciave+=record[idx].science;
    }

    mathave=mathave/3;
    sciave=sciave/3;
    litave=litave/3;

    fprintf(fout,"%f %f %f",litave, mathave, sciave);

    fclose(fptr);
    fclose(fout);
}

编辑:同事提到我应该 malloc 数组,所以代码现在看起来更丑:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
typedef struct studentT{
    char *name;
    int literature;
    int math;
    int science;
}studentT;

int main(void)
{
    printf("Start of main\n");

    FILE *fptr;
    int i;
    fptr = fopen("input.txt", "r");

//reading first line to dynamically allocate studentT
    printf("dynamically allocating studentT\n");

    char tempsize[4];
    //fgets(tempsize,1,fptr);
    //i=atoi(&tempsize[0]);
    fscanf(fptr,"%d",&i);
    struct studentT* record = malloc(i*sizeof(*record));

    printf("i has interger value %d\n", i);
//line counter ignoring line 0; reading 1 and 2.

    char line[24];
    char buffer[24];
    char delim[] = " ";

    char *array[4];
    int darray[4];
    printf("entering while loop\n");

    fgets(buffer,24,fptr);

    int idx =0;

    while(fgets(line, sizeof(line),fptr)!=NULL &&idx<i)
    {

        puts(line);
        char *buf = strtok(line, delim);
        int iter =0;
        while(buf!=NULL)
        {
            if(iter = 0){
                array[iter] = malloc(sizeof(char)*strlen(buf));
                strcpy(array[iter],buf);
                buf = strtok(NULL,delim);
            }
            for(iter=1;iter<4;iter++){
            darray[iter] = (int*)malloc(sizeof(char)*strlen(buf));
            memcpy(&darray[iter],buf,(sizeof(char)*strlen(buf)));//
            buf=strtok(NULL, delim);
            }
        }


            record[idx].name=malloc(sizeof(char)*strlen(array[0]));
            strcpy(record[idx].name,array[0]);
            record[idx].literature=darray[1];
            record[idx].math=darray[2];
            record[idx].science=darray[3];

        //    printf("array value: %s %d %d %d\n",array[0], array[1], array[2], array[3]);
        //    printf("value after casting: %s %zu %zu %zu\n", array[0], (uintptr_t)array[1], (uintptr_t)array[2], (uintptr_t)array[3]);
        //sscanf(buf,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
        printf("%s\n", line);

        //fscanf(fptr,"%s %d %d %d",record[idx].name, &record[idx].literature, &record[idx].math, &record[idx].science);
        line[strlen(line)-1]='\0';    
        printf("in idx loop %d %s %d %d %d\n\n", idx, record[idx].name, record[idx].literature, record[idx].math, record[idx].science);
        idx++;
    }

//output of file

    printf("output commencing\n\n\n");
    int tempave;
    FILE *fout;
    char *str1 = "Name Literature Math Science Ave.\n";

    char *str2 = "Ave. ";
    char *str3 = "Sarah\t 96\t 90\t 80\t 88.67";
    char *str4 = "Minsu\t 55\t 70\t 76\t 67.00";
    char *str5 = "Nara\t 88\t 70\t 96\t 84.67";
    char *str6 = "79.67 76.67 84.00 80.11";

    fout = fopen("output.txt", "w");
    fprintf(fout,"%s\n", str1);


    for(int idx=0;idx<i;idx++){
        tempave = (record[idx].math+record[idx].literature+record[idx].science)/3;
        fwrite(&record[idx],sizeof(struct studentT),1,fout);
        fprintf(fout, "%d\n",tempave);
    }

    //fprintf(fout, "%s\n %s\n %s\n %s %s\n",str3,str4,str5,str2,str6); 


    fprintf(fout,"%s",str2);

    float mathave,litave,sciave;

    for(int idx=0;idx<3;idx++){
        mathave+=record[idx].math;
        litave+=record[idx].literature;
        sciave+=record[idx].science;
    }

    mathave=mathave/3;
    sciave=sciave/3;
    litave=litave/3;

    fprintf(fout,"%f %f %f",litave, mathave, sciave);

    fclose(fptr);
    fclose(fout);
}

【问题讨论】:

  • darray 是一个指针数组,但是指针实际指向哪里? 而且它真的需要是一个指针数组吗? ?
  • 从 darray 中删除 * 似乎会创建过多关于指向 int wint 转换的指针的错误链......
  • 您是否还记得删除数组元素的取消引用,例如darray[iter] =atoi(buf)?
  • 我有,但是当我调试时,我在 darray[iter] =atoi(buf); 行中遇到了分段错误。我问了我的同事,他提到我应该对每个数组和 strcpy 进行 malloc,而不是对字符串使用 = 运算符.. 仍然出现 seg 错误。
  • @Some 程序员老兄,我对所有内容都进行了防御,尝试对所有内容进行 malloc,darray[iter] = malloc(sizeof(char)*strlen(buf)); 但随后这一行给出了 assignment makes integer from pointer without a cast

标签: c


【解决方案1】:

我已经用 cmets 编写了您需要的新版本。希望您可以了解正在发生的事情并修复您的代码,或者您也可以使用它。您可能需要更改输入文件和输出文件的名称才能使用您的输入文件。

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

struct student {
    char *name;
    int literature;
    int math;
    int science;
};
typedef struct student Student;

int main(void) {

  FILE* inputFile;
  FILE* outputFile;
  int first_read; //check to see if the number of students value was read
  int readNumStudents; //count of how many students are there
  int i; //tracking students struct array
  Student* students; //array of student structs

  readNumStudents = 0;
  first_read = 0;
  i = 0;

  inputFile = fopen("input.txt", "r"); //might have to change to whatever your file name is
  outputFile = fopen("output.txt", "w"); //might have to change to whatever you want the output file name to be

  //checking for null  file pointers 
  if(inputFile == NULL){
    printf("Failed to open input file.\n");
    exit(1);
  }

  if(outputFile == NULL){
    printf("Failed to open output file.\n");
    exit(1);
  }

  //read file until end of file is reached
  while(!feof(inputFile)){

    if (first_read == 0){// check to see if first line was read. if not read, then write the value to readNumStudents variable
      fscanf(inputFile, "%d", &readNumStudents);

      first_read = 1; //set the value to 1. this means that the number of students was read.

      students = (Student*) malloc(sizeof(Student) * readNumStudents);//allocate Student structs for the number of given students fro input file. (ie. 3 structs)

      if(students == NULL){//check for null
          printf("Failed to allocate memory for students.\n");
          break;
      }

      //If not null, then for every struct allocate memory for the name string because its char* not char name[50]
      for(int j = 0; j < readNumStudents; j++){
        students[j].name = (char*) malloc(sizeof(char) * 50);

        if(students[j].name == NULL){//check for null
          printf("Failed to allocate memory for name.\n");
          exit(1);
        }
      }
    } else {//this means that the first line was read. now read the names and scors
        //since you know the format of the input file (string int int int) you can use fscanf with "%s %d %d %d" and the adress of the struct values
        fscanf(inputFile, "%s %d %d %d",  students[i].name, &(students[i].literature), &(students[i].math), &(students[i].science));

        i++;//used to point to next student structure
      }
    }

    //Go thorugh every struct and write each value to outputfile
    for(int j = 0; j < i; j++){
      fprintf(outputFile, "%s %d %d %d\n", students[j].name, (students[j].literature), (students[j].math), (students[j].science));
    }

    //free all the allocated memory and files
    fclose(inputFile);
    fclose(outputFile);
    //you need to free the char array on top of the studnets struct array. so loop through every student to free it
    for(int j = 0; j < i; j++){
      free(students[j].name);
    }
    free(students);

  return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    相关资源
    最近更新 更多