简体   繁体   English

一维数组但多个字符串

[英]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;
}

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.这样,字符串在数组中连接起来并由终止 0 分隔。

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];我建议你改变char *name[10]; to char name[10][10]; 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.此外,您可能希望将二维数组name的变量名称更改为names ,因为该名称具有误导性,因为它暗示它只包含一个字符串。

Also, you must start the loop counter i at 0 , not 1 , as array indexes are zero-based in C.此外,您必须从0开始循环计数器i ,而不是1 ,因为数组索引在 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).请注意,如果用户输入大于10的 integer 或任何一天的长度大于910包括终止字符 null),程序将越界写入数组。

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.此外,如果您使用for循环而不是while循环,您的程序将具有更清晰的结构,因为它减少了循环计数器的scope

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.相反,它应该检查 function scanf是否成功,如果没有成功则打印一条错误消息。

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!

The reason your code does not work is the array of pointers char *name[10];您的代码不起作用的原因是指针数组char *name[10]; is uninitialized so you pass an invalid address name[i] to scanf() .未初始化,因此您将无效地址name[i]传递给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;
}

See this beginner string handling FAQ: Common string handling pitfalls in C programming .请参阅初学者字符串处理常见问题解答: C 编程中常见的字符串处理陷阱 Yours is FAQ #3 - you try to store data using a pointer which isn't pointing at a valid memory location.你的是常见问题 #3 - 你尝试使用未指向有效 memory 位置的指针存储数据。

char *name[10]; is correct as far as it can be used for the name[i] syntax to access a string.就其可用于name[i]语法访问字符串而言是正确的。 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.动态分配的好处是我们可以realloc在运行时重新分配一个字符串来改变字符串的长度。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM