使用 do-while 循环计算字符串中的字符、单词和行 | C++

Counting characters, words and lines in a string using a do-while loop | C++

我正在尝试将计算字符串中字符、单词和行数的 while 循环转换为 do-while 循环。

这是我的 while 循环:

#include <stdio.h>
#include <string>
#include <typeinfo>
using namespace std;

int main()
{
    int c;
    int characters = 0;
    int words = 1;
    int newlines = 0;
    printf("Input a string.  Press enter, then ctrl+Z, then enter once more to end string.\n");

    while ((c = getchar()) != EOF)
    {
        if (c >= 'a' && c <= 'z' || c>= 'A' && c<= 'Z')
            characters++;
        else if (c == ' ')
            words++;
        else if (c == '\n')
            newlines++;
    }

    printf("The number of characters is %d\n", characters);
    printf("The number of words is %d\n", words);
    printf("The number of newlines is %d\n", newlines);


    return 0;
}

我已经尝试了几个小时来使用 do-while 循环重复上述过程,但无济于事。

这是我目前的情况:

#include <stdio.h>
#include <string>
#include <typeinfo>
using namespace std;  

int main()
{
    int c;
    int characters = 0;
    int words = 0;
    int newlines = 0;
    printf("Input a string.  Press enter, then ctrl+Z, then enter once more to end string.\n");
    
    do 
    {
        c = getchar();
        if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
            characters++;
        else if (c == ' ')
            words++;
        else if (c == '\n')
            newlines++;
    } while (c = getchar() != EOF);
        

    printf("The number of characters is %d\n", characters);
    printf("The number of words is %d\n", words);
    printf("The number of newlines is %d\n", newlines);

    return 0;
}

问题:

您正在尝试做的事情是完全反自然的,没有任何意义。您显示的情况应该使用 while 循环,而不仅仅是任何循环。

解法:

技术上你仍然可以这样做,但是非常糟糕的风格:

    do
    {
        bool do_end = (c = getchar()) != EOF;
        if(do_end)
            break;
        if ((c >= 'a' && c <= 'z') || (c>= 'A' && c<= 'Z'))
            characters++;
        else if (c == ' ')
            words++;
        else if (c == '\n')
            newlines++;
    } while (true);

while 循环在这种情况下要好得多,所以除非你确实需要,否则不要使用 do while

此外,考虑到这解决了您要求的问题,但是如果有相邻的空格或字符串为空,您的代码本身将无法计算单词的数量。

附加信息:

  1. using namespace std; 被认为是 bad practice 在这里你甚至不需要它,因为你没有在 std 命名空间中使用任何东西。
  2. 您包括了 <string><typeinfo>,但两者都没有使用。

发布的 do-while 循环有两个主要问题。

第一个是您正在读取两个字符,但在循环的每次迭代中只处理字符。

第二个是 while (c = getchar() != EOF) 没有按照您希望的那样进行。由于运算符的优先级,这相当于 while (c = (getchar() != EOF)).

do 
{
    c = getchar(); // OK the first time, not after that.
    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
        characters++;
    else if (c == ' ')
        words++;
    else if (c == '\n')
        newlines++;
} while (c = getchar() != EOF); // This is bad.

即使你使用

解决了第二个问题
while ((c = getchar()) != EOF);

它仍然不好,因为该行很适合检测 EOF,但该字符在进一步处理时会被忽略。


您必须将 do-while 循环更改为:

do 
{
    c = getchar();
    if ( c == EOF )
    {
        break;
    }

    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
        characters++;
    else if (c == ' ')
        words++;
    else if (c == '\n')
        newlines++;
} while (true);

如您所见,这并不是 while 循环的改进。从清洁度的角度来看,它比 while 循环更糟糕。

正如其他人所提到的,您描述的情况 far 更适合使用普通 while 循环,而不是 do ... while。然而,尽管如此,并且在不解决代码中的其他问题(例如评论中提到的问题)的情况下,您可以简单地通过给 'control variable' 一个初始的 'dummy' 值来更改许多这样的循环循环内没有影响。在您的情况下,c 的零值几乎不可能是 实际 输入值,因此您可以使用它:

int c = 0; // Give c an initial (non)value.
do 
{
//  c = getchar(); // Remove this line, as it makes two 'reads' per loop!
    if (c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z')
        characters++;
    else if (c == ' ')
        words++;
    else if (c == '\n')
        newlines++;
} while ((c = getchar()) != EOF); // Note the added parentheses!!!

但是请注意,真正实现的所有这些都是通过循环添加一个额外的运行,没有任何目的。