【问题标题】:C++ Validating Comma Placement in Numerical InputC++ 验证数字输入中的逗号放置
【发布时间】:2021-02-05 01:01:02
【问题描述】:

我正在学习我的第一门 cs 课程,目前正在学习验证数字输入的不同方法。下面是我为检查逗号位置而编写的一个布尔函数,但是当我输入 65,000 时,它认为逗号在错误的位置。

bool commas(string input) {
    bool commas = true;
    long len = input.length();
    int counter = 0;

    for(int z = len-1; z >= 0; --z) {
        if(counter == 3) {
            if(input[z] != ',') {
                commas = false;
            counter = 0;
            }
        }
        else {
            if(input[z] == ',') {
                commas = false;
            }
            else {
                ++counter;
            }
        }
    }
    return commas;
}

【问题讨论】:

  • 如果从字符串的右侧开始向后循环而不是从左侧循环不是更容易吗?
  • 65,000 中的逗号位于索引 2。在索引4 它有一个0。我建议您考虑z 距离字符串的end 有多远,而不是距离开头有多远。毕竟,1,000,000 在索引26 处有逗号,而10,000,000 在索引37 处有逗号。
  • 还要考虑误报的风险。我假设您不想要认为1,0,0,0,0,0,0 在正确位置有逗号的东西。您将如何检测到这一点?
  • 之所以要从右边开始往后走,是因为每次迭代必须有正确的字符。如果您像现在一样从左侧开始,您不知道5 之后的, 是否有效——您必须等到您到达字符串中的某个位置才能说“哦,对了,我之前看到的那个逗号真的不好”。比如65,00——从左边开始往前走怎么知道逗号在正确的位置?现在从右边开始往回走——那个逗号马上就知道是坏的。
  • c++14 还提供了 digit separator 功能。

标签: c++ validation for-loop boolean numeric


【解决方案1】:

判断逗号是否在更正位置的最简单方法是在字符串中向后(从最右边的字符开始)。

这更容易的原因是,如果你从最左边的字符开始往前走,当你遇到,,你真的不知道那个时候逗号处于有效位置。您只有在迭代过程中稍后才会知道。

另一方面,当您从右到左时,您知道如果遇到逗号,则该逗号处于有效位置 - 无需等到您走得更远判断逗号是否有效的字符串。

为此,需要在循环中进行调整以向后移动,并使用一个额外的计数器来跟踪当前的 3 位数组,因为逗号只能在处理完一组 3 位数后出现。

这是一个未经测试的示例(main 中的简单测试除外):

#include <string>
#include <cctype>
#include <iostream>

bool commas(std::string input)
{
    // if the string is empty, return false
    if (input.empty())
        return false;

    // this keeps count of the digit grouping
    int counter = 0;

    // loop backwards
    for (int z = static_cast<int>(input.size()) - 1; z >= 0; --z)
    {
        // check if the current character is a comma, and if it is in
        // position where commas are supposed to be 
        if (counter == 3)
        {
            if (input[z] != ',')
                return false;

            // reset counter to 0 and process next three digits
            counter = 0;
        }
        else
        // this must be a digit, else error
        if (input[z] == ',')
            return false;
        else
            // go to next digit in group of 3
            ++counter;
    }

    // the first character must be a digit.
    return isdigit(static_cast<unsigned char>(input[0]));
}

int main()
{
    std::string tests[] = { "123,,345", 
                            "123,345",                                 
                            "123,345,678",
                            "12,345",
                            "1223,345",
                            ",123,345",
                            "1",
                            "",
                            "65,00",
                            "123"};

    const int nTests = sizeof(tests) / sizeof(tests[0]);
    for (int i = 0; i < nTests; ++i)
        std::cout << tests[i] << ": " << (commas(tests[i]) ? "good" : "no good") << "\n";
}

输出:

123,,345: no good
123,345: good
123,345,678: good
12,345: good
1223,345: no good
,123,345: no good
1: good
: no good
65,00: no good
123: good

这个工作的方式很简单——我们只是增加一个计数器,看看我们正在查看的当前位置(位置z)在字符串中是否是逗号必须的位置存在。

计数只是计算每组 3 位数字 - 当该组 3 位数字已被处理后,下一个字符(当倒退时)必须是逗号,否则字符串无效。我们还会检查当前位置是否是不能放置逗号的位置。

请注意,最后,我们需要像这样检查无效输入:

,123

这只需检查字符串中的第一个字符并确保它是一个数字即可。

【讨论】:

  • 这个解释对我来说很有意义,谢谢!!现在唯一的问题是使用该逻辑来适应我的代码。由于我的字符串不在数组中,它只是一个输入,我改变了一些东西。我不能说我做对了,因为对于在正确位置有逗号的输入,我的函数没有返回 true。您能看到我可能遗漏或错误解释的内容吗?如果不是也可以,感谢您的帮助!
猜你喜欢
  • 2019-03-11
  • 2018-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多