1

I have problem to sort an array of string by length loaded from txt file.

So I read from the file line by line and put the strings into an array, after that I sort that array by the length of the string, but I get a strange output of the array stream.

The problem is that the program is sorting an array of strings, but one of the strings is pasted on top of another.

Example:

The data in the file I'm reading from:

X&Y
X|Y
!X
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
(X&Y)|Z&(A|B
((X|Y)|Z)&((A|B)|(C&D))
(X&Y)|(Z&(A|B))
(A|B)&(!C)
A|(B&(C&(D|E)))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))
(A|B)|(C&D)&(D|E)
!A&(B|C)
(A|B)|(C|D)&(D

Content of the array after sorting in ascending order:

!X
X|Y
X&Y
(X|Y)|Z
(X&Y)|Z
(X&Y)&Z
!A&(B|C)
(A|B)&(!C)
(X&Y)|Z&(A|B
(A|B)|(C|D)&(DA|(B&(C&(D|E))) //Here' is problem ! (A|B)|(C|D)&(D and A|(B&(C&(D|E))) are concatenated?
(X&Y)|(Z&(A|B))
(A|B)|(C&D)&(D|E)
((X|Y)|Z)&((A|B)|(C&D))
((X|Y)|(Z&(A|B)))|((C&D)&(D|E))




Here is the code:

//Sort function
void sort(char str[][MAXLEN], int number_of_elements) {
    int d, j;
    char temp[100];
    for (d = 0; d < number_of_elements - 1; d++) {
        for (j = 0; j < number_of_elements - d - 1; j++) {
            if (strlen(str[j]) < strlen(str[j + 1])) {
                strcpy(temp, str[j]);
                strcpy(str[j], str[j + 1]);
                strcpy(str[j + 1], temp);
            }
        }
    }
}

int main() {
    FILE *dat;
    int number_of_elements;
    char str[MAX][MAXLEN];
    int i = 0;
    dat = fopen("ulaz.txt", "r");
    if (dat == NULL) {
        printf("Error");
    }
    while (!feof(dat) && !ferror(dat)) {
        if (fgets(str[i], 100, dat) != NULL)
            i++;
    }

    number_of_elements = i;
    fclose(dat);
    
    sort(str, number_of_elements);
    
    for (int d = 0; d < i; d++) {
        printf("%s", str[d]);
    }
    return 0;
}

Thanks in advance !

chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Works exactly as I would expect, after changing the comparison from a less-than to a greater-than. https://replit.com/@robertwharvey/LowQuarterlyMemorypool#main.c – Robert Harvey Nov 12 '22 at 13:17
  • You don't have concatenate strings like me? – Andew Tayloe Nov 12 '22 at 13:21
  • @user3121023 how to fix that? I still have the same problem... – Andew Tayloe Nov 12 '22 at 13:26
  • Check your data file. The one in the example I provided has a trailing newline after the last line. – Robert Harvey Nov 12 '22 at 13:27
  • To fix it, simply add a newline after the last line, if it is not there. – Robert Harvey Nov 12 '22 at 13:28
  • I agree with @user3121023 that it would be best to always remove the newline character after using `fgets`, if it exists. See this question for various ways to do that: [Removing trailing newline character from fgets() input](https://stackoverflow.com/q/2693776/12149471) – Andreas Wenzel Nov 12 '22 at 13:29
  • Of course, if you remove the newline character from the input, you will then have to add a newline character to the output, by changing the line `printf("%s", str[d]);` to `printf("%s\n", str[d]);`. – Andreas Wenzel Nov 12 '22 at 13:35

1 Answers1

1

Your observations is consistent with the last line of the source file having no trailing newline: (A|B)|(C|D)&(D

You can correct the problem by stripping the newline after fgets() and always appending one in the output phase.

Also make sure that the temporary array used for swapping the strings is long enough: instead of 100 bytes, it should have a length of MAXLEN. Also stop reading from the file when i reaches MAX.

Here is a modified version:

#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define MAXLEN  200
#define MAX     100

//Sort function by decreasing string lengths
void sort(char str[][MAXLEN], int number_of_elements) {
    int d, j;
    for (d = 0; d < number_of_elements - 1; d++) {
        for (j = 0; j < number_of_elements - d - 1; j++) {
            if (strlen(str[j]) < strlen(str[j + 1])) {
                char temp[MAXLEN];
                strcpy(temp, str[j]);
                strcpy(str[j], str[j + 1]);
                strcpy(str[j + 1], temp);
            }
        }
    }
}

int main() {
    int number_of_elements;
    char str[MAX][MAXLEN];
    int i;
    FILE *dat = fopen("ulaz.txt", "r");
    if (dat == NULL) {
        fprintf(stderr, "Cannot open %s: %s\n", "ulaz.txt", strerror(errno));
        return 1;
    }
    for (i = 0; i < MAX && fgets(str[i], MAXLEN, dat) != NULL; i++) {
        /* strip the trailing newline if any */
        str[i][strcspn(str[i], "\n")] = '\0';
    }

    number_of_elements = i;
    fclose(dat);
    
    sort(str, number_of_elements);
    
    for (int d = 0; d < number_of_elements; d++) {
        printf("%s\n", str[d]);
    }
    return 0;
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189