-1

The program is expected to sort and display a list of words from a array whose elements are pointers to char. I use malloc to alocate space to each element and use a read_line function to store in the element the typed word. The issue rests on the garbage of random characters that has each word as though the program wasn't able to read my typed characters and store them.

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


#define MAX 100
#define LEN 20

int string_compare(const void *n, const void *m);
int read_line(char *str, int n);

int main(void)
{
    int i, num_words, largo;
    char *list[MAX], word[LEN+1];

    for (i=num_words=0; i<MAX; i++, num_words++) {
        printf("Enter word: ");
        list[i] =  malloc(LEN + 1);

        if (list[i] == NULL) {
            printf("Error, no more memory available\n");
            break;
        }

        largo = read_line(word, LEN) ;      // no sé por qué la string
        if (largo == 0)                     // que recoge la funcion
            break;       // el break ya va  // son char random (garabage)
        

        printf("Copying string %s...\n",list[i]);
        strcpy(list[i], word);
    }

    qsort(list, i, 21 * sizeof(char), string_compare);
    

    printf("In sorted order: ");
    for (i=0; i < num_words; i++) 
        printf("Displaying...\n");
        printf("%s ", list[i]);
    
    return 0;
}

int string_compare(const void *n, const void *m)
{
    return strcmp((char *) n, (char *) m);
}

int read_line(char *str, int n)
{
    int ch, i=0;

    while ((ch=getchar()) != '\n')
        if (i < n)
            str[i++] = ch;
    str[i] = '\0';
    
    return i;
}

I used strcpy, strcat and altered the order of reading and allocation code lines without successs.

4
  • Please be more specific as to the problem than "without success". Commented Jun 24, 2024 at 15:22
  • 3
    There are a few problems... One major problem is that you treat the array list as an array of arrays, which it is not. It's an array of pointers. So that means the element size is sizeof(char *) and the comparison function receives pointers to the pointers (i.e. char **). Commented Jun 24, 2024 at 15:28
  • @ScottHunter Without any success.:) Commented Jun 24, 2024 at 15:49
  • 2000 bytes is not overly onerous. I would get rid of all of the dynamic memory allocation entirely. Commented Jun 24, 2024 at 18:32

2 Answers 2

2

You are sorting an array of char *. The size of each element is therefore sizeof(char *), but you are telling qsort that it is 21 (times sizeof(char), but sizeof(char) is 1 by definition). I am 100% confident that your char * size is not 21.

This approach not only fixes the problem, but avoids you having to think too hard about it:

    qsort(list, i, sizeof(*list), string_compare);

that that defines the size of the items in terms of the list itself.

Additionally, your comparison function is wrong. Its arguments will be pointers to the elements to compare, which you need to dereference once to get the (char *) values themselves:

int string_compare(const void *n, const void *m)
{
    return strcmp(*(char * const *) n, *(char * const *) m);
}
Sign up to request clarification or add additional context in comments.

15 Comments

Enter word: hola Copying string l... Enter word: ke Copying string N... Enter word: ase Copying string U... Enter word: In sorted order: Displaying... Displaying... Displaying... V
With all your ammends done here is my output:
you see that my program doesn't end to read the string I put in list[i]
in other words: list[i] contains garbage (random characters)
@PepeCuesta for (i=0; i < num_words; i++) printf("Displaying...\n"); will print Displaying... num_words times. After that it will do printf("%s ", list[i]); once, which will access list[num_words] where you haven't stored a word and it may also be out of bounds. Both makes the program have undefined behavior. This isn't python. Indentation means nothing to the C compiler.
|
2

In the while loop of the function read_line you need also to insert at least the condition that i is less than n and to remove the if statement as for example

int read_line(char *str, int n)
{
    int ch, i=0;

    while ( i < n && (ch=getchar()) != '\n')
            str[i++] = ch;
    str[i] = '\0';
    
    return i;
}

And exhange these statements in main

    printf("Copying string %s...\n",list[i]);
    strcpy(list[i], word);

like

    strcpy(list[i], word);
    printf("Copying string %s...\n",list[i]);

list is an array of pointers

char *list[MAX],

So the size of elements of the array is equal to sizeof( char * ).

It means that you need to write

qsort(list, i, sizeof(char *), string_compare);
               ^^^^^^^^^^^^^^

instead of

qsort(list, i, 21 * sizeof(char), string_compare);
               ^^^^^^^^^^^^^^^^^

The function string_compare accepts pointers to elements of the array that is actually it accepts pointers of the type char **.

So within the function you should write

int string_compare(const void *n, const void *m)
{
    return strcmp( *(const char **) n, *(const char **) m);
}

And you should free all the allocated memory at the end of the program.

4 Comments

Again, with all the improvements implemented, the program doesn't store in list[i] the string typed by me keyboard. Here is the following output:
Enter word: hola Copying string l... Enter word: ke Copying string i... Enter word: ase Copying string a... Enter word: In sorted order: Displaying... Displaying... Displaying... U
@PepeCuesta As I told you above: printf("Copying string %s...\n",list[i]); ... What list[i] points at is uninitialized at that point so you have undefined behavior. Replace it with printf("Copying string %s...\n", word); - Or use read_line(list[i], LEN) and skip the copy
@PepeCuesta See my updated answer.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.