简体   繁体   English

如何打印出由 C 中的 char ** 创建的字符串(数组)数组?

[英]How do I print out an array of string(array) create by char ** in C?

I'm new to C and trying to create an array using char **, but I'm having a problem printing it out.我是 C 的新手,并试图使用 char ** 创建一个数组,但我在打印它时遇到了问题。 Is there a way to print it out or shouldn't I use this way to create an array of string?有没有办法打印出来,或者我不应该用这种方式来创建一个字符串数组?

int main()
{
    char **a = {"abc", "ddd", "ccc", "aaa"};

    for (size_t i = 0; i < 4; i++){
        printf("%s\n", a+i);  // only print out "abc" correctly
//        printf("%s\n", *(a+i));  doesn't work
//        printf("%s\n", a[i]);  doesn't work
    }

    return 0;

}

在此处输入图片说明

This declaration本声明

char **a = {"abc", "ddd", "ccc", "aaa"};

is incorrect.是不正确的。 A scalar type may be initialized using only a single expression in braces.标量类型可以仅使用大括号中的单个表达式进行初始化。

If you want to declare an array of pointers then you should write如果你想声明一个指针数组,那么你应该写

char * a[] = {"abc", "ddd", "ccc", "aaa"};

To output it you can write要输出它,你可以写

for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
    puts( a[i] );
}

Or或者

char * a[] = {"abc", "ddd", "ccc", "aaa"};
const size_t N = sizeof( a ) / sizeof( *a );

for (size_t i = 0; i < N; i++){
    puts( a[i] );
}

Another approach is to declare a two-dimensional array like for example另一种方法是声明一个二维数组,例如

char a[][4] = {"abc", "ddd", "ccc", "aaa"};

It can be outputted the same way as shown above.可以像上图一样输出。

for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
    puts( a[i] );
}

If you want to have a declaration of an object of the type char ** like如果你想声明一个char **类型的对象,比如

char **a = /*...*/;

then you could initialize it with a compound literal.然后你可以用复合文字初始化它。

Here is a demonstrative program.这是一个演示程序。

#include <stdio.h>

int main(void) 
{
    enum {  N = 4 };
    char **a = ( char * [N] ){"abc", "ddd", "ccc", "aaa"};
    
    for ( size_t i = 0; i < N; i++ )
    {
        puts( a[i] );
    }
    
    return 0;
}

Its output is它的输出是

abc
ddd
ccc
aaa

running the posted code through the compiler results in:通过编译器运行发布的代码会导致:

gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o" (in directory: /home/richard/Documents/forum)
untitled1.c: In function ‘main’:
untitled1.c:8:17: warning: initialization of ‘char **’ from incompatible pointer type ‘char *’ [-Wincompatible-pointer-types]
    8 |     char **a = {"abc", "ddd", "ccc", "aaa"};
      |                 ^~~~~
untitled1.c:8:17: note: (near initialization for ‘a’)
untitled1.c:8:24: warning: excess elements in scalar initializer
    8 |     char **a = {"abc", "ddd", "ccc", "aaa"};
      |                        ^~~~~
untitled1.c:8:24: note: (near initialization for ‘a’)
untitled1.c:8:31: warning: excess elements in scalar initializer
    8 |     char **a = {"abc", "ddd", "ccc", "aaa"};
      |                               ^~~~~
untitled1.c:8:31: note: (near initialization for ‘a’)
untitled1.c:8:38: warning: excess elements in scalar initializer
    8 |     char **a = {"abc", "ddd", "ccc", "aaa"};
      |                                      ^~~~~
untitled1.c:8:38: note: (near initialization for ‘a’)
untitled1.c:11:18: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
   11 |         printf("%s\n", a+i);  // only print out "abc" correctly
      |                 ~^     ~~~
      |                  |      |
      |                  char * char **
Compilation finished successfully.

when compiling, do NOT ignore the warnings.编译时,不要忽略警告。

That final line from the compiler:编译器的最后一行:

 Compilation finished successfully

only means the compiler used some 'workaround' for each of the problems, NOT that the correct code was produced.仅意味着编译器对每个问题都使用了一些“解决方法”,而不是生成了正确的代码。

If we make a change so only a single pointer is used rather than a pointer to pointer:如果我们进行更改,因此仅使用单个指针而不是指向指针的指针:

#include <stdio.h>




int main( void )
{
    char *a = {"abc", "ddd", "ccc", "aaa"};

    for (size_t i = 0; i < 4; i++){
        printf("%s\n", a+i);  // only print out "abc" correctly
//        printf("%s\n", *(a+i));  doesn't work
//        printf("%s\n", a[i]);  doesn't work
    }

    return 0;

}

results in:结果是:

gcc -ggdb3 -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled1.c" -o "untitled1.o" (in directory: /home/richard/Documents/forum)
untitled1.c: In function ‘main’:
untitled1.c:8:23: warning: excess elements in scalar initializer
    8 |     char *a = {"abc", "ddd", "ccc", "aaa"};
      |                       ^~~~~
untitled1.c:8:23: note: (near initialization for ‘a’)
untitled1.c:8:30: warning: excess elements in scalar initializer
    8 |     char *a = {"abc", "ddd", "ccc", "aaa"};
      |                              ^~~~~
untitled1.c:8:30: note: (near initialization for ‘a’)
untitled1.c:8:37: warning: excess elements in scalar initializer
    8 |     char *a = {"abc", "ddd", "ccc", "aaa"};
      |                                     ^~~~~
untitled1.c:8:37: note: (near initialization for ‘a’)
Compilation finished successfully.

which is better, but still not right.哪个更好,但仍然不对。

modifying the declaration of a[] so it is appropriately declared and initialized results in:修改a[]的声明,以便对其进行适当的声明和初始化,结果如下:

char *a[]

which reads as an array of pointers to char它读取为指向 char 的指针数组

the next problem is:下一个问题是:

printf("%s\n", a+i);  

which results in:这导致:

untitled1.c:17:22: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]

that is corrected by:通过以下方式更正:

printf("%s\n", *(a+i) );

so a passable, but not great version of the code looks like:所以一个可以通过但不是很好的代码版本看起来像:

#include <stdio.h>




int main( void )
{
    char *a[] =
    {
        "abc", 
        "ddd",
        "ccc", 
        "aaa"
    };

    for (size_t i = 0; i < 4; i++){
        printf("%s\n", *(a+i) );  // only print out "abc" correctly
//        printf("%s\n", *(a+i));  doesn't work
//        printf("%s\n", a[i]);  doesn't work
    }

    return 0;

}

However, that has the 'magic' number 4 .然而,这有“魔法”数字4

We can eliminate that 'magic' number by letting the compiler perform the calculations for the for() loop:我们可以通过让编译器为for()循环执行计算来消除这个“神奇”数字:

for( size_t i = 0; i < (sizeof(a) / sizeof( *a ); i++ )

So the final code is: (with excess blank lines removed)所以最终的代码是:(去掉多余的空行)

#include <stdio.h>

int main( void )
{
    char *a[] =
    {
        "abc", 
        "ddd",
        "ccc", 
        "aaa"
    };

    for (size_t i = 0; i < (sizeof( a ) / sizeof( *a )); i++)
    {
        printf("%s\n", *(a+i) );  
    }

    return 0;
}

The result of running the above code is:运行上面代码的结果是:

abc
ddd
ccc
aaa

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

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