下面给出的程序将所有名称和姓氏与最后一个名称和姓氏相等。学生.dat的内容;
2020102054 Name1 Surname1
2021202051 Name2 Surname2
2020302057 Name3 Surname3
2020802053 Name4 Surname4
2020602059 Name5 Surname5
2019452065 Name6 Surname6
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *stdFptr, *orderFptr;
int student_id ,temp_id[20],ordered_id[20], a=0,i,j;
char student_name[32], student_surname[32];
char *ordered_name[32],*ordered_surname[32],*temp_string[32];
stdFptr = fopen("students.dat","r");
orderFptr = fopen("order.dat","w");
if(!stdFptr || !orderFptr){
puts("File Error, Exiting The Program");
exit(0);
}
else{
puts("Before ordering");
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
while(!feof(stdFptr)){
ordered_name[a] = student_name;
ordered_surname[a] = student_surname;
ordered_id[a] = student_id;
a++;
fprintf(stdout,"%d %s %sn",student_id,student_name,student_surname);
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
}
ordered_name[a] = student_name;
ordered_surname[a] = student_surname;
ordered_id[a] = student_id;
fprintf(stdout,"%d %s %sn",student_id,student_name,student_surname);
for(i=0;i<a;i++){
for(j=i+1;j<=a;j++){
if(ordered_id[i]>ordered_id[j]){
temp_string[i] = ordered_name[i];
ordered_name[i] = ordered_name[j];
ordered_name[j] = temp_string[i];
temp_string[i] = ordered_surname[i];
ordered_surname[i] = ordered_surname[j];
ordered_surname[j] = temp_string[i];
temp_id[i] = ordered_id[i];
ordered_id[i] = ordered_id[j];
ordered_id[j] = temp_id[i];
}
}
}
rewind(stdFptr);
fclose(stdFptr);
}
stdFptr = fopen("students.dat","r");
if(!stdFptr || !orderFptr){
puts("File Error, Exiting The Program");
exit(0);
}
else{
puts("After ordering");
i=0;
while(i<=a){
fprintf(orderFptr,"%dt%sttt%sn",ordered_id[i],ordered_name[i],ordered_surname[i]);
fprintf(stdout,"%d %s %sn",ordered_id[i],ordered_name[i],ordered_surname[i]);
i++;
}
fclose(stdFptr);
fclose(orderFptr);
}
return 0;
}
您的程序中有多个错误。
错误:
ordered_name[a] = student_name;
数组中只有指针。并且名称只有一个数组。这意味着您只需将相同数组的地址分配给ordered_name
中的每个条目。其他字段也是如此。
while(!feof(stdFptr)){
只是不要这样做。请参阅为什么"while(!feof(file(("总是错误的?为什么这是错误的。
temp_id[i] = ordered_id[i];
您可以使用数组temp_id
来交换数组条目。首先,这是非常低效的,因为您只需要一个变量,而不需要一个数组
其次,这是错误的,因为temp_id
和ordered_id
中只有20个元素,而其他ordered*
阵列中有32个元素
此外,您不关心文件中的项数,可能会溢出两个数组。
不良做法:
int student_id ,temp_id[20],ordered_id[20], a=0,i,j;
char student_name[32], student_surname[32];
char *ordered_name[32],*ordered_surname[32],*temp_string[32];
您正在使用相应的数组来存储数据集的每个字段。这太可怕了。请改用结构:
#define NAME_LENGTH 32
#define MAX_NUMBER 50
struct student {
int id;
char name[NAME_LENGTH];
char surname[NAME_LENGTH];
};
fscanf(stdFptr, "%d %s %s ",&student_id,student_name,student_surname);
您没有检查fscanf
的结果,而您应该始终这样做。更好的是,使用fgets
和sscanf
来解析您的内容。
stdFptr = fopen("students.dat","r");
在阅读完所有内容后,您可以再次打开该文件。这是不需要的。
您的分拣效率也很低:
for(i=0;i<a;i++){
for(j=i+1;j<=a;j++){
if(ordered_id[i]>ordered_id[j]){
这可以用于对未排序的数组进行完全排序。你对每一行都这样做。因此,您可以依赖于正在排序的数组。你只需要找到放置新条目的地方。为此,一个循环就足够了。
或者,您可以在读取完文件后移动排序。
如果出现错误,您可以退出程序,但不会向调用环境报告错误
exit(0);
与exit(EXIT_SUCCESS);
相同。如果由于错误而终止,您还应该指出该条件。
一个改进的版本可能看起来像这样:
#include <stdio.h>
#include <stdlib.h>
#define NAME_LENGTH 32
#define MAX_NUMBER 50
struct student {
int id;
char name[NAME_LENGTH];
char surname[NAME_LENGTH];
};
int main(void)
{
struct student students[MAX_NUMBER];
int count = 0;
FILE *infile = fopen("students.dat","r");
if (infile == NULL) {
fprintf(stderr, "Input file cannot be openend.");
exit(EXIT_FAILURE);
}
// PART 1: Read the file content
puts("Before ordering");
char line[2*NAME_LENGTH + 20];
while (fgets(line, sizeof (line), infile) != NULL
&& count < MAX_NUMBER)
{
int result = sscanf(line, "%d %31s %31s", &students[count].id, students[count].name, students[count].surname);
if (result != 3)
{
fprintf(stderr, "Invalid line ignored: <%s>", line);
}
else
{
fprintf(stdout,"%d %s %sn", students[count].id, students[count].name, students[count].surname);
count++;
}
}
fclose(infile);
// PART 2: Sort the array
struct student temp;
for (int i = 0; i < count-1; i++) {
for (int j = i+1; j < count; j++) {
if (students[i].id > students[j].id) {
temp = students[i];
students[i] = students[j];
students[j] = temp;
}
}
}
// Note: You could also just use qsort() function from standard library.
// PART 3: Write to output file
FILE *outfile = fopen("order.dat","w");
if (outfile == NULL) {
fprintf(stderr, "Output file cannot be openend.");
exit(EXIT_FAILURE);
}
puts("After ordering");
for (int i=0; i < count; i++) {
fprintf(outfile,"%dt%sttt%sn", students[i].id, students[i].name, students[i].surname);
fprintf(stdout,"%d %s %sn", students[i].id, students[i].name, students[i].surname);
}
fclose(outfile);
}