-1

The program given below is equalize all name and surname with last ones. The contents of the 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;
}
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
  • Welcome to SO. You have a misconception how arrays work. You only have one single array `student_name` which you use again and again to read a new line. Here `ordered_name[a] = student_name;` you assign the addres (not the content!) to the pointer in your array. This makes all pointers point to that same array. – Gerhardh Apr 10 '22 at 11:30
  • You should take a look at [Why is “while ( !feof (file) )” always wrong?](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). You should also read about structs. Having an array for each field is bad practice. It makes maintainance and overall handling very hard. Use a struct instead and create an array of that struct. Also each struct should contain an array for each field instead of a pointer. Otherwise you have to allocate memory separately. – Gerhardh Apr 10 '22 at 11:32
  • Why do you open `students.dat` again after reading and sorting? – Gerhardh Apr 10 '22 at 11:45
  • Please clarify your specific problem or provide additional details to highlight exactly what you need. As it's currently written, it's hard to tell exactly what you're asking. – Community Apr 10 '22 at 15:00
  • Note: You are supposed to respond to comments... – Gerhardh Apr 10 '22 at 19:14

1 Answers1

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. Same for the other fields.

while(!feof(stdFptr)){

Just don't do this. See Why is “while ( !feof (file) )” always wrong? why this is wrong.

temp_id[i] = ordered_id[i];

You use array temp_id to swap your array entries. 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.
Also you do not care about the number of entries in your file and might overflow both 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. 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. Even better, use fgets followed by sscanf to parse your content.

    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);. 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);
}
Gerhardh
  • 11,688
  • 4
  • 17
  • 39
  • Thanks for answering. I am totally new in programming . So I am aware that I had plenty of mistakes. The reason why I dont care of number of entries, This is just a trying so I know that I never owerflow to 20. – Yunus Kurtyemez Apr 11 '22 at 19:54