简体   繁体   English

在 C 中,如何将文件中的字符串传递到字符串数组中。 请注意,主要目标是根据学生的身份对学生进行排序

[英]In C, how can I pass the strings from a file into a string array. Notice that main objective is to order the students with respect to their id

The program given below is equalize all name and surname with last ones.下面给出的程序是将所有姓名和姓氏与最后一个相等。 The contents of the students.dat; students.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 %s\n",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 %s\n",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,"%d\t%s\t\t\t%s\n",ordered_id[i],ordered_name[i],ordered_surname[i]);
            fprintf(stdout,"%d %s %s\n",ordered_id[i],ordered_name[i],ordered_surname[i]);
            i++;
        }
        fclose(stdFptr);
        fclose(orderFptr);
    }
    return 0;
}

You have multiple errors in your program.您的程序中有多个错误。

Errors:错误:

ordered_name[a] = student_name;

You only have pointers in your array.你的数组中只有指针。 And you only have one single array for the name.而且您只有一个数组作为名称。 That means you just assign the address of the same array to each of your entries in ordered_name .这意味着您只需将同一数组的地址分配给ordered_name中的每个条目。 Same for the other fields.其他领域也一样。

while(!feof(stdFptr)){

Just don't do this.只是不要这样做。 See Why is “while (?feof (file) )” always wrong?请参阅为什么“while (?feof (file) )”总是错误的? why this is wrong.为什么这是错误的。

temp_id[i] = ordered_id[i];

You use array temp_id to swap your array entries.您使用数组temp_id来交换数组条目。 First of all, that is very inefficient as you only need a single variable, not an array.首先,这是非常低效的,因为你只需要一个变量,而不是一个数组。
Second, this is wrong because you only have 20 elements in temp_id and ordered_id but 32 elements in the other ordered* arrays.其次,这是错误的,因为您在temp_idordered_id中只有 20 个元素,而在另一个ordered* arrays 中有 32 个元素。
Also you do not care about the number of entries in your file and might overflow both arrays.此外,您不关心文件中的条目数,并且可能会同时溢出 arrays。

Bad practice:不好的做法:

    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];

You are using corresponding arrays to store each field of your data sets.您正在使用相应的 arrays 来存储数据集的每个字段。 That is terrible to maintain.维护起来太糟糕了。 Use a struct instead:改用结构:

#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);

You do not check the result of fscanf which you should always do.你不检查你应该经常做的fscanf的结果。 Even better, use fgets followed by sscanf to parse your content.更好的是,使用fgets后接sscanf来解析您的内容。

    stdFptr = fopen("students.dat","r");

You open the file again after you already read all the content.阅读完所有内容后,您再次打开文件。 That's not needed.那是不需要的。

Your sorting is also inefficient:您的排序也很低效:

        for(i=0;i<a;i++){
            for(j=i+1;j<=a;j++){
                if(ordered_id[i]>ordered_id[j]){

This can be used to fully sort an unsorted array.这可用于对未排序的数组进行完全排序。 You do this for each new line.您为每条新行执行此操作。 Therefore you can rely on the array being sorted.因此,您可以依赖正在排序的数组。 You onle need to find the place where to put the new entry.你只需要找到放置新条目的地方。 For this, a single loop would be sufficient.为此,一个循环就足够了。

Or you can move that sorting after you have finished reading the file.或者您可以在阅读完文件后移动该排序。

You exit your program in case of an error but you don't report an error to the calling environment出现错误时退出程序,但不向调用环境报告错误

exit(0);

That is same as exit(EXIT_SUCCESS);这与exit(EXIT_SUCCESS); . . If terminate due to an error, you should also indicate that condition.如果由于错误而终止,您还应该指出该情况。


An improved version could look like this:改进后的版本可能如下所示:

#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 %s\n", 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,"%d\t%s\t\t\t%s\n", students[i].id, students[i].name, students[i].surname);
        fprintf(stdout,"%d %s %s\n", students[i].id, students[i].name, students[i].surname);
    }
    fclose(outfile);
}

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

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