Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to input strings into an array in C?

I tried to get the inputs(strings) from user and store them in an array.But after I ran this code, the program instantly crashed.

#include <stdio.h>
int main() {
    int i;
    char *word[3];
    for(i=0;i<3;i++)
    {
        printf(" Enter a word: ");
        scanf("%s", &word[i]);
    }
    printf("%s ", word[0]);
    return 0;
}
like image 852
Top Serious Avatar asked Dec 23 '22 21:12

Top Serious


1 Answers

In this line:

scanf("%s", &word[i]);

You need to make sure word[i] is pointing somewhere, and has enough space to occupy the string entered. Since word[i] is a char * pointer, you need to at some time allocate memory for this. Otherwise, it is just a dangling pointer not pointing anywhere.

If you want to stick with scanf(), then you can allocate some space beforehand with malloc.

malloc() allocates requested memory on the heap, then returns a void* pointer at the end.

You can apply malloc() in your code like this:

size_t malloc_size = 100;

for (i = 0; i < 3; i++) {
    word[i] = malloc(malloc_size * sizeof(char)); /* allocates 100 bytes */
    printf("Enter word: ");
    scanf("%99s", word[i]); /* Use %99s to avoid overflow */
                            /* No need to include & address, since word[i] is already a char* pointer */
} 

Note: Must check return value of malloc(), because it can return NULL when unsuccessful.

Additionally, whenever you allocate memory with the use of malloc(), you must use free to deallocate requested memory at the end:

free(word[i]);
word[i] = NULL; /* safe to make sure pointer is no longer pointing anywhere */

Another approach without scanf

A more proper way to read strings should be with fgets.

char *fgets(char *str, int n, FILE *stream) reads a line from an input stream, and copies the bytes over to char *str, which must be given a size of n bytes as a threshold of space it can occupy.

Things to note about fgets:

  • Appends \n character at the end of buffer. Can be removed easily.
  • On error, returns NULL. If no characters are read, still returns NULL at the end.
  • Buffer must be statically declared with a given size n.
  • Reads specified stream. Either from stdin or FILE *.

Here is an example of how it can be used to read a line of input from stdin:

char buffer[100]; /* statically declared buffer */

printf("Enter a string: ");
fgets(buffer, 100, stdin); /* read line of input into buffer. Needs error checking */

Example code with comments:

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

#define NUMSTR 3
#define BUFFSIZE 100

int main(void) {
    char *words[NUMSTR];
    char buffer[BUFFSIZE];
    size_t i, count = 0, slen; /* can replace size_t with int if you prefer */

    /* loops only for three input strings */
    for (i = 0; i < NUMSTR; i++) {

        /* read input of one string, with error checking */
        printf("Enter a word: ");
        if (fgets(buffer, BUFFSIZE, stdin) == NULL) {
            fprintf(stderr, "Error reading string into buffer.\n");
            exit(EXIT_FAILURE);
        }

        /* removing newline from buffer, along with checking for overflow from buffer */
        slen = strlen(buffer);
        if (slen > 0) {
            if (buffer[slen-1] == '\n') {
                buffer[slen-1] = '\0';
            } else {
                printf("Exceeded buffer length of %d.\n", BUFFSIZE);
                exit(EXIT_FAILURE);
            }
        } 

        /* checking if nothing was entered */
        if (!*buffer) {
            printf("No string entered.\n");
            exit(EXIT_FAILURE);
        }

        /* allocate space for `words[i]` and null terminator */
        words[count] = malloc(strlen(buffer)+1);

        /* checking return of malloc, very good to do this */
        if (!words[count]) {
            printf("Cannot allocate memory for string.\n");
            exit(EXIT_FAILURE);
        }

        /* if everything is fine, copy over into your array of pointers */
        strcpy(words[count], buffer);

        /* increment count, ready for next space in array */
        count++;
    }  

    /* reading input is finished, now time to print and free the strings */
    printf("\nYour strings:\n");
    for (i = 0; i < count; i++) {
        printf("words[%zu] = %s\n", i, words[i]);
        free(words[i]);
        words[i] = NULL;
    }

    return 0;
}

Example input:

Enter a word: Hello
Enter a word: World
Enter a word: Woohoo

Output:

Your strings:
words[0] = Hello
words[1] = World
words[2] = Woohoo
like image 102
RoadRunner Avatar answered Jan 04 '23 17:01

RoadRunner