简体   繁体   English

c的while循环中的'\\ 0'字符

[英]'\0' character in a while loop at c

I want to make a function which takes an array full of strings and counts the words. 我想做一个函数,该函数需要一个充满字符串的数组并计算单词数。 I don't think that my code in the pic is wrong. 我不认为照片中的代码是错误的。 Everytime a blank appears it is counted. 每次出现空白时,都会对其进行计数。 BUT when a '\\0' character shows up, the while loop doesn't do anything. 但是,当出现'\\0'字符时, while循环不会执行任何操作。 Is something I don't know? 是我不知道的事吗?

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

Here's a working version of your code, and a test program. 这是您的代码的工作版本和测试程序。

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

Note that your Number() function does two jobs — and should only do one, delegating the other to a separate function. 请注意,您的Number()函数完成两项工作-只能完成一项工作,而将另一项委派给单独的函数。 It both counts the words in a single string and prints related information. 它既可以计算单个字符串中的单词,也可以打印相关信息。 I delegate the word counting to a separate function wc() , which greatly simplifies the code in Number() — almost to the point that the function isn't needed. 我将单词计数委托给一个单独的函数wc() ,这大大简化了Number()的代码-几乎达到了不需要该函数的地步。 Note, too, that my version of Number() is told the number of entries the array it is working on, rather than relying on a magic number like 4 . 还要注意,我的Number()版本被告知正在处理的数组的条目数,而不是依赖于像4这样的幻数。 Note that the output from my code allows you to check it for accuracy. 请注意,我的代码输出允许您检查其准确性。 Simply printing the output number doesn't allow you to check for accuracy so easily; 简单地打印输出编号并不能使您如此轻松地检查准确性。 you have to look at the code to see what the numbers mean. 您必须查看代码以了解数字的含义。 Note that your Number() function is defined to return an int but doesn't actually do so. 请注意,您的Number()函数已定义为返回一个int但实际上并未这样做。 This version is defined not to return anything, and it doesn't. 此版本定义为不返回任何内容,也不返回任何内容。

The output from the code is: 该代码的输出为:

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.    ]

Obviously, you could refine the space testing using the isblank() or isspace() macros (functions) from <ctype.h> if you wished, or define the boundary between word and not-word in other ways. 显然,如果愿意,可以使用<ctype.h>isblank()isspace()宏(函数)优化空间测试,或以其他方式定义单词和非单词之间的边界。 The basic concept is reliable, though, across fairly perverse sequences of blanks and words. 但是,基本概念在空白和单词的相当不正确的序列中是可靠的。

If you really want a 2D array of characters, it is not hard to write the code to work with that, though the 'lazy dog' strings will have to be reduced to fit into char data[][20] cleanly. 如果您确实想要2D字符数组,则编写代码以使用该数组并不难,尽管必须将“懒狗”字符串简化为完全适合char data[][20] The basic ideas remain the same — and the wc() function doesn't change. 基本思想保持不变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;
}

Output: 输出:

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   ]

Tests like the " ab cd " example (with double blanks at the start, middle and end) are often very good ones for pushing edge cases — in more contexts than just word counting. " ab cd "示例(开头,中间和结尾处有双空格)之类的测试通常是用于处理极端情况的非常好的测试-在更多情况下,不仅仅是单词计数。 Many a shell script will not correctly handle arguments like that string, for example. 例如,许多Shell脚本将无法正确处理类似该字符串的参数。

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

Now, call this function for any of your strings, adding the results. 现在,为您的任何字符串调用此函数,添加结果。

There are some problems in your code: 您的代码中存在一些问题:

  • if a line does not have characters (starts with a '\\0' ), you increment j before testing for the end of string. 如果一行没有字符(以'\\0'开头),则在测试字符串结尾之前先递增j Do not use do / while loops, they are error prone, and this bug is a classic one. 不要使用do / while循环,因为它们很容易出错,而这个错误是经典的错误。
  • you merely count the number of spaces: this is not the same as the number of words because there could be multiple spaces between 2 words or at the start or end of the line etc. You should instead count the number of transitions from space to non-space, starting from space. 您只计算空格数:这与单词数不同,因为2个单词之间或行首或结尾处可能有多个空格,等等。您应该计算从空格到非空格的过渡数-space,从太空开始。

Here is a simple implementation for your 2D array: 这是2D数组的简单实现:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM