0

I have a question about sorting records in a file. This is my code

case 7: {
            struct record ar[1000];
            int x=-1;
            if((ftemp = fopen(file_name, "r")) != NULL) {
                if((f = fopen(temp, "w")) != NULL) {
                    while(fgets(line, 100, ftemp) != NULL) {
                        x++;
                        ar[x] = parse_line(line); //parse the line and store in an array
                    }
                }
            }

            printf("What do you want sort?\n\n1 - region\n2 - area\n3 - population\nYour choose: ");
            while(scanf("%d%c", &choose_sort, &symbol) != 2 || symbol != '\n' || choose_sort > 3 || choose_sort < 1) { 
            printf("\nInvalid input. Please, try again\n\n1 - region\n2 - area\n3 - population\nYour choose: ");
            fflush(stdin); }

            printf("Choose order\n\n1 - ascending\n2 - descending\nYour choose: ");
            while(scanf("%d%c", &variant_sort, &symbol) != 2 || symbol != '\n' || variant_sort < 1 || variant_sort > 2) { 
            printf("\nInvalid input. Please, try again\n\n1 - ascending\ndescending\nYour choose: ");
            fflush(stdin); }

            switch(choose_sort) {
                case 1: {
                    for(int i = 0; i < x - 1; i++) {
                        for(int j = i + 1; j < x; j++) {
                            if(strcmp(ar[i].region, ar[j].region) > 0) {
                                record e = ar[i];
                                ar[i] = ar[j];
                                ar[j] = e;
                            }
                        }
                    }
                    break;  
                }
                case 2: {
                    for(int i = 0; i < x - 1; i++) {
                        for(int j = i + 1; j < x; j++) {
                            if(ar[i].area > ar[j].area) {
                                record e = ar[i];
                                ar[i] = ar[j];
                                ar[j] = e;
                            }
                        }
                    }
                    break;
                }

                case 3: {
                    for(int i = 0; i < x - 1; i++) {
                        for(int j = i + 1; j < x; j++) {
                            if(ar[i].population > ar[j].population) {
                                record e = ar[i];
                                ar[i] = ar[j];
                                ar[j] = e;
                            }
                        }
                    }
                    break;
                }
            }

            if (variant_sort == 1) {
                for (int i = 0; i < x; i++) {
                    fprintf(f,"Region: %s     Area: %lf     Population:%d\n", ar[i].region, ar[i].area, ar[i].population);
                }
                } else {
                    for (int i = x - 1; i >= 0; i--) {
                        fprintf(f, "Region: %s     Area: %lf     Population: %d\n", ar[i].region, ar[i].area, ar[i].population);
                    }
                }

            fclose(ftemp);
            fclose(f);
            remove(file_name);
            rename(temp, file_name);
            break;
        }

As well as the function itself

struct record parse_line(char* line) {
  struct record record;
  memset(record.region, 0, sizeof(record.region));  // Clear the region field
  int spaces=0;

  // Read the region field
  int i = 0;
  while (line[i] != ' ') {
    record.region[i] = line[i];
    i++;
    spaces++;
  }
  i++;  // Skip the space character

  // Read the area field
  char* area_str = malloc(50);  // Allocate memory to hold the area string
  memset(area_str, 0, 50);  // Clear the memory
  int space = 0;
  int j = 0;
  while (line[i] != ' ') {
    area_str[j] = line[i];
    i++;
    space++;
  }
  j++;

  record.area = atof(area_str);  // Convert the area string to a double and store it in the record
  free(area_str);  // Free the memory allocated for the area string

  // Read the population field
  char* population_str = malloc(50);  // Allocate memory to hold the population string
  memset(population_str, 0, 50);  // Clear the memory
  j = 0;
  while (line[i] != '\n' && line[i] != '\0') {
    population_str[j] = line[i];
    i++;
  }
  j++;
  record.population = atoi(population_str);  // Convert the population string to an int and store it in the record
  free(population_str);  // Free the memory allocated for the population string

  return record;
}

Can anyone tell me why this is not working properly? I declare x as the upper bound for the outer loop and x - 1 as the upper bound for the inner loop. And it should all work, but nothing happens. I have already dug through everything and so I do not understand. Do you have any ideas?

If I choose sorting by population in ascending form, and then I go to the file, then nothing happens there

  • Your `while (scanf(...` loops for input validation are not going to work. If `scanf()` can't parse the input, it leaves it in the buffer, and the next iteration will fail the same way. You should use `fgets()` to read a line, then parse it with `sscanf()`. – Barmar Jan 11 '23 at 23:39
  • What exactly are you expecting to happen? If you're expecting the sorted result to be written to a file, you need to write it to a file. You don't do this anywhere in the code shown. – Layne Bernardo Jan 11 '23 at 23:40
  • @Layne Bernardo won't fprintf write the sorted lines I need to a file? – hrytsenkoo Jan 11 '23 at 23:45
  • Can you use `qsort()`? – Barmar Jan 11 '23 at 23:46
  • Can you use `strtok()`? – Fe2O3 Jan 11 '23 at 23:47
  • @Barmar i tested it right now and it works. Doesn't let me enter any number other than what I need. The buffer is cleaned up and I don't see any problems here – hrytsenkoo Jan 11 '23 at 23:47
  • 1
    Have you stepped through in a debugger, looked at `ar` as it's being modified, make sure you're reaching `fprintf`? Are you sure you're not going out of bounds on `ar`? How is `line` declared, does it have adequate space? This is quite a distance from a [mre], which makes it more difficult to help. – yano Jan 11 '23 at 23:47
  • @hrytsenkoo Yes, my bad. Skimmed a bit too quickly. – Layne Bernardo Jan 11 '23 at 23:47
  • @Barmar I haven't tried qsort because I just wanted to figure out what I'm doing wrong in this case. Think qsort can save me? – hrytsenkoo Jan 11 '23 at 23:48
  • `fflush(stdin)` is non-standard. I guess it works on your system. See https://stackoverflow.com/questions/2979209/using-fflushstdin – Barmar Jan 11 '23 at 23:49
  • @hrytsenkoo I have no idea what your problem is, so I don't know what will save you. – Barmar Jan 11 '23 at 23:50
  • Could you reduce this to a [mre]? If you're having trouble sorting the data or writing to a file, the code that prompts for options doesn't seem to be relevant and obscures things. – Barmar Jan 11 '23 at 23:51
  • @Barmar about fflush(stdin) I agree, it's really not recommended, but I use it – hrytsenkoo Jan 11 '23 at 23:51
  • yes guys, I can minimize everything, maybe I'm wrong, I just wanted everything to be more detailed on the contrary, so that all the code was and everything is clear – hrytsenkoo Jan 11 '23 at 23:52
  • Make a backup copy of the file. Then, open the file ONCE to both read and write. Read it all into memory, sort it (somehow... Needs work)... Then `fseek()` to the beginning and write the data back into the same file... No need for a temporary file that has to be renamed (if that works)... – Fe2O3 Jan 11 '23 at 23:55
  • In contrast to the convention whereby `x` would be the number of records loaded, your version of `x` is the index of the last used element of the array. So, `i < x-1` and `j < x` won't take you where you want to go... – Fe2O3 Jan 12 '23 at 00:01

0 Answers0