C ++中输入字符数组的特定验证

时间:2017-07-13 10:12:56

标签: c++ validation

有一段时间我在验证char数组时遇到了问题。我已经看到很多很好的方法可以做到这一点,但仍然没有弄清楚如何在我的代码中组合一些东西。 无法弄清楚如何正确解决这个简单的问题。

 struct student{
    char fullname[SLEN];
    char hobby[SLEN];
    int ooplevel;
    };

int getinfo( student*, int );
void display1( student );
void display2( const student* );
void display3( const student pa[], int );

int main()
{
    std::cout << "Group size: ";
    int class_size;
    std::cin >> class_size;
    while( std::cin.get() != '\n' )
        continue;

    student* ptr_stu = new student[class_size];
    int entered = getinfo( ptr_stu, class_size );
    for( int i=0; i<entered; ++i )
    {
        display1( ptr_stu[i] );
        display2( &ptr_stu[i] );
    }
    display3( ptr_stu, entered );
    delete [] ptr_stu;
    std::cout << "Gotowe.\n";

    getchar();
    return 0;
}

int getinfo( student* stu, int n )
{
    int i=0;

    while( i<n ){

        std::cout << "Fullname " << i+1 << ": ";
        std::cin >> stu[i].fullname;

        std::cout << "Hobby " << i+1 << ": ";
        std::cin >> stu[i].hobby;

        std::cout << "OOPlevel " << i+1 << ": ";
        std::cin >> stu[i].ooplevel;
    ++i;
    }
}

我确定必须有办法验证char数组:
1.最大长度为30
2.必须包含2个单词,因为其第一个和第二个名称为 3.不能包含数字
4.如果用户按下回车而没有输入任何内容,则会导致断开循环 5.一切都在功能中,其中一个参数是指向存储名称的结构的指针 请原谅我这样的原始问题。我知道甚至没有尝试在我的代码中解决这个问题,但我还没有想过要把我在这里创建的垃圾放进去。

1 个答案:

答案 0 :(得分:0)

  
      
  1. 最大长度为30
  2.   

std::cin >> std::setw(30) >> ...;

  
      
  1. 必须包含2个字,因为其第一个和第二个名称
  2.   

operator>>运气不好,停在空白处。因此,您需要阅读两次或者阅读完整的一行(std::getline)。

  
      
  1. 不能包含数字
  2.   

好吧,迭代字符串并用isdigit检查每个字符:

for(unsigned char c : theString)
{
    if(isdigit(c))
        // error!
}
  
      
  1. 如果用户按Enter键而不键入任何内容
  2. ,则会导致循环中断   

再次,operator>>运气不好 - 它只会忽略空格,包括换行符......再次,你需要std::getline

std::string s;
std::getline(std::cin, s);
if(s.empty())
    break; // or return

不确定这是不是一个好主意,因为用户可能会意外地输入。那么用户只进入空白区呢? Line非空,但仍然不包含任何信息...

  
      
  1. 一切都在函数中,其中一个参数是指向将存储名称的结构的指针。
  2.   

不确定你的意思 - 你已经有了getInfo,不是吗?

您可能会发现并非所有上述内容都很好,例如: G。获取空行仅适用于std::getline,因此您必须始终使用它...

现在想知道 - 您使用C ++ - 为什么不使用C ++标准容器?它们让您的生活更轻松:

struct Student
{
    std::string fullName; // I personally would prefere surname and forename anyway...
    std::string hobby;
    // ...
}

int getInfo(std::vector<Student>& students)
{
    for(auto& student : students)
    //      ^ enforce reference to actually modify the objects in the vector
    {
        // read input...
    }

    // you should return something!!!
    return students.size();
}

好的,对于过早的循环退出,我们需要一个返回值 - 我们可以从vector providinig连续内存中获利,所以以下是有效的:

if(emptyLine)
    return &student - students.data();

学生姓名:

// we don't need any additional buffer, can read into target directly...
std::getline(std::cin, student.fullName);
auto i = student.fullName.begin(), j = i;
while(isspace((unsigned char)(*i))
    ++i;
while(!isspace((unsigned char)(*i))
{
    if(isdigit((unsigned char)(*i))
        // error handling!
    *j++ = *i++;
}
*j++ = ' '; // separator
// now sure name analogously!
student.fullName.resize(j - student.fullName.begin());

您可能已经注意到:这会读取整个字符串并对其进行修改。喜欢吗?

上面的代码中还有一些错误,你看到了吗?必须在while循环中检查i != fullName.end()并在分配分隔空格之前确保不超过字符串的当前范围!我会把它留给你......

您现在应该使用矢量作为显示功能:

void display(std::vector const& students);
//          ^ no need for additional identifiers, C++ supports overloads
//                        ^ const vector, you won't modify it
//                            ^ reference to prevent a copy

提示循环:

for(auto& student : students)

使用auto关键字可以防止您不必关心const对象。然后引用会阻止您复制数据,因此这是您应该更喜欢的...

类似于一个学生:

void display(Student const& student);
//          ^ overload!
//                     ^  ^ const reference

主要:

//student* ptr_stu = new student[class_size];
//^ replaced by:
std::vector<Student> students(class_size);
//                   ^ or whatever name you like
//                            ^ one of vectors constructors accepts a size
//                              this is then equivalent to:
//                              std::vector<...> v; v.resize(n);
//                                               ^ (empty vector)
// and no need for deletion either...