如何在 C 中打印出由 char ** 创建的字符串数组?
How do I print out an array of string(array) create by char ** in C?
我是 C 语言的新手,正在尝试使用 char ** 创建数组,但打印出来时遇到问题。有没有办法打印出来,或者我不应该使用这种方式来创建一个字符串数组?
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;
}
这个声明
char **a = {"abc", "ddd", "ccc", "aaa"};
不正确。标量类型可以仅使用大括号中的单个表达式进行初始化。
如果你想声明一个指针数组,那么你应该写
char * a[] = {"abc", "ddd", "ccc", "aaa"};
要输出它你可以写
for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
puts( a[i] );
}
或
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] );
}
另一种方法是声明一个 two-dimensional 数组,例如
char a[][4] = {"abc", "ddd", "ccc", "aaa"};
可以按照上面的方式输出。
for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
puts( a[i] );
}
如果你想声明char **
类型的对象,比如
char **a = /*...*/;
然后你可以用复合文字初始化它。
这是一个演示程序。
#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;
}
它的输出是
abc
ddd
ccc
aaa
运行 通过编译器发布的代码导致:
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.
编译时,不要忽略警告。
编译器的最后一行:
Compilation finished successfully
仅表示编译器对每个问题使用了一些 'workaround',而不是生成了正确的代码。
如果我们进行更改,那么只使用单个指针而不是指向指针的指针:
#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;
}
结果:
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.
哪个更好,但还是不对
修改 a[]
的声明以便正确声明和初始化结果:
char *a[]
读取为指向 char
的指针数组
下一个问题是:
printf("%s\n", a+i);
这导致:
untitled1.c:17:22: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
已更正:
printf("%s\n", *(a+i) );
所以一个可以通过但不是很好的代码版本如下所示:
#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;
}
但是,那有 'magic' 个 4
。
我们可以通过让编译器执行 for()
循环的计算来消除 'magic' 数字:
for( size_t i = 0; i < (sizeof(a) / sizeof( *a ); i++ )
所以最终的代码是:(删除了多余的空行)
#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;
}
以上代码运行的结果为:
abc
ddd
ccc
aaa
我是 C 语言的新手,正在尝试使用 char ** 创建数组,但打印出来时遇到问题。有没有办法打印出来,或者我不应该使用这种方式来创建一个字符串数组?
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;
}
这个声明
char **a = {"abc", "ddd", "ccc", "aaa"};
不正确。标量类型可以仅使用大括号中的单个表达式进行初始化。
如果你想声明一个指针数组,那么你应该写
char * a[] = {"abc", "ddd", "ccc", "aaa"};
要输出它你可以写
for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
puts( a[i] );
}
或
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] );
}
另一种方法是声明一个 two-dimensional 数组,例如
char a[][4] = {"abc", "ddd", "ccc", "aaa"};
可以按照上面的方式输出。
for (size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++){
puts( a[i] );
}
如果你想声明char **
类型的对象,比如
char **a = /*...*/;
然后你可以用复合文字初始化它。
这是一个演示程序。
#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;
}
它的输出是
abc
ddd
ccc
aaa
运行 通过编译器发布的代码导致:
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.
编译时,不要忽略警告。
编译器的最后一行:
Compilation finished successfully
仅表示编译器对每个问题使用了一些 'workaround',而不是生成了正确的代码。
如果我们进行更改,那么只使用单个指针而不是指向指针的指针:
#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;
}
结果:
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.
哪个更好,但还是不对
修改 a[]
的声明以便正确声明和初始化结果:
char *a[]
读取为指向 char
的指针数组下一个问题是:
printf("%s\n", a+i);
这导致:
untitled1.c:17:22: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘char **’ [-Wformat=]
已更正:
printf("%s\n", *(a+i) );
所以一个可以通过但不是很好的代码版本如下所示:
#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;
}
但是,那有 'magic' 个 4
。
我们可以通过让编译器执行 for()
循环的计算来消除 'magic' 数字:
for( size_t i = 0; i < (sizeof(a) / sizeof( *a ); i++ )
所以最终的代码是:(删除了多余的空行)
#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;
}
以上代码运行的结果为:
abc
ddd
ccc
aaa