【问题标题】:How do I validate a string to make sure there is no non-digits and integers less than or equal to 1?如何验证字符串以确保没有小于或等于 1 的非数字和整数?
【发布时间】:2020-12-04 21:14:10
【问题描述】:

所以我目前正在用 C++ 编写一个程序。我写了以下函数。它说“//code here”的那一行是我的问题所在。基本上,该程序允许用户创建自己的测验 txt 文件。对于“测验应该有多少问题?”这个问题。用户将输入一个代表问题数量的数字。当必须验证用户输入时,就会出现问题。

谁能帮我创建一个执行以下操作的循环?

  1. 确保用户只输入数字。
  2. 确保输入的数字大于 1。
  3. 如果用户输入了非数字,则会向用户发送错误消息。
  4. 如果用户输入的数字小于 2,则会向用户发送错误消息。
  5. 程序会验证用户是否只是按下了回车键。

所有这些都整理好后,程序会将 NumberOfQuestions 设置为等于用户输入并将其转换为 int 后的值。

void WriteOutQuestions(string &QuizName)
{
ofstream WriteOut;
string filename = "";
string userInput = "";
int numberOfQuestions;
char userInputChar = '0';
bool IncludeCommments = false;

cout << "Name your file\n";
getline(cin, filename);
cout << "Now give your new quiz a title\n";
getline(cin, QuizName);
cout << "How many questions should the quiz have?\n";
getline(cin, userInput);

//code here

numberOfQuestions = stoi(userInput);
cout << "The quiz will contain " << numberOfQuestions << " questions." << endl;
cout<< "Would you like to include comments in any of the choices?\n";
cout << "[Y/y for yes N/n for No]\n";
getline(cin, userInput);

if (userInput == "y" && userInput == "Y")
    IncludeCommments = true;
else
    cout << "Comments disabled by user...\n";

WriteOut.open(filename + ".txt");
if (!WriteOut)
{
    cout << "The file was not found...\n";
}
else
{
    cout << "File was read!\n";
}
WriteOut << QuizName << endl;
WriteOut << numberOfQuestions << endl;

for (int i = 0; i < numberOfQuestions; ++i)
{
    cout << "What is question number " << i + 1 << "?\n";
    getline(cin, userInput);
    WriteOut << "Q" << i + 1 << " " + userInput << endl;
    
    cout << "What is choice A for question number " << i + 1 << "?\n";
    getline(cin, userInput);
    WriteOut << "A) " + userInput << endl;
    
    if (IncludeCommments == true)
    {
        cout << "What is the comment for choice A for question number " << i + 1 << "?\n";
        getline(cin, userInput);
        WriteOut << userInput << endl;
    }
    else
        WriteOut << "" << endl;
    
    cout << "What is choice B for question number " << i + 1 << "?\n";
    getline(cin, userInput);
    WriteOut << "B) " + userInput << endl;
    
    if (IncludeCommments == true)
    {
        cout << "What is the comment for choice B for question number " << i + 1 << "?\n";
        getline(cin, userInput);
        WriteOut << userInput << endl;
    }
    else
        WriteOut << "" << endl;
    
    cout << "What is choice C for question number " << i + 1 << "?\n";
    getline(cin, userInput);
    WriteOut << "C) " + userInput << endl;
    
    if (IncludeCommments == true)
    {
        cout << "What is the comment for choice C for question number " << i + 1 << "?\n";
        getline(cin, userInput);
        WriteOut << userInput << endl;
    }
    else
        WriteOut << "" << endl;
    
    cout << "What is choice D for question number " << i + 1 << "?\n";
    getline(cin, userInput);
    WriteOut << "D) " + userInput << endl;
    
    if (IncludeCommments == true)
    {
        cout << "What is the comment for choice D for question number " << i + 1 << "?\n";
        getline(cin, userInput);
        WriteOut << userInput << endl;
    }
    else
        WriteOut << "" << endl;
    
    cout << "Which choice is the right one? [A, B, C or D]\n";
    getline(cin, userInput);
    while (userInput != "a" && userInput != "A" && userInput != "b" && userInput != "B" &&
           userInput != "c" && userInput != "C" && userInput != "d" && userInput != "D")
    {
        cout << "Only A-D is accepted\n";
    }
    userInputChar = userInput[0];
    if (userInputChar > 96)
    {
        userInputChar -= 32;
    }
    userInput = userInputChar;
    cout << "userinput contains " << userInput << endl;
    cout << "userinputchar contains " <<userInputChar << endl;
    WriteOut << userInput << endl;
}
WriteOut.close();
}

【问题讨论】:

  • 允许的最大数量是多少?

标签: c++ loops validation exception getline


【解决方案1】:

首先你需要把下面代码中的&&改为||正确运行代码代码

if (userInput == "y" && userInput == "Y")
    IncludeCommments = true;
else
    cout << "Comments disabled by user...\n";

进入验证后,您可以在获取用户输入后维护一个标志变量

cout << "How many questions should the quiz have?\n";
getline(cin, userInput);
int length=userInput.length(); //gives the length of string entered
int flag=0; //flag variable
for(int i=0;i<length;i++)
{
   if((!(userinput[i]>='0'&&userinput[i]<=9))||isspace(s[i])) //i am 
   considering space is not a problem
   {
      flag=1;
   }
}
if(flag!=0)
{
  cout<<"error:Non digit is entered"<<endl
}else
{
  int numberofquestions = stoi(userinput);
  if(numberofquestions<=1){
     cout<<"error:number less than 2 is entered"<<endl;
  }
}

