C++ 中的字符数组验证

3

我需要使用字符数组验证我的数据“123-AB-12345”是否正确。我设置了一个包括‘\0’在内的大小为13的字符数组。如果条件不满足,该函数必须返回false。但是,问题是当我传入更多的值如“123-AB-123456789”时,程序只会验证前12个字符,而没有返回false,仍然返回true。以下是我的程序:

#include<iostream>
using namespace std;
bool isValidBookId(char bookId[13]);
int main()
{
    char book[13];
    cin.getline(book,13);
    bool id = isValidBookId(book);
    cout<<id;
}
bool isValidBookId( char bookId[13] ) {
    /* Valid:  098-EN-98712   */
    if ( bookId[12] != '\0' )
        return false;
    if ( bookId[3] != '-' )
        return false;
    if ( bookId[6] != '-' )
        return false;

    for ( int i = 0; i < 3; i++ ) {
        if ( bookId[i] < '0' || bookId[i] > '9' ) {
            return false;
        }
    }
    for ( int i = 4; i < 6; i++ ) {
        if ( bookId[i] < 'A' || bookId[i] > 'Z' ) {
            return false;
        }
    }
    for ( int i = 7; i < 12 || bookId[12]!='\0'; i++ ) {
        if(bookId[13]!='\0'){
            return false;
        }
        if ( bookId[i] < '0' || bookId[i] > '9' ) {
            return false;
        }
    }

    return true;
}

我不知道为什么这个条件没有生效。

 if ( bookId[12] != '\0' )
        return false;

3
cin.getline(book,13); 的意思是读入不超过13个字符到变量book中。后面的句子 "You won't have more characters." 表示不能输入更多的字符。 - Jarod42
但是如果我传递的字符数超过了限制,那么它应该返回 false。 - Die Hard
1
获取更大的缓冲区,或检查std::cin的状态。(打印book内容以进行调试)。 - Jarod42
无法复现。 bookId [12]!= '\ 0' 很好地工作。 创建一个 [mcve]。 - eerorika
同一个用户提出了完全相同的问题,链接在这里:https://stackoverflow.com/questions/59568183/user-input-validation-using-character-array-in-c/59576014#59576014,并且已经有了一个被接受的答案。主要和关键的问题是,您仍在使用C样式的字符数组。在C++中,您不应该这样做。只需使用````std::string````即可解决所有问题。我只能鼓励您迈出下一步……如果老师要求在C++中使用char数组来表示字符串,那么可以这样做,否则不应该这样做。 - A M
4个回答

2

从您的代码来看,唯一的解释是您数组的最后一个字符为null。尝试像这样指定一个分隔符字符:

cin.getline(book, 13, '\n');

我参考了这个链接:http://www.cplusplus.com/reference/istream/istream/getline/
如果 n 大于零,即使提取的字符串为空,空字符('\0')也会自动附加到写入序列中。

1

您的问题在于输入函数:

您只读取了前12个字符。因此,您不能超过12个字符。

您可以使用std::string

bool isValidBookId(const std::string&s) {
    static const std::regex r{R"(^\d{3}-[A-Z]{2}-\d{5}$)"};

    return std::regex_match(std::begin(s), std::end(s), r);
}

int main()
{
    std::string s;

    while (std::getline(std::cin, s))
    {
        std::cout << s << ": " << isValidBookId(s) << std::endl;
    }
}

演示

或者更大的缓冲区:

bool isValidBookId(const char (&s)[14]) {
    static const std::regex r{R"(^\d{3}-[A-Z]{2}-\d{5}\0$)"};

    return std::regex_match(std::begin(s), std::end(s) - 1, r);
}

int main()
{
    char s[14];

    while (true)
    {
        bool b = !!std::cin.getline(s, 14);
        if (s[0] == '\0') break;
        std::cout << " " << s << ": " << isValidBookId(s) << std::endl;
        if (!b) {
            std::cin.clear();
            std::cin.ignore(255, '\n');
        }
    }
}

演示


1
所有条件都正确。您的问题最初是在输入数据时创建的。
cin.getline(book,13);

“getline”方法接受任意数量的字符(当然在合理范围内),但仅为前12个字符分配空间,第13个字符始终只是“\ 0”。如果您想写更多字符,请让我输入更多字符。”
“正确的选项是:”
bool isValidBookId(char bookId[100]); // now there is a restriction of not 13 characters, but 100
int main()
{
    char book[100]; // now there is a restriction of not 13 characters, but 100 
    cin.getline(book,100); // now there is a restriction of not 13 characters, but 100
}
bool isValidBookId( char bookId[100] ) // now there is a restriction of not 13 characters, but 100
{...}

isValidBookId(char bookId[100]) 实际上是 isValidBookId(char* bookId)(没有大小限制),因为你不能通过值传递C数组。 - Jarod42

0
如上所述,
cin.getline(book,13)不会在您的数组中保存超过12个字符。 请改用以下代码:
char book[100]; // To save upto 99 characters
cin.getline(book,100);

并更改

isValidBookId(char bookId[13])

返回
isValidBookId( char bookId[100] )

并且在这个isValidBookId函数中,移除所有bookId[12]!='\0'的检查,因为第12个索引处可能是任何字符。


isValidBookId(char bookId[13]) 实际上应该是 isValidBookId(char* bookId),因为你不能通过值传递C数组。 - Jarod42

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接