'One dimensional array but multiple string

I want to make a multiple string of array but with just a one dimensional array, Is it possible?

#include <stdio.h>

int main()
{
    char name1[10];
    char name2[10];
    
    printf("Enter name1: ");
    scanf("%s", name1);
    
    printf("Enter name2: ");
    scanf("%s", name2);
    
    printf("\n%s", name1);
    printf("\n%s", name2);

    return 0;
}

I just started to learn array and I wanted to try to get multiple input from user and display only specific of the elements. This is one of the code I tried before but it does not run.

int main()
{
    char *name[10];

    int i = 1, input;
    printf("How many days a week: "); 
    scanf("%d", &input);
    
    do{
        printf("enter day %d: ", i);
        scanf("%s", name[i]);
        i++;
    }while(i < input);
    
    //output wanted
    printf("\n%s", name[0]);
    printf("\n%s", name[4]);
    
    return 0;
}


Solution 1:[1]

A rather peculiar demand, but it could be achieved like this:

#include <stdio.h>

int main()
{
    char names[256];
    
    printf("Enter name1: ");
    scanf("%s", names);
    
    printf("Enter name2: ");
    scanf("%s", names + strlen(names) + 1);
    
    printf("\n%s", names);
    printf("\n%s", names + strlen(names) + 1);

    return 0;
}

This way, the strings are concatenated in the array and separated by the terminating 0.

Solution 2:[2]

Your question is very unclear, but it sounds to me that you do not want a one-dimensional array, but rather a two-dimensional array (despite your question explicitly stating the opposite).

I suggest that you change char *name[10]; to char name[10][10]; Also, you may want to change the variable name of the 2D-array name to names, because that name is misleading, as it implies that it contains only a single string.

Also, you must start the loop counter i at 0, not 1, as array indexes are zero-based in C.

After making these changes, your program should look like this:

#include <stdio.h>

int main( void )
{
    char names[10][10];

    int i = 0, input;
    printf("How many days a week: "); 
    scanf("%d", &input);
    
    do{
        printf("Enter day %d: ", i+1);
        scanf("%s", names[i]);
        i++;
    }while(i < input);
    
    //output wanted
    printf("The first day is: %s\n", names[0]);
    printf("The fifth day is: %s\n", names[4]);
    
    return 0;
}

This program has the following behavior:

How many days a week: 7
Enter day 1: Monday
Enter day 2: Tuesday
Enter day 3: Wednesday
Enter day 4: Thursday
Enter day 5: Friday
Enter day 6: Saturday
Enter day 7: Sunday
The first day is: Monday
The fifth day is: Friday

Note that the program will write to the array out of bounds if the user enters an integer larger than 10 or if any of the days has a length larger than 9 (10 including the terminating null character).

Also, your program would have a cleaner structure if you used a for loop instead of a while loop, as it reduces the scope of the loop counter.

Another issue is that the program will misbehave if the user does not enter a number. Instead, it should check if the function scanf succeeded, and to print an error message if it did not.

Therefore, it would be better to write it like this:

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

#define MAX_DAYS 10

//MAX_DAY_LENGTH_FORMAT_STRING, which is used by scanf,
//should always be set to one less than MAX_DAY_LENGTH,
//because the latter also needs room for the terminating
//null character
#define MAX_DAY_LENGTH 10
#define MAX_DAY_LENGTH_FORMAT_STRING "%9s"

