在C语言中如何正确地在字符串末尾添加\0?

3

我似乎无法用 \0 结束我的字符串。我不确定这是否是问题,所以决定发帖询问。

首先,我声明我的字符串为:

char *input2[5];

在程序的后续中,我添加了这行代码来将所有未使用的插槽转换为\0,将它们全部变成了空结束符。本可以使用for循环实现,但是就这样吧。
while (c != 4) {
    input2[c] = '\0';
    c++;
}

在Eclipse中,当处于调试模式时,我看到空槽现在包含的是0x0而不是\0。这些是相同的吗?另一个字符串我声明为


char input[15] = "";

但在调试模式下显示\000。我的问题是,我在Debian VM上遇到了分段错误(但在我的Linux 12.04上可以正常运行)。我猜测是因为字符串没有真正终止,编译器不知道它何时停止,因此会尝试在数组中访问内存,而该数组已经越界。

编辑: 我会尽快回答所有其他问题,但当我将字符串声明更改为其他建议的方式时,我的程序崩溃了。有一个strtok()函数,用于将我的fgets输入切成字符串,然后将它们放入我的input2数组中。

所以,

input1[0] = 'l'
input1[1] = 's'
input1[2] = '\n'

input2[0] = "ls". 

这是一个使用fork和execvp模拟shell的程序。我很快会发布更多代码。

关于建议:

char *input2[5]; 这是一个完全合法的声明,但它将input2定义为指针数组。要包含字符串,它需要是char数组。

我会尝试再次进行更改。我之前确实尝试过,但我记得它给了我另一个运行时错误(段错误?)。我认为这是因为我实现的strtok()函数的方式不同。我会再次检查它。谢谢!

编辑2:我在下面添加了一个响应以更新我的进展情况。感谢所有的帮助!

在这里。

.


5
请使用char input2[5];,而非char *input2[5]; - R Sahu
1
为什么你没有声明你的字符串 char input[5];?你真的需要额外的间接层吗?while (c < 4) 更安全。而且一定要初始化 "c"! - FoggyDay
是的,在调试器中的“0x0”和源代码中的“\0”是“同一件事”。 - FoggyDay
1
@FoggyDay:我怀疑这不是这种情况。调试器可能使用0x0来显示空指针的值;它可能会使用'\0'来显示空字符的值。不幸的是,正如我在我的答案中提到的那样,'\0'是一个有效的空指针常量。 - Keith Thompson
1
嗨,Greg!感谢你指出这一点。我在下面添加了一个回复。我展示了我的strtok代码。这就是为什么我决定将其声明为char input2 [5],因为strtok只接受char而不是char数组。 - Kevin
4个回答

3

回复 1:

感谢所有的答案!

我根据大家的回答做了一些更改,但是因为有人指出,我使用了 strtok 函数,而 strtok 需要我发送一个 char *,所以我还原了 char * input[5]。我在下面发布了我的代码到 strtok。我的问题是,程序在我的 Ubuntu 12.04 上运行正常,但当我尝试在 Debian VM 上运行它时,会给我一个 segfault 错误。

我很困惑,因为最初我认为错误是因为编译器尝试访问已经超出界限的数组索引。但这似乎不是问题,因为有很多人提到,0x0 只是另一种写法 \000。我在下面发布了我的调试窗口的变量部分。就我所能看到的,一切似乎都是正确的.. 嗯..

enter image description here

Input2[0] 和 input[0],input[1] 是重点关注的点。

下面是我的代码直到 strtok 函数。其余的只是 fork 然后 execvp 调用:

int flag = 0;
int i = 0;
int status;
char *s; //for strchr, strtok
char input[15] = "";
char *input2[5];
//char input2[5];

//Prompt
printf("Please enter prompt:\n");

//Reads in input
fgets(input, 100, stdin);

//Remove \n
int len = strlen(input);
if (len > 0 && input[len-1] == '\n')
    input[len-1] = ' ';

//At end of string (numb of args), add \0

//Check for & via strchr
s = strchr (input, '&');
if (s != NULL) { //If there is a &
    printf("'&' detected. Program not waiting.\n");
    //printf ("'&' Found at %s\n", s);
    flag = 1;
}


//Now for strtok
input2[i] = strtok(input, " "); //strtok: returns a pointer to the last token found in string, so must declare
                                //input2 as char * I believe

while(input2[i] != NULL)
{
    input2[++i] = strtok( NULL, " ");
}

if (flag == 1) {
    i = i - 1; //Removes & from total number of arguments
}

//Sets null terminator for unused slots. (Is this step necessary? Does the C compiler know when to stop?)
int c = i;
while (c < 5) {
    input2[c] = '\0';
    c++;
}

2
你的代码应该像这样:
```html

你的代码应该像这样:

```
char input2[5];

for (int c=0; c < 4; c++) {
    input2[c] = '\0';
}

0x0和\0是相同值0的不同表示方式。


1
char *input2[5];

这是一个完全合法的声明,但它将input2定义为指针数组。要包含一个字符串,它需要是一个char数组。
while (c != 4) {
    input2[c] = '\0';
    c++;
}

再次强调,这是合法的,但由于input2是指针数组,input2[c]是一个指针(类型为char*)。对于空指针常量的规则是'\0'是一个有效的空指针常量。该赋值等同于:

input2[c] = NULL;

我不知道你想用 input2 做什么。如果你将它传递给一个期望指向字符串的 char* 类型函数,你的代码将无法编译 -- 或者至少会得到一个警告。

但是如果你想让 input2 保存一个字符串,它需要被定义为:

char input2[5];

很不幸,你犯的错误恰好是C编译器不一定会诊断的错误之一。(在C语言中有太多不同类型的“零”,它们通常可以悄悄地互换使用。)


0

问:为什么你没有声明你的字符串char input[5];?你真的需要额外的间接层吗?

问:while (c < 4)更安全。一定要初始化“c”!

是的,“0x0”在调试器中和源代码中的“\0”是“相同的东西”。

建议更改:

char input2[5];
...
c = 0;
while (c < 4) {
    input2[c] = '\0';
    c++;
}

这几乎肯定会解决您的分段违规问题。

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