How to use a pointer to an array of strings? - c++

My homework problem is to modify code written for a previous assignment that saved an array (of user-specified size) of test scores so that it also saves a parallel array of student names associated with these test scores. We are to use pointers and pointer notation whenever possible.
My problem occurs early on: I ask for the student's full name and receive the input using the getline cin object and cin.ignore() to avoid passing the last name into my next cout/cin request.
However, when I attempt to recall the student name using either pointer notation (deref the pointer) or array notation all I get is blank space. String objects have been the most difficult for me to grasp this quarter, so it is possible that it is just that I am missing a crucial bit of reasoning here. I have gone back and read through my text but it is not incredibly helpful as it shows my exact format for a similar desired result. Also, most online research has been yielding info that is well beyond a first quarter c++ student like myself. Any help is very much appreciated! Here is the snippet of code where I think my problem lies:
#include<iostream>
#include<cmath>
#include<iomanip>
#include<string>
using namespace std;
void sortArray(int*, string*, int);
void averageScore(int*, int);
int main()
{
//pointer to point to test scores
int* scores;
string* student;
// integer test to indicate size of array
int test;
// get user defined array size
cout << "How many tests would you like to save?" << endl;
cin >> test;
// define dynamically allocated array scores
scores = new int[test];
student = new string[test];
// for loop to enter each test score as an element of scores array
for (int i = 0; i < test; i++)
{
cout << "Enter the student's name: " << endl;
getline(cin, student[i]);
cin.ignore();
cout << "Enter the test score for " << *(student+i) << " : "<< endl;
cin >> *(scores+i);
EDIT:
I played around with it and was able to get the results I wanted with the following code:
for (int i = 0; i < test; i++)
{
cout << "Enter the student's first name: " << endl;
cin >> first;
cout << "Enter the student's last name: " <<endl;
cin >> last;
*(student+i) = first + " " + last;
cout << "Enter the test score for " << *(student+i) << " : "<< endl;
cin >> *(scores+i);

Related

How to Create & Add new object in existing array using Dynamic Memory allocation

I am trying to do some stuff with C++ and i am new in it :)
I have tried 1 program of class that gets the student details and print the output of it.
#include <iostream>
using namespace std;
#define MAX 10
class student
{
private:
char name[30];
int rollNo;
int total;
float perc;
public:
//member function to get student's details
void getDetails(void);
//member function to print student's details
void putDetails(void);
};
//member function definition, outside of the class
void student::getDetails(void){
cout << "Enter name: " ;
cin >> name;
cout << "Enter roll number: ";
cin >> rollNo;
cout << "Enter total marks outof 500: ";
cin >> total;
perc=(float)total/500*100;
}
//member function definition, outside of the class
void student::putDetails(void) {
cout << "Student details:\n";
cout << "Name:"<< name << ",Roll Number:" << rollNo << ",Total:" << total << ",Percentage:" << perc;
}
int main()
{
student std[MAX]; //array of objects creation
int n,loop;
cout << "Enter total number of students: ";
cin >> n;
for(loop=0;loop< n; loop++){
cout << "Enter details of student " << loop+1 << ":\n";
std[loop].getDetails();
}
cout << endl;
for(loop=0;loop< n; loop++) {
cout << "Details of student " << (loop+1) << ":\n";
std[loop].putDetails();
}
return 0;
}
Its very basic code and works fine and I am able to give inputs and print the output.
Now I want to add new Student object at runtime using Dynamic memory allocation and want to add that object in the existing array of object (So that I can get the highest, lowest marks of any student)
I know I need to use new operator for this.
But I am not sure what could be the best way to write this solution.
Any help will be highly appreciated.
Thanks!
IMO, The best way to do this using dynamic memory is by using std::unique_ptr or std::shared_ptr (it actually depends on the requirement).
Here is one example of usage of unique_ptr:
using StudentPtr = std::unique_ptr<student>;
int main() {
std::vector<StudentPtr> studentDetails;
int n;
cout << "Enter the number of students: ";
cin >> n;
studentDetails.resize(n);
for (auto &s: studentDetails) {
s = StudentPtr(new student);
s->getDetails();
}
return 0;
}
For getting minimum and maximum, you may use min_element and max_element provided by STL respectively.

User can't put input for second variable. C++

Whenever I run the program, I can only input a value for the first variable, employeeName, but when I hit enter after I input the value, I get a "press any key to continue" prompt. Can somebody please tell me what's wrong?
// Calculate how many hours an employee has worked
#include <iostream>
using namespace std;
int main()
{
//Declare Named Constants
int const HOURS_IN_WORK_WEEK = 40;
int const HOURS_IN_WORK_DAY = 8;
//Declare Variables
int employeeName;
int hoursWorked;
int totalWeeksWorked;
int leftoverFromWeeks;
int totalDaysWorked;
int leftoverFromDays;
int totalHoursWorked;
//Get Input
cout << "enter employee name: ";
cin >> employeeName;
cout << "Enter total hours worked: ";
cin >> hoursWorked;
//calculate total weeks, days, and hours worked
totalWeeksWorked = hoursWorked / HOURS_IN_WORK_WEEK;
leftoverFromWeeks = hoursWorked % HOURS_IN_WORK_WEEK;
totalDaysWorked = leftoverFromWeeks / HOURS_IN_WORK_DAY;
leftoverFromDays = leftoverFromWeeks % HOURS_IN_WORK_DAY;
totalHoursWorked = leftoverFromDays;
//Output
cout << employeeName << "worked " << hoursWorked << "hours or " << totalWeeksWorked << "week(s), " << totalDaysWorked << "day(s), and " << totalHoursWorked << "hours.";
system("pause");
}//End Main
What I presume happened is that you unknowingly entered a string for the employee's name. However, if you look at your declaration:
int employeeName;
The type of the variable is int! Change this to std::string and use getline to read a space separated full name (std::cin will stop reading at whitespace, meaning the rest of the input will be attempted to be stored in an int, leading to the same behavior that happened with the first variable).
The input code would now change to:
cout << "enter employee name: ";
getline(cin, employeeName);
Also, on a side note, you should read why using system("pause") is not a good idea (Although it doesn't really matter for such a small program, it is useful knowledge).

Trouble with dynamic arrays and finding the sum of values

So as I explained in the title i'm having trouble trying to get the sum of an array. I've just now learned how to create dynamic arrays and I did some searching on how to calculate the sum. I don't believe I fully understand what is going on to calculate the sum.
// Final Grade Calculator
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <string>
using namespace std;
int main(){
double minor, quiz, major;
int minorG, quizG, majorG;
minorG = 0;
cout << "Final Grade Calculator" << endl;
cout << "Input minor grade weight percent." << endl;
cin >>minor;
cout << "Input quiz grade weight percent." << endl;
cin >>quiz;
cout << "Input major grade weight percent." << endl;
cin >>major;
// Three grade categories
minor = minor/100;
quiz = quiz/100;
major = major/100;
for(int i = 1; i <=10; i++){
cout << "Input a minor grade. (Max=10)" << endl;
cin >>minorG;
int *minorGA = new int[minorG];
minorG+= minorGA[minorG];
cout << "Currently: " << i << " Grade(s)." <<endl;
}
cout << "Minor Sum: " << minorG << endl;
return 0;
}
This is what I have so far and the trouble I am having is within the for loop which is where my array is and where I am trying to get the sum of it. When I compile and run I get a sum of 138,427. Any help would be greatly appreciated!
I think you're over-complicating things with dynamic arrays. I'll explain what you're doing, and try to provide help for what I think you're trying to do.
In your code int* minorGA = new int[minorG]; you are allocating memory for minorG amount of ints. There are two problems here:
You are accessing an element outside of the memory you allocated. When you allocate 10 elements, you can access elements 0-9. Trying to access 10 is undefined behaviour (you are trying to access parts of memory that could contain anything).
The values stored in this array are just whatever is in memory, so when you are attempting to increment minorG by the amount of one of these, it's just whatever is in memory at the time.
A separate problem is that you are not deallocating the memory, but some might argue that it isn't really a problem.
You should just be able to have the following to perform what I think you're trying to do:
for (int i = 0; i < 10; ++i)
{
int inputtedNumber = 0;
cout << "Enter a number" << endl;
cin >> inputtedNumber;
// add that number to some tally:
finalTally += inputtedNumber;
}
Or if you are trying to store the elements in an array, you can use the following:
const int maxElements = 10;
int grades[maxElements] = {}; // this will construct all elements with 0. Without this, the elements may contain any number.
for (int i = 0; i < maxElements; ++i)
{
int inputtedNumber = 0;
cout << "Enter a number" << endl;
cin >> inputtedNumber;
// Store the number
grades[i] = inputtedNumber;
}
In saying that, it will be better to use std::vector (knows its size, handles memory for you, can grow):
std::vector<int> grades;
// Allow the user to enter as many numbers as they'd like
for (;;)
{
int input = 0;
cout << "Enter a number" endl;
cin >> input;
// Store the number. Will continue to grow
grades.push_back(input);
}

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

So for my project I have to...
Create a structure using the format: struct PERSON{string name; int age; float gpa;};
Ask the user to enter the number of records they would like to enter.
Create a dynamic array p of PERSON type to be able to hold all records in part 2
Read data into array p in part 2
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.
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.
The std::getline() function is "misbehaving" in relation to your intentions because there is (I think) a new line character left in the stream input queue.
You can discard such characters by using the following command cin.sync().
Why does this happen? Because operator>> does not read whitespaces, but std::getline() does, so when the cin >> count; statement is executed and you press enter, the new line character (from pressing enter) is left in the stream input queue, which is automatically read by std::getline() upon execution.
There are other functions that can accomplish this and perhaps someone more informed can tell us which is the best choice.
Here is a fixed version:
#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;
}
Notes:
You do not need to check if Person* p is nullptr because the new operator will throw a std::bad_alloc exception if it fails to allocate enough memory. Consider wrapping that memory allocation in a try catch block if you really want to.

C++ Return Statement Not Working

I've just started learning C++ and i've been having problems implementing return statements. I've been easily able to pass data to a new function but I am having no joy in getting it to return.
I've written the simplest code I could think of to try and debug what is going wrong and I still can't work it out. I am NOT trying to pass too many return values and I have a correct function type to pass too. It just doesn't seem to work?
I am using Xcode 4 on a Macbook Pro:
#include <iostream>
using namespace std;
int agenext (int age);
int main ()
{ int age;
cout << "What's Your Age? \n";
cin >> age;
cout << "Your Current Age: " << age;
agenext(age);
cout << endl << "A year has passed your new age is: ";
cout << age;
}
int agenext (int x)
{
x++;
cout << endl << "Your Next Birthday is " << x;
return x;
}
It's returning perfectly find. You just aren't setting the value it returns to anything.
age = agenext(age)
Is what you are looking for, or you could pass a pointer or a reference to the age variable.
returning is only half the battle, the other half is assigning that value to something. Consider changing:
agenext(age);
to
age = agenext(age);
Both the existing answers are correct; if you want to return a value, it needs to be assigned somewhere.
For future reference, you can also do what you want by skipping the return and passing age by reference instead of value.
void agenext (int &x)
{
x++;
cout << endl << "Your Next Birthday is " << x;
/* the value change WILL show up in the calling function */
}
In your main function, you need another variable to hold the new age that is return from the age function.
int main ()
{ int age, newAge;
cout << "What's Your Age? \n";
cin >> age;
cout << "Your Current Age: " << age;
newAge = agenext(age);
cout << endl << "A year has passed your new age is: ";
cout << newAge;
return 0;
}