int main( void )
{
    char names[MAX_DAYS][MAX_DAY_LENGTH];
    int num_days;

    //prompt user for input
    printf( "How many days a week: " );

    //attempt to read input
    if ( scanf( "%d", &num_days ) != 1 )
    {
        printf( "Input error!\n" );
        exit( EXIT_FAILURE );
    }

    //verify that input is in desired range
    if ( ! ( 1 <= num_days && num_days <= 10 ) )
    {
        printf( "Input out of range!\n" );
        exit( EXIT_FAILURE );
    }
    
    for ( int i = 0; i < num_days; i++ )
    {
        int num_read;

        //prompt user for input
        printf( "Enter day %d: ", i+1 );

        //attempt to read input
        if ( scanf( MAX_DAY_LENGTH_FORMAT_STRING "%n", names[i], &num_read ) != 1 )
        {
            printf( "input error!" );
            exit( EXIT_FAILURE );
        }

        //check whether input was small enough to fit in buffer
        if ( num_read == MAX_DAY_LENGTH && getchar() != '\n' )
        {
            printf( "Input too long to fit in buffer!\n" );
            exit( EXIT_FAILURE );
        }
    }
    
    //print input back to user
    printf("The first day is: %s\n", names[0]);
    printf("The fifth day is: %s\n", names[4]);
    
    return EXIT_SUCCESS;
}

The program will now perform proper input validation instead of causing undefined behavior on bad input:

How many days a week: abc
Input error!
How many days a week: 11
Input out of range!
How many days a week: 7
Enter day 1: Monday
Enter day 2: Tuesday
Enter day 3: Wednesdaay
Input too long to fit in buffer!

Solution 3:[3]

The reason your code does not work is the array of pointers char *name[10]; is uninitialized so you pass an invalid address name[i] to scanf().

You can initialize the array explicitly this way:

#include <stdio.h>

int main() {
    char name0[20], name1[20], name2[20], name3[20], name4[20];
    char name5[20], name6[20], name7[20], name8[20], name9[20];
    char *name[10] = { name0, name1, name2, name3, name4,
                       name5, name6, name7, name8, name9 };
    int i, input;
    printf("How many days a week: "); 
    if (scanf("%d", &input) != 1 || input < 1 || input > 10) {
        fprintf(stderr, "invalid input\n");
        return 1;
    }
    
    for (i = 0; i < input; i++) {
        printf("enter day %d: ", i + 1);
        if (scanf("%19s", name[i]) != 1) {
            fprintf(stderr, "invalid input\n");
            return 1;
        }
    }
    
    //output wanted
    printf("%s\n", name[0]);
    if (input > 4)
        printf("%s\n", name[4]);
    
    return 0;
}

Alternately, you can use a 2D array:

#include <stdio.h>

int main() {
    char name[10][20];
    int i, input;
    printf("How many days a week: "); 
    if (scanf("%d", &input) != 1 || input < 1 || input > 10) {
        fprintf(stderr, "invalid input\n");
        return 1;
    }
    
    for (i = 0; i < input; i++) {
        printf("enter day %d: ", i + 1);
        if (scanf("%19s", name[i]) != 1) {
            fprintf(stderr, "invalid input\n");
            return 1;
        }
    }
    
    //output wanted
    printf("%s\n", name[0]);
    if (input > 4)
        printf("%s\n", name[4]);
    
    return 0;
}

Solution 4:[4]

See this beginner string handling FAQ: Common string handling pitfalls in C programming. Yours is FAQ #3 - you try to store data using a pointer which isn't pointing at a valid memory location.

char *name[10]; is correct as far as it can be used for the name[i] syntax to access a string. However, it is just an array of pointers which don't point to allocated data yet. You need to set these pointers to point somewhere before using them.

One way to do so:

char name1[100];
char name2[100];
char* name[10] = {name1, name2};
...
scanf("%s", name[i]); // now this is fine

Alternatively using dynamic allocation:

#include <stdlib.h>
...

char* name[10];
for(int i=0; i<10; i++)
{
  name[i] = malloc(100);
  if(name[i]==NULL) { /* handle error */ return 0; }
}
...
scanf("%s", name[i]); // now this is fine
...
for(int i=0; i<10; i++) // cleanup
{
  free(name[i]);
}

The advantage of dynamic allocation is that we can realloc a string later in runtime to change the string length.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Refugnic Eternium
Solution 2
Solution 3 chqrlie
Solution 4