打印字符数组

6

我有一个字符数组声明为:

char *array[size];

当我执行一项任务时,
printf("%s", array);

为什么我的输出结果会出现些乱码字符?

http://www.cplusplus.com/reference/clibrary/cstdio/printf/

该网址指出printf函数的格式为:`int printf ( const char * format, ... );

#include <stdio.h>
#include <string.h>
#define size 20
#define buff 100
char line[buff];

int main ()
{
    char *array[100];
    char *sep = " \t\n";

    fgets(line, buff, stdin);

    int i;

    array[0] = strtok(line, sep);

    for (i = 1; i < size; i++) {
        array[i] = strtok(NULL, sep);

        if (array[i] == NULL)
            break;
    }

    return 0;
}

6
那是一个指针数组,而不是字符。 - wildplasser
4个回答

7

您可以这样声明一个字符数组:

char foo[size];

您似乎将其与 char * 搞混了,它是指向字符的指针。您可以这样说:

char *bar = foo;

这将使得bar指向foo的内容。实际上,它指向foo的第一个字符。

为了打印数组的内容,你可以采用以下方法之一:

// either print directly from foo:
printf("%s", foo);
// or print through bar:
printf("%s", bar);

需要注意的是,C语言不会对变量的内容进行初始化,所以除非你明确地将内容设置为某些值,否则你会得到垃圾值。此外,如果这些垃圾值不包含\0,也就是值为0的字符,它会继续输出超出数组末尾的内容。


1
"&foo" 的类型是 "char()[size]",它与 "bar" 的类型 "char" 并不兼容。你可以这样说:char *bar = foo; - pmg
@pmg:这会教育我不在测试之前编写 C 代码。已修复,谢谢。 :) - Sebastian Paaske Tørholm

4
为什么我们把这么简单的事情说得那么难懂呢?(为 IT 技术相关内容)
char array[SIZE];
... /* initialize array */
puts(array);   /* prints the string/char array and a new line */
/* OR */
printf("%s", array); /* prints the string as is, without a new line */
\char数组中想要作为你的字符串结尾的字符(例如,如果你想让你的字符串读作“Hello”,那么NUL字符'\0'将是'o'之后的下一个字符)必须是终止字符。如果你使用C函数读取输入,它会自动附加到你的缓冲区的末尾。只有在某些情况下手动写入字符到缓冲区时才需要手动处理它。
编辑:如pmg的评论所述,“\0”放置在你想要字符串结束的任何位置,因此,如果你想缩短你的字符串,你可以将其移动到靠近前面的位置,或者要有一个空字符串,只需array[0] ='\0';即可。这样做也可以用于在单个缓冲区内对较小的字符串进行标记,就像strtok一样。例如,“Part1 \ 0 Part2 \ 0 Part3 \ 0”。但我认为这已经超出了问题的范围。
例如,如果你想将字母表的前三个字符作为字符串存储(不知道为什么任何人会这样做,但这只是一个例子):
char array[4];
array[0] = 'a';
array[1] = 'b';
array[2] = 'c';
array[3] = '\0';
printf("%s\n", array);

如果你有像char array[] = "Hello";这样的东西,'\0'会自动为你添加。

1
printf(array)不会“按原样打印字符串”,它会解释字符串,如果包含任何转换说明符,则会导致未定义行为。请改用printf("%s", array) - pmg
糟糕,我的错。我复制并粘贴了puts(array),然后将其更改为printf。那是一个相当糟糕的失败,容易受到格式字符串漏洞的攻击。 - AusCBloke
1
刚刚撤销了-1。现在你的回答中只有一个小问题:零终止符不需要是数组中的最后一个字符。这是完全有效的(尽管无用):char foo [7] =“foo \ 0bar”; --- foo [6]'r'puts(foo); 输出 "foo\n" - pmg
是的,我想我没有很好地组织我的话,让我来修正一下。干杯。 - AusCBloke

4

你的数组没有被初始化,同时你拥有一个指针数组,而不是char类型的数组。如果你想要一个char类型的数组,应该这样写:char* array = (char*)malloc(sizeof(char)*size);现在你拥有了指向数组第一个元素的指针。


4
在C语言中,new不是一个运算符。 - Mat

0
char *array[size];

array 不是一个 char *,它更像是一个 char **(指向字符数组的指针,类似于指向指向字符的指针)。

如果你只需要一个 C 字符串,可以选择以下任一方法:

char array[size];

确保你正确地进行0终止,否则

char *array;

并确保您为其正确分配和释放存储空间(还要以0结尾)。


什么是将字符数组指针零终止? - ilovetolearn
在C语言中,字符串只是char值的数组。字符串的结尾由一个值为0的char表示。 - Mat
1
这完全不是那么回事。如果你传递一个 char* 并使用 %s 格式说明符,printf 就会做到这一点。但是,如果你的字符串没有以 0 结尾(这不是一个指针,而是一个字符),它将继续打印存储在字符串后面内存中的任何内容,导致未定义的行为。 - Mat
@Mat 我不理解网上给出的示例。它只有非常简单的数组访问示例。 - ilovetolearn
然后拿起一本C语言书,或者在网上寻找其他例子。这是基础的C语言。 - Mat
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接