将用户输入数据存储在结构的动态数组中/显示所述数据。 C++

Storing user input data in a dynamic array of structures/ displaying said data. C++

所以对于我的项目,我必须...

  1. 使用以下格式创建结构:struct PERSON{string name;年龄;浮动 gpa;};
  2. 要求用户输入他们想要输入的记录数。
  3. 创建一个 PERSON 类型的动态数组 p 以能够保存第 2 部分中的所有记录
  4. 在第 2 部分中将数据读入数组 p
  5. 显示数组p

但是,每当我 运行 我的程序开始输入我的数据时,它不会让我输入多于一组的数据,输出似乎没有什么意义。

这是我的代码:

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;

struct PERSON
{
  string name;
  int age;
  float gpa;
};
PERSON *p;

int main()
{
  int count;
  cout << "Please enter the number of records you wish to enter: ";
  cin >> count;

  p = new (nothrow) PERSON[count];

  if (p == nullptr)
    cout << "Error: memory could not be allocated";

  for (int i = 0; i < count; i++)
  {
    cout << "Enter name, age, and gpa: ";

    getline(cin, p[i].name);
    cin >> p[i].age;
    cin >> p[i].gpa;

    cout << endl;
  }cout << endl;

  cout << "This is the content of array p: " << endl;
  cout << right << setw(8) << "NAME" << setw(7) << "AGE" << setw(7) << "GPA"  << endl;
  cout << "--------------------------" << endl;

  for (int i = 0; i < count; i++)
  {
    cout << p[i].name << " " << p[i].age << " " << p[i].gpa << endl;
  }

  return 0;
}

现在,当我将数据从文件复制到结构的动态数组时,这种格式似乎工作得很好,但我现在似乎无法让它工作,因为我正在处理用户输入。

以下是试用 运行 程序的结果:

Please enter the number of records you wish to enter: 3
Enter name, age, and gpa: Robert 21 2.1 // This is the info I tested

Enter name, age, and gpa:
Enter name, age, and gpa:

This is the content of array p:
    NAME    AGE    GPA
--------------------------
 -842150451 -4.31602e+008 //?
 -842150451 -4.31602e+008 //?
 -842150451 -4.31602e+008 //?
Press any key to continue . . .

我现在可能已经检查了代码两打,并且一直在寻找答案很长一段时间。任何 advice/analysis/comments 将不胜感激。

所以@AndyG 建议我将 getline(cin, p[i].name) 更改为 cin >> p[i].name ,这似乎解决了问题。谢谢!

不好意思给大家添麻烦了

std::getline() 函数是 "misbehaving" 与您的意图相关,因为(我认为)在流输入中留下了一个换行符排队。

您可以使用以下命令丢弃此类字符 cin.sync().

为什么会这样?因为 operator>> 不读取空格,但是 std::getline() 读取,所以当 cin >> 计数; 语句被执行并按下回车,新行字符(来自按下回车)留在流输入队列中,由 std::getline()[=30 自动读取=] 执行时。

还有其他函数可以完成此操作,也许更有消息的人可以告诉我们哪个是最佳选择。

这是一个固定版本:

#include "stdafx.h"
#include <iostream>
#include <iomanip>
#include <string>
#include <cstdlib>
using namespace std;

struct Person
{
    string name;
    int age;
    float gpa;
};

int main()
{
    cout << "Please enter the number of records you wish to enter: ";

    int count;
    cin >> count;


    Person* p = new Person[ count ];

    for ( int i = 0; i < count; i++ )
    {
        cin.sync(); // added this to discard unused characters from input queue

        cout << "Enter name: ";
        getline( cin, p[ i ].name );

        cout << "Enter age: ";
        cin >> p[ i ].age;

        cout << "Enter gpa: ";
        cin >> p[ i ].gpa;

        cout << endl;
    }cout << endl;

    cout << "This is the content of array p: " << endl;
    cout << right << setw( 8 ) << "NAME" << setw( 7 ) << "AGE" << setw( 7 ) << "GPA" << endl;
    cout << "--------------------------" << endl;

    for ( int i = 0; i < count; i++ )
    {
        cout << p[ i ].name << " " << p[ i ].age << " " << p[ i ].gpa << endl;
    }

    return 0;
}

备注: 您不需要检查 Person* p 是否为 nullptr,因为如果 new 运算符无法分配足够的内存,它将抛出 std::bad_alloc 异常。如果确实需要,请考虑将该内存分配包装在 try catch 块中。

问题

您的 getline(cin, p[i].name) 实际上是在同一行获取您的所有输入,您后面的 cin 语句将不匹配。

std::getline 应该保留用于将整行放入字符缓冲区或 std::string,也就是说,它并不总是适合读取字符串的工具。

解决方案

相反,您只需将 getline(cin, p[i].name) 替换为 cin >> p[i].name

Live Demo


其他小改动

删除 nullptr 检查:

if (p == nullptr)
    cout << "Error: memory could not be allocated";

因为在 C++ 中,如果 new 运算符分配失败,您将抛出异常。就像提到的 一样,您可以将其包装在 try catch 块中,尽管我个人只是将其完全删除。

#include <new>
// ...
Person* p = null;
try
{
   p = new Person[count];
} catch(std::bad_alloc& ex)
{
   cerr << "Unable to allocate memory for Person! Error msg: " << ex.what() << "\n";
   return 1;
}

最后,别忘了delete[]你分配给p的内存:

   // ...
   delete[] p;
   return 0;
} //end of int main()

即使您的 OS 肯定会为您清理内存,您仍然应该确保手动清理它。至少要好好练习。或者,您可以改用 std::arraystd::vector,这仍然会为您提供随机访问,就像您已经拥有的 PERSON 的 c 样式数组一样。