0

I am struggling with writing a C program that sorts numbers read from a number of files, in ascending order.

Requirements:

  1. create 3 files (file1, file2, file3)
  2. get numbers from the user and in file1
  3. find the smallest number (in file1) and copy it to file3
  4. copy the numbers from file1 to file2 except the smallest number that we copied to file3.
  5. copy the numbers in file2 to file1 (removing the all old numbers).
  6. using while function to repeat the steps above until we sort all numbers in ascending order in file3.
  7. copy numbers from file3 to file1 and print all the numbers on the screen (from file1).

Note: The program must be using only files to sort numbers and shouldn't use any array.

I am working on this for hours but now and sometimes it works and sometimes it does not. I don't really know what's wrong.

Any ideas or suggestions on solving this problem?

#include <conio.h>
#include <stdio.h>
// to save the position of the smallest number
int pos;

// to get numbers from the user and save them in file1
void getNumbers(FILE *file) {
  char x[255];
  printf("Enter numbers: ");
  scanf("%[^\n]s", &x);
  fprintf(file, "%s", x);
}

// to find the smallest number and copy it to file3
void findSmallestNo(FILE *file1, FILE *file3) {
  int x, temp;
  rewind(file1);
  fscanf(file1, "%d", &temp);
  pos = ftell(file1);
  while (!(feof(file1))) {
    fscanf(file1, "%d", &x);
    if (x < temp) {
      temp = x;
      pos = ftell(file1);
    }
  }
  fprintf(file3, "%d ", temp);
}

// to copy numbers from file1 to file2 except the smallest number that we copied
// in the file3

void copyToFile2(FILE *file1, FILE *file2) {
  int cur_pos, x;
  rewind(file1);
  rewind(file2);
  while (!(feof(file1))) {
    fscanf(file1, "%d", &x);
    cur_pos = ftell(file1);
    if (cur_pos != pos) {
      fprintf(file2, "%d ", x);
    }
  }
}

// to copy from file2 to file1 (it should delete the old data in file1)
void copyToFile1(FILE *file1, FILE *file2) {
  int x, count = 0;
  rewind(file2);

  while (!feof(file2)) {
    count++;
    fscanf(file2, "%d", &x);
    fprintf(file1, "%d ", x);
  }
}

// to print numbers on the screen
void print_file(FILE *file1) {
  int x;
  rewind(file1);
  printf("\nSorted Numbers: ");

  while ((fscanf(file1, "%d", &x)) == 1) {
    printf("%d ", x);
  }
  printf("\n");
}

