Search code examples
c++arraysstructdynamic-arrays

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


So for my project I have to...

  1. Create a structure using the format: struct PERSON{string name; int age; float gpa;};
  2. Ask the user to enter the number of records they would like to enter.
  3. Create a dynamic array p of PERSON type to be able to hold all records in part 2
  4. Read data into array p in part 2
  5. Display array p

However, whenever I run my program and begin to enter my data it won't let me enter more than one set of data and the output seems to make little sense.

Here is my code:

#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;
}

Now, this format seemed to work just fine when I was copying data from a file into a dynamic array of structures, but I can't seem to get it to work now that I'm dealing with user input.

Here is what a trial run of the program produces:

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 . . .

I've probably gone over the code two dozen times now and have been searching for an answer for quite a while. Any advice/analysis/comments would be greatly appreciated.

So @AndyG suggested that I change the getline(cin, p[i].name) to cin >> p[i].name and that seemed to clear things up. Thank you!

Sorry to trouble everyone over such a silly muck-up.


Solution

  • The Problem

    Your getline(cin, p[i].name) is actually grabbing all your input on the same line, and your later cin statements are going to be mismatched.

    std::getline should be reserved for getting an entire line into a character buffer or std::string, i.e., it's not always the appropriate tool for reading in a string.

    The Solution

    Instead, you simply need to replace getline(cin, p[i].name) with cin >> p[i].name.

    Live Demo


    Other minor changes

    Remove the nullptr check:

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

    Because in C++ you will get an exception thrown if the new operator fails to allocate. Like bku_drytt mentioned, you can wrap this in a try catch block instead, although I'd personally just remove it altogether.

    #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;
    }
    

    Finally, don't forget to delete[] the memory you allocated for p:

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

    Even though your OS will most definitely clean that memory up for you, you should still ensure you clean it up manually. Good practice at least. Alternatively, you can use a std::array or a std::vector instead, which will still give you random access just like the c-style array of PERSON you already have.