Getting average age of students and youngest student's name - c++

I'm having some trouble with getting the average age of all students including getting the youngest student's name outputted. The output is supposed to come from a function call I wrote called ageCalc(...).
main.cpp
#include <iostream>
#include <fstream>
#include <iomanip>
#include "Student1.h"
#include "Student2.h"
#include "ageCalc.h"
using namespace std;
const int SIZE = 100;
int main()
{
ifstream inFile;
inFile.open("C:\\COMSC200\\a2data.input", ios::in|ios::binary);
// Open the input file – if it fails to open, display an error message and terminate
if(!inFile.is_open())
{
cout << "Unable to open file!";
return 1;
}
else
{
cout << "File successfully open!\n\n";
}
// Use a pointer array to manage all the created student variables.
Student1 **ptrArr = new Student1 *[SIZE];
Student1 s;
int total = 0;
// read the first input record
inFile.read(reinterpret_cast<char *> (&s), sizeof(s));
while(!inFile.eof())
{
// dynamically allocate space for new student variable
ptrArr[total] = new Student1;
// populate the student variable from the input
*ptrArr[total] = s;
total++;
// read the next input record
inFile.read(reinterpret_cast<char *> (&s), sizeof(s));
}
Student2 *st = new Student2[SIZE];
for(int i = 0; ptrArr[i]; i++)
{
for(char fn: ptrArr[i]->first_name)
st[i].fn += fn;
st[i].mi = ptrArr[i]->middle_int[0];
for(char ln: ptrArr[i]->last_name)
st[i].ln += ln;
st[i].cc = ptrArr[i]->campus_code;
for(char sID: ptrArr[i]->student_ID)
st[i].sID += sID;
st[i].age = atoi(ptrArr[i]->age);
}
cout << "First Name" << setw(9)
<< "MI" << setw(15)
<< "Last Name" << setw(17)
<< "Campus Code" << setw(16)
<< "Student ID" << setw(15)
<< "Age" << endl;
cout << "===================================================================================" << endl;
for(int j = 0; st[j].age != 0; j++)
{
cout << st[j].fn << setw(8);
cout << st[j].mi << " ";
cout << st[j].ln << setw(2);
cout << st[j].cc << " ";
cout << st[j].sID << setw(16);
cout << st[j].age << " " << endl;
}
Student2 *y;
int avg = ageCalc(&st, y);
cout << "Average student age is: " << avg << " years." << endl;
cout << "Youngest student is: " << arr[i]->fn << " " << arr[i]->mi << " " << arr[i]->ln << endl;
for(int x = 0; ptrArr[x]; x++)
{
delete ptrArr[x];
}
delete [] st;
inFile.close();
return 0;
}
ageCalc.cpp
#include "Student2.h"
using namespace std;
int ageCalc(Student2 *arr[], Student2 *&y)
{
int i = 0, sum = 0, index = 0, avg;
while(arr[i] != nullptr)
{
sum = arr[i]->age + sum;
i++;
if(arr[i]->age < arr[index]->age)
{
index = i;
}
}
y = arr[index];
avg = sum / i;
return avg;
}
Student1.h
#ifndef STUDENT1_H_
#define STUDENT1_H_
#include <iostream>
using namespace std;
struct Student1
{
char first_name[10];
char middle_int[10];
char last_name[20];
char campus_code;
char student_ID[8];
char age[3];
};
#endif
Student2.h
#ifndef STUDENT2_H_
#define STUDENT2_H_
#include <iostream>
#include <string>
using namespace std;
struct Student2
{
string fn;
char mi;
string ln;
char cc;
string sID;
short int age;
};
#endif
ageCalc.h
#ifndef AGECALC_H_
#define AGECALC_H_
#include "Student2.h"
int ageCalc(Student2 *[], Student2 *&);
#endif

Related

C++ Read Value from a pointer to struct including the target struct in an array

