【问题标题】:'\0' character in a while loop at cc处的while循环中的“\ 0”字符
【发布时间】:2018-02-12 03:48:35
【问题描述】:

我想创建一个函数,它接受一个充满字符串的数组并计算单词。我不认为我在图片中的代码是错误的。每次出现空白时都会计算在内。但是当出现'\0' 字符时,while 循环不会做任何事情。有什么我不知道的吗?

int Number(char w[][20]) {
    int i, counter, j;
    counter = 0;
    for (i = 0; i < 4; i++) {
        j = 0;
        do {
            if ((w[i][j] == '\0') || (w[i][j] == ' '))
                ++counter;
            j++;
        } while (w[i][j] != '\0');
        printf("counter=%d\n", counter);
    }
}

【问题讨论】:

  • 如果字符串为“空”,即仅包含"\0",则将计算\0,否则do .. while() 循环条件将不考虑\0。我建议改用while() {...} 循环。想想“当\0 字符出现时”。它不是一个字符一个C字符串中,而是它的结束标记。
  • 那么循环在到达 \0 字符时停止,那么您为什么认为它会被计算在内?
  • while 循环不起作用。如果我没有将任何东西放在二维数组中的一行中,那么 while 将根本不会执行...虽然我之前尝试过我在论坛上写。

标签: c string multidimensional-array while-loop escaping


【解决方案1】:

这是您的代码的工作版本和测试程序。

#include <stdbool.h>
#include <stdio.h>

static int wc(const char *str)
{
    int count = 0;
    bool inword = false;

    char c;
    while ((c = *str++) != '\0')
    {
        if (c == ' ')
            inword = false;
        else
        {
            if (inword == false)
                count++;
            inword = true;
        }
    }
    return count;
}

static void Number(const char *tests[], int num_tests)
{
    for (int i = 0; i < num_tests; i++)
        printf("%d: [%s]\n", wc(tests[i]), tests[i]);
}

int main(void)
{
    const char *tests[] =
    {
        "",
        " ",
        "  ",
        "a",
        "a b",
        " a b ",
        "  ab  cd  ",
        "The quick brown  fox jumps  over   the  lazy     dog.",
        "      The quick brown  fox jumps  over   the  lazy     dog.    ",
    };
    enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
    Number(tests, NUM_TESTS);
    return 0;
}

请注意,您的 Number() 函数做了两项工作——并且应该只做一项,将另一项委托给一个单独的函数。它既计算单个字符串中的单词并打印相关信息。我将单词计数委托给一个单独的函数wc(),这极大地简化了Number() 中的代码——几乎到了不需要该函数的地步。还要注意,我的Number() 版本被告知它正在处理的数组的条目数,而不是依赖于像4 这样的幻数。请注意,我的代码的输出允许您检查它的准确性。简单地打印输出编号并不能让您如此轻松地检查准确性;您必须查看代码以了解数字的含义。请注意,您的Number() 函数被定义为返回int,但实际上并没有这样做。这个版本被定义为不返回任何东西,它不会。

代码的输出是:

0: []
0: [ ]
0: [  ]
1: [a]
2: [a b]
2: [ a b ]
2: [  ab  cd  ]
9: [The quick brown  fox jumps  over   the  lazy     dog.]
9: [      The quick brown  fox jumps  over   the  lazy     dog.    ]

显然,如果您愿意,您可以使用&lt;ctype.h&gt; 中的isblank()isspace() 宏(函数)来优化空间测试,或者以其他方式定义单词和非单词之间的边界。不过,基本概念在相当反常的空格和单词序列中是可靠的。

如果你真的想要一个 2D 字符数组,编写代码来处理它并不难,尽管必须减少“懒狗”字符串以干净地适应 char data[][20]。基本思想保持不变——wc() 函数没有改变。

#include <stdbool.h>
#include <stdio.h>

static int wc(const char *str)
{
    int count = 0;
    bool inword = false;

    char c;
    while ((c = *str++) != '\0')
    {
        if (c == ' ')
            inword = false;
        else
        {
            if (inword == false)
                count++;
            inword = true;
        }
    }
    return count;
}

static void Number(const char tests[][20], int num_tests)
{
    for (int i = 0; i < num_tests; i++)
        printf("%d: [%s]\n", wc(tests[i]), tests[i]);
}

int main(void)
{
    const char tests[][20] =
    {
        "",
        " ",
        "  ",
        "a",
        "a b",
        " a b ",
        "  ab  cd  ",
        "The quick brown fox",
        "  jumps   over     ",
        "  the  lazy  dog   ",
    };
    enum { NUM_TESTS = sizeof(tests) / sizeof(tests[0]) };
    Number(tests, NUM_TESTS);
    return 0;
}

输出:

0: []
0: [ ]
0: [  ]
1: [a]
2: [a b]
2: [ a b ]
2: [  ab  cd  ]
4: [The quick brown fox]
2: [  jumps   over     ]
3: [  the  lazy  dog   ]

"  ab  cd  " 示例这样的测试(在开头、中间和结尾都有两个空格)通常非常适合推动边缘情况——在更多的上下文中,而不仅仅是单词计数。例如,许多 shell 脚本无法正确处理像该字符串这样的参数。

【讨论】:

  • 你是绝对正确的,我的函数的哲学计算''并且单词必须改变。
【解决方案2】:

你的代码有一些问题:

  • 如果一行没有字符(以'\0' 开头),则在测试字符串结尾之前增加j。不要使用do/while 循环,它们容易出错,而这个错误是一个经典的错误。
  • 您只计算空格数:这与单词数不同,因为两个单词之间或行首或行尾等可能有多个空格。您应该计算从空间到非空间,从空间开始。

以下是二维数组的简单实现:

int Number(char w[][20]) {
    int i, j, counter = 0;
    for (i = 0; i < 4; i++) {
        char c, last = ' ';
        for (j = 0; (c = w[i][j]) != '\0'; j++) {
            if (last == ' ' && c != ' ')
                counter++;
            last = c;
        }
    }
    printf("counter=%d\n", counter);
}

【讨论】:

  • 你是对的。在一个完整的程序中这是必要的。你的方法比我的更聪明,我将重写我的函数。我不知道为什么该死的转义整数 '\0' 结束我的 do...while 循环在它结束之前,但我会有一个更好、更逻辑的程序。谢谢你的时间。
【解决方案3】:
 - The first principle of programming is: divide and conquer
 - The second is: use  a loop to iterate
So:

unsigned count_words(char*str)
{
unsigned len, words;

for(len=words=0; *str; str++){
        if(*str == ' ') if(len) {words++; len=0;}
        else len += 1;
        }

if (len) {words++; }
return words;
}

现在,为您的任何字符串调用此函数,并添加结果。

【讨论】:

    猜你喜欢
    • 2014-09-25
    • 1970-01-01
    • 1970-01-01
    • 2011-10-21
    • 2017-01-20
    • 2012-11-11
    • 2022-01-21
    • 2011-06-18
    • 2021-01-31
    相关资源
    最近更新 更多