【讨论】:

  • 这是在正确的轨道上,但不要命名变量flag;给它起一个名字,告诉读者它做了什么。此外,标准库提供了isdigit,您可以使用它来代替检查'0''9'。但更重要的是:一旦您看到了错误的输入字符,您就不需要检查其余的字符。所以在设置标志后添加break; 语句。就个人而言,我会将该循环编写为一个单独的函数;如果检测到错误,return false; 如果循环运行完成,return true;
  • 感谢您的宝贵建议,因为我是编程新手,这些宝贵的反馈对良好的编程实践非常有帮助。
【解决方案2】:

选择太多,很难做出好的推荐。

我将向您展示几种解决方案。第一部分始终采用相同的方法:

  • 我们运行一个 do 循环
  • 首先我们指导用户,做什么
  • 然后我们读取输入
  • 然后我们检查一下,是否都是数字
  • 如果我们有所有数字,那么我们将转换为数字
  • 并检查,如果数字大于 1

如果我们发现错误,我们会再次循环。让我们看看下面代码中的选项

  1. 基于索引的 for 循环并与字符数字进行比较
  2. 基于索引的 for 循环和 isdigit 函数的使用
  3. 基于范围的 for 循环和 isdigit 函数的使用
  4. all_of算法及isdigit函数的使用
  5. 正则表达式。还将处理空行
  6. 扩展的正则表达式。还将处理空行并检查 number > 1

选项 1-4 需要额外检查空行。用户按一下就可以了。

请查看包含所有选项的代码:

#include <iostream>
#include <string>
#include <cctype>
#include <algorithm>
#include <regex>

int main() {
    // We try to get input from the user and run a loop as long as it is not OK
    bool inputIsOK{};
    // This is the number of questions that we want to read
    int numberOfQuestions{};

    // Ask for valid input from user
    do {
        // Assume valid input
        inputIsOK = true;

        // Instruct user
        std::cout << "\nHow many questions should the quiz have? Enter a number > 1.\n";

        // Read complete line from the user
        std::string line{};
        if (std::getline(std::cin, line)) {
            // Check, if all characters are valid (digits)
            // Option 1 -------------------------------------------------------------------
            // Index based for loop and compare with character digits
            for (size_t i{}; i < line.length(); ++i) {
                if (line[i] < '0' || line[i] > '9') {
                    inputIsOK = false;
                    std::cerr << "\nError 1: Please enter digits only\n";
                    break;
                }
            }
            // Option 2 -------------------------------------------------------------------
            // Index based for loop and use of isdigit function
            for (size_t i{}; i < line.length(); ++i) {
                if (not std::isdigit(line[i])) {
                    inputIsOK = false;
                    std::cerr << "\nError 2: Please enter digits only\n";
                    break;
                }
            }
            // Option 3 -------------------------------------------------------------------
            // Range based for loop and use of isdigit function
            for (const char c : line) {
                if (not std::isdigit(c)) {
                    inputIsOK = false;
                    std::cerr << "\nError 3: Please enter digits only\n";
                    break;
                }
            }
            // Option 4 -------------------------------------------------------------------
            // all_of algorithm and use of isdigit function
            if (not std::all_of(line.begin(), line.end(), isdigit)) {
                inputIsOK = false;
                std::cerr << "\nError 4: Please enter digits only\n";
            }

            // Option 1-4 -----------------------------------------------------------------
            // For option 1 to 4 you need to additionally check for empty line
            if (inputIsOK && line.length() == 0) {
                inputIsOK = false;
                std::cerr << "\nError 5: Please enter digits only\n";
            }

            // Option 5 -------------------------------------------------------------------
            // regex. Will also handle empty lines
            if (not std::regex_match(line, std::regex("\\d{1,6}"))) {
                inputIsOK = false;
                std::cerr << "\nError 6: Please enter digits only (max 6)\n";
            }
            // Option 6 -------------------------------------------------------------------
            // Extened regex. Will also handle empty lines AND will check if number > 1
            if (not std::regex_match(line, std::regex(R"([2-9]|([1-9][0-9]{1,6}))"))) {
                inputIsOK = false;
                std::cerr << "\nError 7: Please enter number > 1  (Max 6 digits)\n";
            }
            // End Option -----------------------------------------------------------------

            // Check, if number is > 1
            if (inputIsOK) {
                numberOfQuestions = std::stoi(line);
                if (numberOfQuestions < 2) {
                    inputIsOK = false;
                    std::cerr << "\nError 8: Number too small. Enter number > 1\n";
                }
            }
        }
        else {
            std::cerr << "\nError: General problem with input\n";
            inputIsOK = false;
            std::cin.clear();
        }

    } while (not inputIsOK);
    return 0;
}

你可以选择任何你想要的选项。


但是。我不会使用上述任何一种。

我会使用 IOstream 工具并直接读取一个无符号整数。如果输入错误,std::cin 的状态会转到失败并指出问题。

所以,你可以改用它:

#include <iostream>
#include <limits>
int main() {
    // We try to get input from the user and run a loop as long as it is not OK
    bool inputIsOK{};
    // This is the number of questions that we want to read
    unsigned int numberOfQuestions{};

    // Ask for valid input from user
    do {
        // Instruct user
        std::cout << "\nHow many questions should the quiz have? Enter a number > 1.\n";

        // Get input. Directly as number
        inputIsOK = (std::cin >> numberOfQuestions) && (numberOfQuestions > 1);

        // In case of error. Show message
        if (not inputIsOK) {
            std::cerr << "\nError 1: Wrong input\n";
            std::cin.clear(); std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
        }
    } while (not inputIsOK);
    return 0;
}

ignore 函数将删除所有可能仍在输入缓冲区中的垃圾。

【讨论】:

    猜你喜欢
    • 2021-04-19
    • 2015-09-14
    • 2013-10-09
    • 1970-01-01
    • 1970-01-01
    • 2021-12-08
    • 2014-12-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多