I am new to c++ and trying to make an atm. It consits of one file reading user data from files and a main file. Everytime I try to read the output of the returned pointer to the array of structs, where the data is stored, I get strange data. I think there is a problem when assigning strings to the first struct, because when I tried with test values (third file) it worked.
Edit:
I can read out integeres from the strcut, but I have problems with strings.
Here is the code
users.cpp (Creates the struct, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
void print_user_vars(User *user){
cout << "Id: " << user->id << "\nFirstname: " << user->firstname << "\nName: " << user->name << "\nAge: " << user->age << "\nPIN: " << user->pin << endl;
}
int get_usercount(string path){
int usercount = 0;
ifstream file;
string line;
file.open(path, ios::binary | ios::in);
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find("}") != STRING_ERROR){
usercount++;
}
}
file.close();
return usercount;
}
container * get_users(string path){
const int usercount = get_usercount(path);
ifstream file;
string line;
User users[usercount];
const char *values[5] = {"id", "firstname", "name", "age", "pin"};
file.open(path, ios::binary | ios::in);
User proto_user;
int user_num = 0;
while(true){
getline(file , line);
if(file.fail())
break;
if(line.find(":") != STRING_ERROR){
for(int i = 0; i < 5; i++){
if(line.find(values[i]) != STRING_ERROR){
string value;
for(int v = 0; v < line.length(); v++){
if(v > line.find_first_of(":")){
value += line[v];
}
}
if(values[i] == "id"){
proto_user.id = stoi(value);
}
else if(values[i] == "firstname"){
proto_user.firstname = value;
}
else if(values[i] == "name"){
proto_user.name = value;
}
else if(values[i] == "age"){
proto_user.age = stoi(value);
}
else if(values[i] == "pin"){
proto_user.pin = stoi(value);
}
break;
}
}
}
else if(line.find("}") != STRING_ERROR){
//print_user_vars(&proto_user);
users[user_num++] = proto_user;
//cout << "Added user at " << user_num << endl;
}
//cout << line << endl;
}
for(int i = 0; i < user_num; i++){
//cout << "\nUSER: " << i + 1 << endl;
//print_user_vars(&users[i]);
}
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
print_user_vars(&con.users[0]);
return &con;
}
main.cpp (Calls the function)
#include <iostream>
#include "includes/users.h"
using namespace std;
int main(void){
string wasd = "w";
int id;
int pin;
cout << "\n Welcome\n\n ID\n>>> ";
cin >> id;
cout << " PIN\n>>> ";
cin >> pin;
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
//Functionality
return 0;
}
Simpler.cpp (Just like users.cpp, but with test values, included in main.cpp)
#include <fstream>
#include <string>
#include <iostream>
#define STRING_ERROR 4294967295
#define MAX_USERS 100000
using namespace std;
struct user
{
int id;
string firstname;
string name;
int age;
int pin;
};
struct user_container{
int size;
user users [MAX_USERS];
};
typedef struct user User;
typedef struct user_container container;
container * get_users(string path){
const int usercount = 2;
User users[usercount];
users[0].age = 59;
users[0].firstname = "Peter";
users[0].name = "Bremer";
users[0].id = 456878;
users[0].pin = 1234;
users[1].age = 8;
users[1].firstname = "a";
users[1].name = "b";
users[1].id = 456;
users[1].pin = 1111;
static container con;
con.size = usercount;
for(int i = 0; i < usercount; i++){
if(i <= MAX_USERS){
// con.users[i] = users[i] didnt work, but this does
con.users[i].firstname = users[i].firstname;
con.users[i].age = users[i].age;
con.users[i].name = users[i].name;
con.users[i].pin = users[i].pin;
con.users[i].id = users[i].id;
}
}
cout << "Usercount " << usercount << endl;
return &con;
}
int main(void){
container *con = get_users("users");
int size = con->size;
cout << "Age: " << con->users[0].age << ", PIN: " << con->users[0].pin << ", Firstname: " << con->users[0].firstname << ", Name: "
<< con->users[0].name << ", ID: " << con->users[0].id << endl;
return 0;
}
Not really the answer you are looking for:
Avoid using typedef when you don't need it. Just name your struct User, it will be available under that name without writing struct User.
And for your container, just use one of the STL containers. std::vector<User> would be a good start. This also removes the need for MAX_USERS.
struct User
{
int id;
std::string firstname;
std::string name;
int age;
int pin;
};
typedef std::vector<User> container;
With the three interfaces in user.cpp you can now just use
void print_user_vars(const User& user);
int get_usercount(const std::string& path);
container get_users(const std::string& path);
and thus get rid of the static container con; in get_users.
With a std::vector I no longer see a need for the get_usercount function.
And instead of macros go for constants (and remove magic numbers):
auto const STRING_ERROR = std::string::npos;
(Though I don't agree with the name STRING_ERROR. It's more a STRING_NOT_FOUND.)
Cleanup of print_user_vars after signature change:
void print_user_vars(const User& user)
{
std::cout << "Id: " << user.id << "\nFirstname: " << user.firstname
<< "\nName: " << user.name << "\nAge: " << user.age
<< "\nPIN: " << user.pin << std::endl;
}
And getting some inspiration from get_usercount (a method I don't believe you need):
int get_usercount(const std::string& path)
{
int usercount = 0;
std::ifstream file(path, std::ios_base::binary);
std::string line;
while(std::getline(file, line))
{
if(line.find("}") != STRING_ERROR)
{
usercount++;
}
}
return usercount;
}
This line in get_users is NOT C++. (It's part of the C99 standard):
User users[usercount];
And as #bruno points out:
else if(values[i] == "name"){
does not work. Consider
else if(std::strcmp(values[i], "name") == 0){

Function return nothing with multiple files?

When I run one file, it works perfectly. Then I separate 3 file: header, main, function from that file. It aslo works but return nothing. Here the code:
File Header: printStudent.h
//Header.h
#ifndef PRINTSTUDENT_H_INCLUDED
#define PRINTSTUDENT_H_INCLUDED
void read ();
#endif
File Function: readFileCSV.cpp . It read and print from my .csv file
#include <iostream>
#include <fstream>
#include <iomanip>
#include <string.h>
#include <algorithm>
#define student 1000
using namespace std;
void read (){
ifstream readFileCSV;
readFileCSV.open("studentEn.csv");
if(!readFileCSV.is_open()) {cout << "ERROR: File can't be opened or it doesn't exist" << endl;};
string aMSSV[student];
string aname[student];
string abirthDay[student];
string aaddress[student];
string MSSV;
string name;
string birthDay;
string address;
int countStudent = 0;
while(readFileCSV.good()) {
getline(readFileCSV, MSSV, ',');
getline(readFileCSV, name, ',');
getline(readFileCSV, birthDay, ',');
getline(readFileCSV, address, '\n');
int lengthAddress = address.length();
char charAddress[lengthAddress];
strcpy(charAddress, address.c_str());
char newCharAddress[lengthAddress-2];
for(int i = 0 ; i < lengthAddress-2 ; i++){
newCharAddress[i] = charAddress[i+1];};
string address(newCharAddress, lengthAddress - 2);
aMSSV[countStudent] = MSSV;
aname[countStudent] = name;
abirthDay[countStudent] = birthDay;
aaddress[countStudent] = address;
countStudent ++;
};
countStudent = countStudent - 1;
cout << "..................................................STUDENT..........................................................." << endl;
cout << setw(5) << left << "STT";
cout << setw(25) << left << "MSSV";
cout << setw(25) << left << "Name";
cout << setw(25) << left << "Date of Birth";
cout << left << "Address";
cout << endl;
cout << "...................................................................................................................." << endl;
for(int i = 0 ; i < countStudent ; i++){
cout << setw(5) << left << i + 1;
cout << setw(25) << left << aMSSV[i];
cout << setw(25) << left << aname[i];
cout << setw(25) << left << abirthDay[i];
cout << left << aaddress[i];
cout << endl;
}
readFileCSV.close();
}
File main:
#include <iostream>
#include "printStudent.h"
using namespace std;
int main(){
void read ();
return 0;
}
Help me why it's return nothing and give me a solution how can i make it works? Thanks!
int main(){
void read ();
return 0;
}
It is a function declaration in main a.k.a. forward declaration. Any expression that starts with a type or void is a declaration. It is a local declaration, thus it doesn't conflict with the globally declared function read.
To call the function do it so
int main(){
read ();
return 0;
}

Why the result doesn't write on the text file?

I have created csis.txt file but when I look up, it is empty. Could anyone teach me why the file is created without results? Here are my codes:
//ZipCode.cpp
#include <iostream>
#include "ZipCode.h"
#include <fstream>
#include <string>
#include <math.h>
#include <sstream>
using namespace std;
extern ofstream csis;
ZipCode::ZipCode(int _zipcode) {
zipcode = _zipcode;
}
ZipCode::ZipCode(const char *barcode) {
int value;
zipcode = 0;
for (int i = 0; i<5; i++) //repeat x5 positions
{
value = 0;
for (int j = 0;j<5;j++) //repeat x5 letters
{
if (barcode[i * 5 + j] == '1') //if '1' is letter
{
value += base[j]; //add position(5)
}
}
if (value >10)
{
value = 0;
}
zipcode = zipcode * 10 + value;
}
}
string ZipCode::getBarCode()
{
char barcode[26] = "";
int zip = zipcode;
int value;
for (int i = 0;i<5;i++) //repeat x5 positions
{
for (int j = 0;j<4;j++) //repeat x4(last barcode position 0)
{
//10^position * barcode position goes to value
value = (int)(pow(10.0, 4 - i) * base[j]);
if (zip / value)
{
barcode[i * 5 + j] = '1'; //set as '1'
zip = zip % value;//zip is now remainder
}
else
{
barcode[i * 5 + j] = '0'; //set as '0'
}
}
barcode[i * 5 + 4] = '0';
}
return barcode;
}
int ZipCode::getZipCode()
{
return zipcode;
}
//ZipCode.h
#ifndef _ZIPCODE_H
#define _ZIPCODE_H
using namespace std;
class ZipCode {
private:
int zipcode;
int base[5] = { 7,4,2,1,0 }; //barcode positions
public:
ZipCode(int _zipcode); //convert zipcode to barcode
ZipCode(const char *barcode); //convert barcode to zipcode
string getBarCode(); //get barcode
int getZipCode(); //get zipcode
};
#endif
//main.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include "ZipCode.h"
#include <sstream>
using namespace std;
ofstream csis;
int main()
{
csis.open("csis.txt");
ZipCode zip1(99504);
ZipCode zip2(12345);
ZipCode zip3(67890);
ZipCode zip4("100101010011100001100110001");
ZipCode zip5("110100001011100001100010011");
ZipCode zip6("100011000110101000011100101");
cout << "Digits" << " " << "Bar Code" << endl;
cout << zip1.getZipCode() << setw(35) << zip1.getBarCode() << endl;
cout << zip2.getZipCode() << setw(35) << zip2.getBarCode() << endl;
cout << zip3.getZipCode() << setw(35) << zip3.getBarCode() << endl;
cout << endl;
cout << zip4.getZipCode() << setw(35) << zip4.getBarCode() << endl;
cout << zip5.getZipCode() << setw(35) << zip5.getBarCode() << endl;
cout << zip6.getZipCode() << setw(35) << zip6.getBarCode() << endl;
return 0;
}
You probably want to write the file rather than std::cout.
Just replace :
cout << "Digits" << " " << "Bar Code" << endl;
by
csis << "Digits" << " " << "Bar Code" << endl;`
And repeat that for every line...

Doesn't seem to be working using ifstream fin; and fin.open("filename");

I have a program for my class to read in information from a file, as an array, using a function and I've coded this the same way I did for classes last year and I'm not sure why it's not working. I'm supposed to also add more to this but wanted to try to figure out why it's not working with what it already has.
I don't think it's reading the file in because nothing comes out on the output file or the window that pops up when it runs.
#include <iostream>
#include <fstream>
#include <string>
#include <iomanip>
using namespace std;
const int maxs = 50;
struct stype
{
int crn;
string name;
int crhrs;
int numstu;
int stucrhrs;
string prof;
};
stype initrec = { 0.0, "course", 0.0, 0.0, 0.0, "prof" };
void initem(stype p[], int &numc)
{
int i;
for (i = 0; i < maxs; i++) p[i] = initrec;
numc = 0;
}
void readem(stype p[], int &numc)
{
int i = 0;
ifstream fin;
fin.open("program1.dat");
while (!fin.eof())
{
fin >> p[i].crn >> p[i].name >> p[i].crhrs >> p[i].numstu >> p[i].stucrhrs >> p[i].prof;
i++;
}
numc = i;
cout << "readem reached " << endl;
}
void printem(stype p[], int &numc, ofstream &fout)
{
int i;
for (i = 0; i < numc; i++)
{
fout << left << setw(10) << p[i].crn << left << setw(15) << p[i].name << left
<< setw(15) << p[i].numstu << right << setw(2) << p[i].crhrs << right <<
setw(2) << p[i].stucrhrs << right << setw(10) << p[i].prof << endl;
}
cout << "printem reached " << endl;
}
void swapem(stype &a, stype &b)
{
stype temp;
temp = a;
a = b;
b = temp;
cout << "swapem reached " << endl;
}
void sortem()
{
cout << "sortem reached " << endl;
}
void getaverage()
{
cout << "getaverage reached " << endl;
}
void credithours()
{
cout << "Credit hours totalled. " << endl;
}
void main()
{
int crn[maxs], crhrs[maxs], stucrhrs[maxs];
string name[maxs], prof[maxs];
stype p[maxs];
int numc;
ofstream fout;
fout.open("program1.out");
fout.setf(ios::fixed);
fout.precision(2);
initem(p, numc);
readem(p, numc);
printem(p, numc, fout);
getaverage();
sortem();
printem(p, numc, fout);
system("pause");
}

Trying to make string array passed through methods C++

I'm trying to read names and ages from user, until user inputs "stop". Then just print all these values. Please help me , I'm just the beginner in C++
// Pass.cpp
// Reading names and ages from user and outputting them
#include <iostream>
#include <iomanip>
#include <cstring>
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::strcmp;
char** larger(char** arr);
int* larger(int* arr);
void read_data(char*** names, int** ages);
void print_data(char*** names, int** ages);
int main()
{
char** names = new char*[5];
char*** p_names = &names;
int* ages = new int[5];
int** p_ages = &ages;
read_data(p_names,p_ages);
print_data(p_names,p_ages);
}
void read_data(char*** names, int** ages)
{
const char* sent = "stop";
const int MAX = 15;
int count = 0;
char UI[MAX];
cout << "Enter names and ages."
<< endl << "Maximum length of name is " << MAX
<< endl << "When stop enter \"" << sent << "\".";
while (true)
{
cout << endl << "Name: ";
cin.getline(UI,MAX,'\n');
if (!strcmp(UI, sent))
break;
if (count + 1 > sizeof (&ages) / sizeof (&ages[0]))
{
*names = larger(*names);
*ages = larger(*ages);
}
*names[count] = UI;
cout << endl << "Age: ";
cin >> *ages[count++];
}
}
void print_data(char*** names, int** ages)
{
for (int i = 0; i < sizeof(*ages) / sizeof(*ages[0]);i++)
{
cout << endl << setw(10) << "Name: " << *names[i]
<< setw(10) << "Age: " << *ages[i];
}
}
char** larger(char** names)
{
const int size = sizeof(names) / sizeof(*names);
char** new_arr = new char*[2*size];
for (int i = 0; i < size; i++)
new_arr[i] = names[i];
return new_arr;
}
int* larger(int* ages)
{
const int size = sizeof(ages) / sizeof(*ages);
int* new_arr = new int[2 * size];
for (int i = 0; i < size; i++)
new_arr[i] = ages[i];
return new_arr;
}
You are really over complicating things.
Given the original problem:
Write a program that reads a number (an integer) and a name (less than
15 characters) from the keyboard. Design the program so that the data
is done in one function, and the output in another. Store the data in
the main() function. The program should end when zero is entered for
the number. Think about how you are going to pass the data between
functions
The problem wants you to think about passing parameters to functions. A simple solution would be:
#include "stdafx.h"
#include <iostream>
#include <iomanip>
using namespace std;
// Pass in a char array and an integer reference.
// These values will be modified in the function
void read_data(char name[], int& age)
{
cout << endl << "Age: ";
cin >> age;
cin.ignore();
cout << endl << "Name: ";
cin.getline(name, 16);
}
// Pass a const array and an int value
// These values will not be modified
void print_data(char const *name, int age)
{
cout << endl << setw(10) << "Name: " << name
<< setw(10) << "Age: " << age;
}
int main()
{
char name[16];
int age;
cout << "Enter names and ages."
<< endl << "Enter 0 age to quit.";
do {
read_data(name, age);
print_data(name, age);
} while (0 != age)
}
EDIT: Modified per user3290289's comment
EDIT2: Storing data in an array
// Simplify by storing data in a struct (so we don't have to manage 2 arrays)
struct Person {
char name[16];
int age;
};
// Returns how many People were input
int read_data(Person*& arr)
{
int block = 10; // How many persons to allocate at a time
arr = NULL;
int arr_size = 0;
int index = 0;
while (true) {
if (index == arr_size) {
arr_size += block;
arr = (Person *)realloc(arr, arr_size * sizeof(Person)); // Reallocation
// Should check for error here!
}
cout << endl << "Age: ";
cin >> arr[index].age;
cin.ignore();
if (0 == arr[index].age) {
return index;
}
cout << endl << "Name: ";
cin.getline(arr[index++].name, 16);
}
}
void print_data(Person *arr, int count)
{
for (int i = 0; i < count; i++) {
cout << endl << setw(10) << "Name: " << arr[i].name
<< setw(10) << "Age: " << arr[i].age;
}
}
int main()
{
Person *arr;
int count = read_data(arr);
print_data(arr, count);
free(arr); // Free the memory
}
try this:
#include <iostream>
#include <iomanip>
#include <vector>
#include <sstream>
using std::cout;
using std::cin;
using std::endl;
using std::setw;
using std::strcmp;
void read_data(std::vector<std::string> &names, std::vector<int> &ages);
void print_data(std::vector<std::string> &names, std::vector<int> &ages);
int main()
{
std::vector<std::string> names;
std::vector<int> ages;
read_data(names, ages);
print_data(names, ages);
}
void read_data(std::vector<std::string> &names, std::vector<int> &ages)
{
const char* sent = "stop";
cout << "Enter names and ages."
<< endl << "When stop enter \"" << sent << "\".";
while (true)
{
std::string input;
cout << endl << "Name: ";
std::getline(cin, input);
if (!strcmp(input.c_str(), sent))
break;
names.push_back(input);
cout << endl << "Age: ";
std::string age;
std::getline(cin, age);
ages.push_back(atoi(age.c_str()));
}
}
void print_data(std::vector<std::string> &names, std::vector<int> &ages)
{
for (int i = 0; i < names.capacity() ; i++)
{
cout << endl << setw(10) << "Name: " << names.at(i)
<< setw(10) << "Age: " << ages.at(i);
}
}
One problem I see is this if statement:
if (count + 1 > sizeof (&ages) / sizeof (&ages[0]))
&ages is the address of an int**, a pointer, and so it's size is 8 (usually) as that is the size of a pointer type. The function does not know the size of the array, sizeof will only return the correct answer when ages is declared in the same scope.
sizeof(&ages) / sizeof(&ages[0])
will always return 1
I believe one natural solution about this problem is as follows:
create a "std::map" instance. Here std::map would sort the elements according to the age. Here my assumption is after storing the data into the container, you would like to find about a particular student age/smallest/largest and all various manipulation with data.Just storing and printing the data does not make much sense in general.
create a "std::pair" and take the both input from the user into the std::pair "first" and "second" member respectively. Now you can insert this "std::pair" instance value into the above "std::map" object.
While printing, you can now fetch the each element of "std::map" in the form of "std::pair" and then you can display pair "first" and "second" part respectively.