我正在编写一个接受文件输入并将其保存到数组的程序。问题是我不完全确定我是否应该做一个二维数组。特别是我听说过的 while 循环 !feof
可能不是正确的方法。我还需要找出 city_mpg 和 highway_mpg 的平均值,然后将其作为另一列添加到数组中。添加列后,我需要对其进行升序排序。如果它是一维数组然后将其添加到另一列,我将如何找到平均值?如果它是 2D,我不能只指定 [1][4]
和 [1][5]
并执行类似的操作,然后将其保存为 [1][6]
等等还是我应该坚持使用 Malloc?
输入文件:
Mercury Sable 2009 18 28
Jeep Wrangler 2016 17 21
Honda civic 2015 31 41
Toyota Corolla 2015 30 42
Toyta Prius 2010 51 48
Ford Escape 2013 23 33
Ford Fusion 2013 25 37
Acura MDX 2014 20 28
Lexus RX 2013 32 28
程序不完整:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CARS 1000 //no more than 1000 cars
#define MAX_STR 30 //str wont be longer than 30
struct car { // declare my structure
char *make; // pointers for char and declares my vars
char *model;
int manufacture_year;
int city_mpg;
int highway_mpg;
int average_mpg;
};
//sorts array based on average mpg here
int main(void) { //main function
int cars = 0;
int c;
struct car *data;
char make[MAX_STR+1]; //char will be 30 + 1 for null char
char model[MAX_STR+1];
int year, city, highway; //declares ints
FILE *file; //declares input file
FILE *file2; //declares output file
file = fopen("cars.txt", "r"); //opens car.txt as read
if(file == NULL) { //if file is null
printf("File error\n"); //throws error
return 1;
}
data = malloc(MAX_CARS * sizeof(struct car)); //allocates memory for array by max cars for pointers
if(data == NULL) {
printf("Memory error\n"); //error if memory is a issue just incase mainly used for testing
return 1;
}
while(fscanf(file, "%30s %30s %d %d %d", make, model, &year, &city, &highway) == 5) { //reads the data with a while loop
if(cars >= MAX_CARS) { //just a check if file is more than 1k
printf("Too many cars\n"); //outputs result if too many cars
break;
}
data[cars].make = strdup(make); // makes a copy of the strings
data[cars].model = strdup(model);
data[cars].manufacture_year = year; // copies the data so that it is headed properly
data[cars].city_mpg = city; // copies the data so that it is headed properly
data[cars].highway_mpg = highway; // copies the data so that it is headed properly
data[cars].average_mpg = (city + highway) / 2; //gets the average mpg
cars++; // loop counter
}
fclose(file); //closes file
file2 = fopen("sorted_cars.txt", "a+"); //opens new file or creates one if there isnt one
fprintf(file2,"Make Model Year City mpg Highway mpg Average mpg\n"); //prints to new txt file
for(c=0; c<cars; c++) {
sprintf(model, "%s %s", data[c].make, data[c].model); //sprintf sends formatted output to a string
fprintf(file2,"%-20s %4d %4d %4d %4d\n", model, data[c].manufacture_year,data[c].city_mpg, data[c].highway_mpg, data[c].average_mpg); //prints to oufile
}
// free the memory, It tries to allocate enough memory to hold the old string (plus a null character to mark the end of the string)
while(--cars >= 0) {
free(data[cars].model);
free(data[cars].make);
}
free(data); //frees the array memory
return 0;
}
预期结果:
Make Model year city mpg highway mpg average mpg
Jeep Wrangler 2016 17 21 19
Mercury Sable 2009 18 28 23
and so on...
最佳答案
我对您的代码进行了一些调整,并提供了一些评论。它使用一维数组。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_CARS 1000
#define MAX_STR 99
struct car { // array of cars appears later
char *make; // pointer to string memory that will be allocated
char *model; // ditto
int manufacture_year;
int city_mpg;
int highway_mpg;
int average_mpg;
};
int cmp(const void *a, const void *b) {
// compare function for qsort
// this is the user-supplied compare function always required by qsort
// qsort does not know or care about the data type, only its dimensions
// so I cast the void pointers to our local data type
struct car *aa = (struct car*)a;
struct car *bb = (struct car*)b;
if(aa->average_mpg > bb->average_mpg) return 1;
if(aa->average_mpg < bb->average_mpg) return -1;
return 0;
}
int main(void) {
int cars = 0;
int c;
struct car *data;
char make[MAX_STR+1];
char model[MAX_STR+1];
int year, city, highway;
FILE *file;
// set up
file = fopen("cars.txt", "r");
if(file == NULL) {
printf("File error\n"); // finish messages with a newline
return 1;
}
// allocate dynamic memory for the array, for maximum cars specified
// the argument is the total memory requirement
// could have been a global array of struct but it's bad practice
data = malloc(MAX_CARS * sizeof(struct car));
if(data == NULL) {
printf("Memory error\n");
return 1;
}
// read the data, controlling the loop with fscanf return value
// feof is commonly, but incorrectly used, and since it is essential to check the
// return value from fscanf, this kills two birds with one stone
while(fscanf(file, "%49s %49s %d %d %d", make, model, &year, &city, &highway) == 5) {
if(cars >= MAX_CARS) {
printf("Too many cars\n");
break;
}
data[cars].make = strdup(make); // make a copy of the strings
data[cars].model = strdup(model);
data[cars].manufacture_year = year; // copy the data
data[cars].city_mpg = city;
data[cars].highway_mpg = highway;
data[cars].average_mpg = (city + highway) / 2;
cars++; // track the number of records
}
fclose(file);
// sort the records, qsort needs to know the width of each element,
// and how many many, and you tell it your own comparison callback function
qsort(data, cars, sizeof *data, cmp);
// print the data
printf("Make Model Year City mpg Highway mpg Average mpg\n");
for(c=0; c<cars; c++) {
sprintf(model, "%s %s", data[c].make, data[c].model); // to make alignment easy
printf("%-20s %4d %4d %4d %4d\n", model, data[c].manufacture_year,
data[c].city_mpg, data[c].highway_mpg, data[c].average_mpg);
}
// free the memory, note that strdup allocated memory secretly
while(--cars >= 0) {
free(data[cars].model); // it was acquired by strdup
free(data[cars].make); // so was this
}
free(data); // now free the array memory we got ourselves
return 0;
}
程序输出:
Make Model Year City mpg Highway mpg Average mpg
Jeep Wrangler 2016 17 21 19
Mercury Sable 2009 18 28 23
Acura MDX 2014 20 28 24
Ford Escape 2013 23 33 28
Lexus RX 2013 32 28 30
Ford Fusion 2013 25 37 31
Honda civic 2015 31 41 36
Toyota Corolla 2015 30 42 36
Toyta Prius 2010 51 48 49
关于C读取输入文件并对一种类型进行升序排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38294685/