【问题标题】:Trouble \0 null terminating a string (C)麻烦 \0 null 终止字符串 (C)
【发布时间】:2014-12-03 17:38:46
【问题描述】:

我似乎很难让我的字符串以 \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模拟程序。我会尽快发布更多代码。

关于建议:

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

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

编辑 2:我在下面添加了回复以更新我目前的进度。感谢大家的帮助!

It is here.

.

【问题讨论】:

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

标签: c string null exec strtok


【解决方案1】:

你的代码应该是这样的:

char input2[5];

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

0x0和\0是同一个值0的不同表示;

【讨论】:

    【解决方案2】:

    响应 1:

    感谢所有答案!

    我对响应做了一些更改,但我恢复了 char 建议(或正确的字符串声明),因为就像有人指出的那样,我有一个 strtok 函数。 Strtok 要求我发送一个 char *,所以我恢复到原来的状态(char * input[5])。我将我的代码发布到下面的 strtok 上。我的问题是该程序在我的 Ubuntu 12.04 中运行良好,但是当我尝试在 Debian VM 上运行它时出现段错误。

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

    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++;
    }
    

    【讨论】:

      【解决方案3】:

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

      问:while (c &lt; 4) is safer。并且一定要初始化“c”!

      是的,调试器中的“0x0”和源代码中的“\0”是“同一件事”。

      建议更改:

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

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

      【讨论】:

        【解决方案4】:
        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 中有太多不同风格的“零”,而且它们通常可以悄悄地互换。)

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-02-01
          • 2020-09-16
          • 1970-01-01
          • 2021-05-15
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多