1

How can I take words from STDIN, then put them into an array I can sort later? this is the code I have for taking in STDIN.

printf("Please enter words to sort:\n");
char *line = NULL;
size_t len = 0;
ssize_t lineSize = 0;
lineSize = getline(&line, &len, stdin);
printf("You entered: %swhich has %zu chars.\n", line, lineSize - 1);
free(line);
return 0;
Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • This example sorts lines rather than words, but might be instructive: https://github.com/wrp/examples/blob/main/c/read-txt-into-array.c – William Pursell Nov 10 '22 at 14:29
  • It may seem obvious, but the first thing you need to do is define what a *word* is. The specific rules will change the viability of some approaches. – Oka Nov 10 '22 at 15:11
  • Is the user supposed to enter all words on a single line? Or one word per line? Or should the user be able to enter several lines with several words per line? In that case, how is the program supposed to know when the user is finished? Should it be when an empty line is finished? And is it possible that some words are [hyphenated](https://en.wikipedia.org/wiki/Syllabification), so that a word starts on one line but ends on another line? – Andreas Wenzel Nov 10 '22 at 15:32
  • Since you appear to be using POSIX `getline`, I assume that your question does not apply to plain ISO C. I have therefore added the `posix` tag to the question. – Andreas Wenzel Nov 10 '22 at 15:34
  • @AndreasWenzel one line, finishes when user hits enter due to getline – Dakota Kellogg Nov 10 '22 at 15:37
  • Once you've read the line into memory, you can parse it using the ideas from [Using `sscanf()` in loops](https://stackoverflow.com/q/3975236/15168). – Jonathan Leffler Nov 10 '22 at 16:15
  • @DakotaKellogg Why the unnecessary `- 1` in `lineSize - 1`? Why use a mis-matched unsigned specifier `"zu"` with the signed type `ssize_t`? – chux - Reinstate Monica Nov 10 '22 at 18:23

2 Answers2

1

In order to sort the words, I recommend that you create an array of char *, in which every element of the array points to a word.

In order to find the start of the words and to make the words properly terminated by a null character, I recommend that you use the function strtok or strtok_r.

Here is an example:

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

#define MAX_WORDS 100

//custom compare function for the function "qsort" which does
//nothing else than call the function "strcmp" for comparison
//purposes
int my_compare( const void *a, const void *b )
{
    return strcmp( *(const char**)a, *(const char**)b );
}

int main( void )
{
    char *words[MAX_WORDS];
    int num_words = 0;
    char *line = NULL, *p;
    size_t len = 0;
    ssize_t lineSize = 0;

    //prompt user for input
    printf( "Please enter words to sort:\n" );

    //read one line of input
    lineSize = getline( &line, &len, stdin );
    if ( lineSize <= 0 )
    {
        fprintf( stderr, "Input error!\n" );
        exit( EXIT_FAILURE );
    }

    //remove newline character, if it exists
    line[strcspn(line,"\n")] = '\0';

    //find first word
    p = strtok( line, " " );

    //loop until no more words are found, processing one word
    //per loop iteration
    while ( p != NULL )
    {
        //verify that we are not overflowing the array
        if ( num_words == MAX_WORDS )
        {
            fprintf( stderr, "Too many words for array!\n" );
            exit( EXIT_FAILURE );
        }

        //add pointer to found word to the "words" array
        words[num_words++] = p;

        //find next word for next loop iteration
        p = strtok( NULL, " " );
    }

    //now we can sort the array
    qsort( words, num_words, sizeof *words, my_compare );

    //print the sorted words
    for ( int i = 0; i < num_words; i++ )
    {
        printf( "%s\n", words[i] );
    }

    //cleanup
    free( line );
}

For the input

apple orange banana dog cat

this program has the following output:

apple
banana
cat
dog
orange

As you can see, the words were properly sorted.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
0

How to take words from stdin, and put them into array to sort later?

Properly read a line into a string, parse the string for words and save the words in a master linked list. No need for a WORDS_MAX restriction.

After all lines read, allocate for the required string pointer array based on linked-list length.

Move the string pointers from the link-list to the array. Delete the linked-list.


Small issue. Properly use/print ssize_t. ssize_t has no specified matching print specifier. - 1 not needed.

// ssize_t lineSize = 0;
// lineSize = getline(&line, &len, stdin);
// printf("You entered: %swhich has %zu chars.\n", line, lineSize - 1);

ssize_t number_of_characters_read = getline(&line, &len, stdin);
if (number_of_characters_read < 0) {
  Handle_error();
} else {
  printf("You entered: \"%s\" which has length %lld.\n", 
      line, (long long) number_of_characters_read);
}
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256