int main() {
  int len, count = 1;
  FILE *pFile1, *pFile2, *pFile3;
  pFile1 = fopen("file1.txt", "w+");
  pFile2 = fopen("file2.txt", "w+");
  pFile3 = fopen("file3.txt", "a+");
  if (pFile1 == NULL) {
    printf("Couldn't open the file\n");
    exit(1);
  }
  // to get the count of numbers in file1
  getNumbers(pFile1);
  int getLength(FILE * file) {
    int nn, counting = 1;
    rewind(file);
    while ((fscanf(file, "%d ", &nn) == 1)) {
      counting++;
    }
    return counting;
  }
  len = getLength(pFile1);

  // while loop until var count is equal to the count of numbers in file1
  while (count < len) {
    ++count;
    findSmallestNo(pFile1, pFile3);
    copyToFile2(pFile1, pFile2);
    fclose(pFile1);
    pFile1 = fopen("file1.txt", "w+");
    copyToFile1(pFile1, pFile2);
  }

  fclose(pFile1);
  fclose(pFile3);
  pFile1 = fopen("file1.txt", "w+");
  pFile3 = fopen("file3.txt", "r");

  int number;
  // to copy numbers from file3 to file1
  while (count != 1) {
    fscanf(pFile3, "%d ", &number);
    fprintf(pFile1, "%d ", number);
    --count;
  }
  // to print numbers on the screen in file1
  print_file(pFile1);
  fclose(pFile1);
  fclose(pFile2);
  fclose(pFile3);

  return 0;
}
Armen Michaeli
  • 8,625
  • 8
  • 58
  • 95
  • 1
    Side note: Your usage of `while(!(feof(file1))){` looks [wrong](https://stackoverflow.com/questions/5431941/why-is-while-feof-file-always-wrong). – MikeCAT Apr 26 '21 at 12:36
  • 2
    Can you tell us why you would only use files? Copying between files is rather inefficient! – Bananenkönig Apr 26 '21 at 12:37
  • @Bananenkönig it's an assignment in the universiy and our professor wants us to use ony files. – Anonymous Programmer Apr 26 '21 at 12:41
  • Do you know about linked list ? If you do, are you allowed to use them ? – Dzious Apr 26 '21 at 12:42
  • 1
    What you would usually do with files is https://en.wikipedia.org/wiki/Merge_sort –  Apr 26 '21 at 12:42
  • @MikeCAT How can I correct it? – Anonymous Programmer Apr 26 '21 at 12:43
  • "Does not work" is a frequently used description, but unfortunately say nothing. Please tell us, what works, and what in detail not. Optimally provide a reproducible input that leads to an unwanted result. – the busybee Apr 26 '21 at 13:17
  • "I want to..." The description that follows does not sound like something anyone would want. If you need help with homework, that's okay, but ask specific questions. – Emanuel P Apr 26 '21 at 14:44
  • @EmanuelP This way of sorting, I just make it up, it works but sometimes does not, g.e. input: 45 77 88 1 0 5 6 output: 0 1 5 6 45 77 88 but sometimes it gives me repeated numbers like this: input: 77 55 66 44 11 33 output: 11 33 33 33 33 33 I am working on this for hours but I don't know what a mastake I made! so I thought that maybe someone can help if I post it here!. Thanks for your commet. – Anonymous Programmer Apr 26 '21 at 21:15

1 Answers1

0
//#include <conio.h>
#include <stdio.h>
// to save the position of the smallest number

// to get numbers from the user and save them in file1
void getNumbers(char *filename) {
    char x[255];
    FILE *file;
    file = fopen(filename, "w");
    if (file == NULL) {
        printf("Couldn't open the file\n");
        return;
    }
    printf("Enter numbers: ");
    scanf("%[^\n]s", &x);
    fprintf(file, "%s", x);
    fclose(file);
}

// to find the smallest number and copy it to file3
int findSmallestNo(char *filename1, char *filename3) {
    int x, temp = 100000;
    FILE *file1, *file3;
    file1 = fopen(filename1, "r");
    file3 = fopen(filename3, "a");
    fscanf(file1, "%d", &temp);
    while (fscanf(file1, "%d", &x) == 1) {
        if (x < temp) {
            temp = x;
        }
    }
    fprintf(file3, "%d ", temp);
    fclose(file1);
    fclose(file3);
    return temp;
}

// to copy numbers from file1 to file2 except the smallest number that we copied
// in the file3

void copyToFile2(char *filename1, char *filename2, int min_value) {
    int flag = 0, x;
    FILE *file1, *file2;
    file1 = fopen(filename1, "r");
    file2 = fopen(filename2, "w");
    while (fscanf(file1, "%d", &x) == 1) {
        if (x != min_value || flag == 1) {
            fprintf(file2, "%d ", x);
        } else {
            flag = 1;
        }
    }
    fclose(file1);
    fclose(file2);
}

// to copy from file2 to file1 (it should delete the old data in file1)
void copyToFile(char *filename1, char *filename2) {
    int x;
    FILE *file1, *file2;
    file1 = fopen(filename1, "w");
    file2 = fopen(filename2, "r");
    rewind(file2);

    while (fscanf(file2, "%d", &x) == 1) {
        fprintf(file1, "%d ", x);
    }
    fclose(file1);
    fclose(file2);
}

// to print numbers on the screen
void print_file(char *filename) {
    int x;
    FILE *file;
    file = fopen(filename, "r");
    printf("\nSorted Numbers: ");

    while ((fscanf(file, "%d", &x)) == 1) {
        printf("%d ", x);
    }
    printf("\n");
    fclose(file);
}

int getLength(char *filename) {
    int nn, counting = 1;
    FILE *file;
    file = fopen(filename, "r");
    rewind(file);
    while ((fscanf(file, "%d ", &nn) == 1)) {
        counting++;
    }
    fclose(file);
    return counting;
}

void clearFile (char *filename) {
    FILE *file;
    file = fopen(filename, "w");
    fclose(file);
}

int main() {
    int len, count = 1;
    char *filename1 = "file1.txt";
    char *filename2 = "file2.txt";
    char *filename3 = "file3.txt";

    clearFile(filename3);

    // to get the count of numbers in file1
    getNumbers(filename1);

    len = getLength(filename1);

    // while loop until var count is equal to the count of numbers in file1
    while (count < len) {
        ++count;
        int cur_min = findSmallestNo(filename1, filename3);
        copyToFile2(filename1, filename2, cur_min);
        copyToFile(filename1, filename2);
    }

    int number;
    // to copy numbers from file3 to file1
    copyToFile(filename1, filename3);
    clearFile(filename3);
    // to print numbers on the screen in file1
    print_file(filename1);
    return 0;
}

i fixed your code, it seems working fine.

your algorithm works, but i think like @Bananenkönig said "Copying between files is rather inefficient!". The problem with your code is just about working with files.

Your way to read till end of file with fscanf will read 1 more time to find the eof, that's why you'll get some unwanted number in your results.

  • 1
    Downvoted because no explanation given. Remember, that although unlikely given specificity of the question, someone else may stumble upon this question as related to their own problem in a way neither you nor we may anticipate, and when they look at your answer they will have to basically understand themselves what is it you fixed, exactly. Stack Overflow is not just a forum, the value is in the answers being more than just "posts". If you took the time to explain what was wrong with the code, that'd go a good mile towards providing value. – Armen Michaeli Apr 27 '21 at 11:01
  • @thọ-Đỗ-xuân Your code is so clear and understandable and I understood where I made a mistake. There is one thing I didn't understand. Why did you add variable "int flag" in the function "copyToFile2" ? can you explain this please? And another thing I want to ask about: why did you add the function "clearFile(filename3)" two times, one at the beginning and the other at the end. I think it's redundant. So i removed the first one (at the beginning) and the code still works fine. Thanks so much. – Anonymous Programmer Apr 28 '21 at 17:49
  • that for the case you have multiple number with the same value, so you just want to leave one of them on file 1 each time, so i set the flag to check if the fist of them is reached or not. "clearFile(filename3)" is just to clear the file3 so i can run and debug without having to delete the files program created, and like you said, now i think do it 2 time looks redundant too :) – Thọ Đỗ Xuân Apr 28 '21 at 17:54
  • @ThọĐỗXuân Thanks again. Now I understood. – Anonymous Programmer Apr 28 '21 at 23:14