it's my first time working with classes and headers in C++ and I ran into these errors after putting together my code
function does not take 1 arguments // For all 4 functions
overloaded member function not found in 'Animals' // Also for all 4 fncs
syntax error: identifier 'fstream' // header file error
The program is designed to read and write to a file, while also doing searches and being able to manipulate the binary file. I'm pretty sure the error is in my declarations somewhere but I can't figure it out myself; any help is appreciated.
main.cpp
#include <iostream>
#include<iomanip>
#include <fstream>
#include"animals.h"
using namespace std;
int main()
{
Animals nA;
fstream animalFile;
int choice;
cout << setprecision(2) << fixed;
do
{
// Display the menu.
cout << "\n1. Add a new animal\n";
cout << "2. Remove an animal\n";
cout << "3. Search and display a animal\n";
cout << "4. Display all animals\n";
cout << "5. Exit\n";
do
{
cout << "Enter your choice (1-5): ";
cin >> choice;
} while (choice < 1 || choice > 5);
// Process the selection.
switch (choice)
{
// Choice 1 is to add an animal
case 1:
nA.addAnimal(animalFile);
break;
// Choice 2 is to remove an animal
case 2:
nA.removeAnimal(animalFile);
break;
// Choice 3 is to search and display 1 animal
case 3:
nA.searchAnimal(animalFile);
break;
// Choice 4 is to display all animals
case 4:
nA.displayAnimal(animalFile);
}
} while (choice != 5);
system("pause");
return 0;
}
Animals.h
#ifndef ANIMALS_H
#define ANIMALS_H
#include <string>
#include <iostream>
#include <fstream>
class Animals
{
private :
std::string name;
int age;
public :
//Default constructor
Animals();
//Create an animal object
Animals(std::string name, int age);
//Add a new animal record
void addAnimal(fstream &d);
//Remove an animal record
void removeAnimal(fstream &d);
//Displays an animal through a search
void searchAnimal(fstream &d);
//Display ALL animals
void displayAnimal(fstream &d);
};
#endif
Animals.cpp
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include "Animals.h"
using namespace std;
Animals::Animals()
{
name = "NULL";
age = 0;
}
Animals::Animals(std::string name, int age)
{
Animals *newAnimal = new Animals;
}
void Animals::addAnimal(fstream &d)
{
string userName;
int userAge = 0;
int stringRemainder;
int record;
const int RECORD_SIZE = 40;
//Collecting user input
do
{
std::cout << "Please enter your animal name: ";
std::cin >> userName;
std::cout << "\n";
} while (sizeof(userName) > 30);
do
{
std::cout << "Please enter your animal age: ";
std::cin >> userAge;
std::cout << "\n";
} while (userAge <= 0 || !isdigit(userAge));
//Fixing length of string
stringRemainder = 30 - sizeof(userName);
//Finds record number based on position
record = (d.tellg() % RECORD_SIZE) + 1;
//Writing to file
d.close();
d.open("animals.txt", std::ios_base::app | ios::binary);
d << record << "";
d << userName;
for (int i = 0; i < stringRemainder; i++)
{
d << "";
}
d << userAge << "\n";
d.close();
}
void Animals::removeAnimal(fstream &d)
{
int recordNumber = 0;
const int RECORD_SIZE = 40;
char recordBuffer[RECORD_SIZE];
d.open("animals.txt", ios::out| ios::in |ios::binary);
//Collecting user input
do
{
cout << "Enter the record of the animal to be removed: ";
cin >> recordNumber;
} while (recordNumber <= 0 || !isdigit(recordNumber));
// move pointer to desired position, and overwrite!
d.seekp((recordNumber-1) * RECORD_SIZE);
d.write(recordBuffer, RECORD_SIZE);
d.close();
}
void Animals::searchAnimal(fstream &d)
{
int userRecord = 0;
char displayRecord[2];
const int RECORD_SIZE = 40;
char fileOutput[RECORD_SIZE];
string displayInfo;
char displayName[RECORD_SIZE];
char displayAge[2];
int i,k;
int j = 0;
d.open("animals.txt", ios::out | ios::binary);
//Getting user input
do
{
cout << "Enter the record of the animal to be diplayed: ";
cin >> userRecord;
} while (userRecord <= 0 || !isdigit(userRecord));
//Moving pointer position to searched value
d.seekp((userRecord - 1) * RECORD_SIZE);
//Gets data from file, stores into displayInfo
getline(d, displayInfo);
d.close();
//Entering file data into diplay variables,
//value 'i' increments through entire displayInfo array
for (i = 0; isdigit(displayInfo[i]); i++)
{
displayRecord[i] = displayInfo[i];
}
//New sentinel for ONLY string cap including buffer
k = i + 30;
for (i; i < k; i++)
{
displayName[j] = displayInfo[i];
j++;
}
//Finishes off last of the displayInfo array
for (i; i < sizeof(displayInfo); i++) {
displayAge[i] = displayInfo[i];
}
//Prints the data for user
cout << "For record number: " << userRecord << "\n";
cout << "Animal: ";
for (int i = 0; i < strlen(displayName); i++)
{
cout << displayName[i];
}
cout << "\n";
cout << "Age: ";
for (int i = 0; i < strlen(displayAge); i++)
{
cout << displayAge[i];
}
cout << "\n";
}
//Mostly copied from above function, displays ALL animals
void Animals::displayAnimal(fstream &d)
{
int userRecord = 0;
char displayRecord[2];
const int RECORD_SIZE = 40;
char fileOutput[RECORD_SIZE];
string displayInfo;
char displayName[RECORD_SIZE];
char displayAge[2];
int numberOfRecords;
int i, k;
int j = 0;
int q = 0;
d.open("animals.txt", ios::out | ios::in | ios::binary);
d.seekg(0, d.end);
numberOfRecords = d.tellg() % RECORD_SIZE;
d.seekg(0, d.beg);
for (int q; q < numberOfRecords; q++) {
d.seekp(q * RECORD_SIZE);
//Gets data from file, stores into displayInfo
getline(d, displayInfo);
//Entering file data into diplay variables,
//value 'i' increments through entire displayInfo array
for (i = 0; isdigit(displayInfo[i]); i++)
{
displayRecord[i] = displayInfo[i];
}
//New sentinel for ONLY string cap including buffer
k = i + 30;
for (i; i < k; i++)
{
displayName[j] = displayInfo[i];
j++;
}
//Finishes off last of the displayInfo array
for (i; i < sizeof(displayInfo); i++) {
displayAge[i] = displayInfo[i];
}
//Prints the data for user
cout << "For record number: " << userRecord << "\n";
cout << "Animal: ";
for (int i = 0; i < strlen(displayName); i++)
{
cout << displayName[i];
}
cout << "\n";
cout << "Age: ";
for (int i = 0; i < strlen(displayAge); i++)
{
cout << displayAge[i];
}
cout << "\n\n";
}
d.close();
}
The headers <iostream> and <fstream> bring their symbols into the std namespace, so any reference to these symbols in the header need to be fully qualified; e.g. std::fstream. Also, you might want to include <iosfwd> in your headers instead - this minimizes the compiler time cost of importing the header, assuming that the header only uses reference to the symbols mentioned in the iostream header.
You should use ifstream for read files and ofstream for write files.
And in header file, you should use std::ifstream & d or std::ofstream & d in argument of 4 functions.
Related
I just need to know how to have size, index, and counter keep their values when they are called in another function. Right now they are just being given random values when they are called instead of the values I'm initializing them with in the constructor. How can I fix this? The objective for this code is to make a program that Captures a string of words from a user of the program (via the keyboard) and adds the entered
words to a dynamic array of strings.
This is the array.cpp file
#include "array.h"
using namespace std;
Array::Array()
{
int size = 100;
int index = 0;
int counter = 0;
counter ++;
index++;
string *ptr = new string[size];
}
Array::~Array()
{
delete ptr;
ptr = nullptr;
}
void Array::populate()
{
string word;
cout << "Enter word to add to array: ";
cin >> word;
ptr[index] = word;
}
void Array::printContent()
{
cout << "Number of words in array: " << counter << endl;
cout << "Array size: " << size << endl;
cout << "Words in array: " << endl;
for (int i = 0; i < counter; i++)
{
cout << ptr[i] << endl;
}
}
void Array::displayMenu() const
{
cout << "[1] Add Word\n"
<< "[2] Print Array Information\n"
<< "[3] Quit Program\n"
<< "Enter Choice: ";
}
int Array::getChoice(int & choice1)
{
cin >> choice1;
while (choice1 < 1 || choice1 > 3) {
cout << endl;
cout << "Invalid Entry!!" << endl;
cout << "Enter Choice: ";
cin >> choice1;
}
return choice1;
}
int Array::endProgram(int & start2)
{
start2 = 0;
cout << "\n\n\t\tThank you for using this system!!\n\n";
return start2;
}
This is the array.h file
#include <iostream>
#include <string>
using namespace std;
class Array {
public:
Array();
~Array();
void populate();
void printContent();
void displayMenu() const;
int getChoice(int & choice1);
int endProgram(int & start2);
private:
int size;
int index;
int counter;
string *ptr;
};
Lastly this is the main.cpp file
#include <iostream>
#include "array.h"
using namespace std;
int main() {
int choice = 0;
int start = 1;
Array theArray;
while(choice != 3)
{
theArray.displayMenu();
theArray.getChoice(choice);
if(choice == 1)
{
theArray.populate();
}
if(choice == 2)
{
theArray.printContent();
}
if (choice == 3)
{
theArray.endProgram(start);
}
}
}
You are defining new local variables inside of your Array constructor and shadowing the member variables of the same name -- which is why the value isn't being preserved.
You only need to specify the type when defining new variables, but not when assigning to existing ones. To assign to the member variables, this should be:
Array::Array()
{
size = 100;
index = 0;
counter = 0;
ptr = new string[size];
...
}
Additionally, in constructors its more correct to use constructor initializer lists to initialize the values:
Array::Array()
: size{100},
index{0},
counter{0},
ptr{new string[size]}
{
...
}
Im working on this program to read in students first, last name, and 5 grades and put the students info into a struct. From there Im trying to use other functions to find the average grade, letter grade, max grade, and minimum grade. Im having issues on the proper way to read in and store students info and then call upon students info within other functions to calculate average, letter grade, etc... My 'displayAverages' function doesn't list any names and the grades are huge negative numbers. IF you can help me (after your headache from looking at my code goes away that is) Id appreciate it.
#include "pch.h"
#include <iostream>
#include <string>
#include <fstream>
#include <iomanip>
#include <cmath>
#include <vector>
#include <sstream>
using namespace std;
// Global variables
const int MAX_STUDENTS = 22;
const int MAX_GRADES = 5;
const string FILENAME = "NamesGrades.txt";
struct Student{
string name;
double grades[MAX_GRADES];
double average;
int max;
int min;
}students[MAX_STUDENTS];
char getLetterGrade(double grade);
void getData(Student &students)
{
ifstream fileIn;
int numStudents = 0;
fileIn.open(FILENAME.c_str());
if (fileIn.fail())
{
cout << "Could not open file" << endl;
system("PAUSE");
exit(1);
}
while (fileIn) {
for (int i = 0; i < MAX_STUDENTS; i++)
{
Student students;
getline(fileIn, students.name);
for (size_t i = 0; i < MAX_GRADES; i++)
{
fileIn >> students.grades[i];
}
return;
}
}
fileIn.close();
return;
}
void displayAverages(Student students) {
double total;
//double average;
int maxLength = 50;
cout << setprecision(1) << fixed << showpoint;
// Providing a header
cout << "\n\nGrade Averages\n";
cout << setw(maxLength + 1) << left << "Name" << setw(4) << right <<
"Average" << setw(6) << "Grade" << endl;
for (int i = 0; i < 22; i++)
{
cout << setw(maxLength + 1) << left << students.name;
total = 0;
for (int j = 0; j < MAX_GRADES; j++)
{
total += students.grades[i];
}
students.average = (double)total / MAX_GRADES;
cout << setw(7) << right << students.average << setw(6) <<
getLetterGrade(students.average) << endl;
}
}
char getLetterGrade(double grade) {
{
if (grade > 90) {
return 'A';
}
else if (grade > 80) {
return 'B';
}
else if (grade > 70) {
return 'C';
}
else if (grade > 60) {
return 'D';
}
else {
return 'F';
}
}
}
Let's take a look at your getData() function. It's defined as:
void getData(Student &students)
Since the return type is void, I'm guessing that you'll probably be passing in a Student and then modifying it in the function. However, you do:
Student students;
getline(fileIn, students.name);
Uh oh! This declares a new students that shadows the parameter students. So when you do students.name, you're talking about the local variable, not the parameter.
Kill that new declaration and things should work like you expected!
First thing - your code should have better structure!
void getData(Student &students)
{
ifstream fileIn;
int numStudents = 0;// you are not using this variable
fileIn.open(FILENAME.c_str());
if (fileIn.fail())
{
cout << "Could not open file" << endl;
system("PAUSE");
exit(1);
}
while (fileIn) {
for (int i = 0; i < MAX_STUDENTS; i++)//you should use auto here
{
Student students;//here you are making local object instead of changing the data off passed argument, you should get rid of this
getline(fileIn, students.name);
for (size_t i = 0; i < MAX_GRADES; i++)//you should use auto here
{
fileIn >> students.grades[i];
}
return;//you will return from you function after reading first student data so you should get rid of this
}
}
fileIn.close();
return;
}
After changes:
void getData(Student &students) {
ifstream fileIn;
fileIn.open(FILENAME.c_str());
if(fileIn.fail()) {
cout << "Could not open file" << endl;
system("PAUSE");
exit(1);
}
while(fileIn) {
for(auto i = 0; i < MAX_STUDENTS; i++) {
getline(fileIn, students.name);
for(auto i = 0; i < MAX_GRADES; i++)
fileIn >> students.grades[i];
}
}
fileIn.close();
}
I've got a class assignment in C++ that basically wants to me to use a struct and as well an array or two to allow customers to view and select items from a breakfast menu. Whenever I go to run the program it just says that it exited with a return value of 0. I've tried spot checking and I can't figure out what's wrong. I suspect I may not be loading the data from the text file correctly and thus it's causing no results because no data is loaded.
Here is my code:
//Student Name: Jacob Gillespie
//Date: 10/18/13
//Program: Breakfast Billing System
//Summary: Program allows customer to select different items from a menu and sums up
their total
//Headers
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
//Define structs
struct menuItemType
{
string menuItem;
double menuPrice;
};
//Declare variables and arrays
ifstream inData;
const double tax = 0.05;
int itemSelected[8];
menuItemType menuList[8];
//Provide function prototypes
void getData(ifstream& inFile);
void showMenu();
void printCheck();
void customerSelection();
//Main Program Execution
int main()
{
//Initialize itemSelected to 0
for (int counter = 0; counter < 8; counter++)
itemSelected[counter] = 0;
//Open input file
inData.open("menu.txt");
//Execute functions
void getData(ifstream& inData);
void showMenu();
void customerSelection();
void printCheck();
inData.close();
return 0;
}
//Function Definitions
//getData
void getData(ifstream& inFile)
{
for (int counter = 0; counter < 8; counter++)
{
inData >> menuList[counter].menuItem
>> menuList[counter].menuPrice;
}
}
//showMenu
void showMenu()
{
for (int counter = 0; counter < 8; counter++)
cout << menuList[counter].menuItem << " " << menuList[counter].menuPrice << endl;
}
//printCheck
void printCheck()
{
double total = 0;
double addedTax = 0;
for (int counter = 0; counter < 8; counter++)
if (itemSelected[counter] = 1)
{
cout << menuList[counter].menuItem << " " << menuList[counter].menuPrice << endl;
total = total + menuList[counter].menuPrice;
}
addedTax = total * tax;
cout << "Tax " << addedTax << endl;
cout << "Amount Due " << total << endl;
}
//customerSelection
void customerSelection()
{
string choice;
for (int counter = 0; counter < 8; counter++)
{
cout << "If you would like to order the item, " << menuList[counter].menuItem << ", please enter 'yes'. "
<< endl << "If not, please enter 'no'." << endl;
if (choice == "yes")
itemSelected[counter] = 1;
}
}
The voids before all the function calls in main are unnecessary where you have
//Execute functions
So here is the program I'm working on. So far it just prints out the double value in my CPP file. Note the two characters arrays I have set up. Why is this?
Molecule.h
const int MAX_STRUCT = 10;
const int MAX_NAME = 20;
class Molecule {
char molecule_structure[];
char molecule_name[];
double molecule_mass;
public:
Molecule();
bool read();
void display() const;
};
Molecule.cpp
#include <iostream>
#include <cstring>
using namespace std;
#include "Molecule.h"
Molecule::Molecule() {
molecule_structure[0] = '\0';
molecule_name[0] = '\0';
molecule_mass = 0;
}
bool Molecule::read(){
bool complete = false;
cout << "Enter structure : ";
cin.getline (molecule_structure, 10);
if (strcmp (molecule_structure, "0") != 0){
cout << "Enter full name : ";
cin.getline (molecule_name, 20);
cout << "Enter weight : ";
cin >> molecule_mass;
cin.ignore();
complete = true;
}
else {
molecule_structure[0] = '\0';
molecule_name[0] = '\0';
molecule_mass = 0;
}
return complete;
}
void Molecule::display() const
{
cout << molecule_structure << " " << molecule_name << " " << molecule_mass << endl;
}
w4x.h
const int MAX_MOLECULES = 10;
w4x.cpp
#include <iostream>
using namespace std;
#include "w4x.h"
#include "Molecule.h"
int main() {
int n = MAX_MOLECULES;
Molecule molecule[MAX_MOLECULES];
cout << "Molecular Information\n";
cout << "=====================" << endl;
for (int i = 0; i < MAX_MOLECULES; i++) {
if (!molecule[i].read()) {
n = i;
i = MAX_MOLECULES;
}
cout << endl;
}
cout << "Structure Name Mass\n";
cout << "==================================================" << endl;
for (int i = 0; i < n; i++)
molecule[i].display();
}
The errors I believe are coming from my Molecule.cpp file which is what I've been changing around.
This is the output I'm currently receiving.
Molecular Information
=====================
Enter structure : Super
Enter full name : Man
Enter weight : 57
Enter structure : 0
Structure Name Mass
==================================================
57
Changing the header Molecule.h so it uses:
const int MAX_STRUCT = 10;
const int MAX_NAME = 20;
class Molecule {
char molecule_structure[MAX_STRUCT];
char molecule_name[MAX_NAME];
double molecule_mass;
public:
Molecule();
bool read();
void display() const;
};
Makes the code work sanely.
A more thorough reworking of the code to use std::string gives:
Molecule.h
#ifndef MOLECULE_H_INCLUDED
#define MOLECULE_H_INCLUDED
#include <string>
class Molecule
{
std::string molecule_structure;
std::string molecule_name;
double molecule_mass;
public:
Molecule();
bool read();
void display() const;
};
#endif // MOLECULE_H_INCLUDED
Molecule.cpp
#include <iostream>
#include <iomanip>
#include <limits>
#include <cstring>
using namespace std;
#include "Molecule.h"
Molecule::Molecule() : molecule_structure(""), molecule_name(""), molecule_mass(0) { }
bool Molecule::read()
{
Molecule m;
cout << "Enter structure : ";
if (!getline(cin, m.molecule_structure) || m.molecule_structure == "")
return false;
cout << "Enter full name : ";
if (!getline(cin, m.molecule_name))
return false;
cout << "Enter weight : ";
if (!(cin >> m.molecule_mass))
return false;
cin.ignore(numeric_limits<streamsize>::max(), '\n');
swap(*this, m);
return true;
}
void Molecule::display() const
{
cout << left << setw(15) << molecule_structure << " ";
cout << left << setw(20) << molecule_name << " ";
cout << setprecision(5) << molecule_mass << endl;
}
The read() function does not modify the variable it is given unless the reading is successful. There are probably better ways to handle the input, but that shown is reasonably sensible. You terminate the input with an empty line in response to the 'Enter structure:' prompt. The printf() format notations have the merit of brevity compared with what's necessary with C++ I/O streams.
w4x.cpp
No longer including w4x.h.
#include <iostream>
using namespace std;
#include "Molecule.h"
const int MAX_MOLECULES = 10;
int main()
{
int n = MAX_MOLECULES;
Molecule molecule[MAX_MOLECULES];
cout << "Molecular Information\n";
cout << "=====================" << endl;
for (int i = 0; i < MAX_MOLECULES; i++) {
if (!molecule[i].read()) {
n = i;
break;
}
cout << endl;
}
if (n > 0)
{
cout << "Structure Name Mass\n";
cout << "===================================================" << endl;
for (int i = 0; i < n; i++)
molecule[i].display();
}
}
For my c++ homework, I have an .txt document containing building information ordered like:
Building name
year built
lat coordinate
lon coordinate
ex.
Parking Deck
1993
34.2252
37.5563
Admin Building
1985
34.2356
37.5734
I have to read this into an array of my created struct:
struct list
{
char name[50];
int yearBuilt;
double latCoord;
double lonCoord;
} building;
now I've created a for loop to read in the data to my created array of type list:
list buildingnumber[SIZE]; //array for buildings
But when I try to print out the "k" earliest buildings made, it shows no data in the array
Here's my current code:
#include <iostream>
#include <fstream>
#include <istream>
#include <cstdlib>
#include <string>
using namespace std;
const int SIZE = 5000;
//struct for building type
struct list
{
char name[50];
int yearBuilt;
double latCoord;
double lonCoord;
}building;
list buildingnumber[SIZE]; //array for buildings
void InsertionSort(list buildingnumber[], int buildingsloaded)
{
int key = 0, i = 0;
for(int j = 1; j < buildingsloaded; j++)
{
key=buildingnumber[j].yearBuilt;
i=j-1;
while(buildingnumber[i].yearBuilt > key && i >= 0)
{
buildingnumber[i+1] = buildingnumber[i];
i--;
}
buildingnumber[i+1].yearBuilt = key;
}
}
int main()
{
char filePath[50];
ifstream openFile;
cout << "Enter the path of the building file: ";
cin.getline(filePath, 50);
openFile.open(filePath);
//verify if file is opened + report buildings loaded
int buildingsloaded = 0;
if(!openFile.fail())
{
while(openFile >> building.name >> building.yearBuilt >> building.latCoord >> building.lonCoord)
{
buildingsloaded++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
// get how many buildings user wants
int k = 0;
cout << "How many buildings are you interested in?: ";
cin >> k;
//create array
// loadKbuildings(building, buildingsloaded);
for(int i = 0; i < k; i++)
{
openFile >> buildingnumber[i].name >> buildingnumber[i].yearBuilt >> buildingnumber[i].latCoord >> buildingnumber[i].lonCoord;
}
// insertion sort
InsertionSort(buildingnumber, buildingsloaded);
// display earliest k buildings
cout << "The " << k << " oldest buildings are: " << endl;
int i = 0;
while ( i < k )
{
cout << buildingnumber[i].name << endl;
cout << "Year Built: " << buildingnumber[i].yearBuilt << endl;
cout << "Coordinates: (" << buildingnumber[i].latCoord << "," << buildingnumber[i].lonCoord << ")" << endl;
cout << endl;
i++;
}
}
The problem is here:
if(!openFile.fail())
{
while(openFile >> building.name >> building.yearBuilt >> building.latCoord >> building.lonCoord)
{
buildingsloaded++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
You've read all of the data already (to count the number of buildings); the next time you try to grab the data, it's gone.
You can resolve this issue by storing the buildings in an array the first scan through.
int c = 0;
if(!openFile.fail())
{
// *
while(openFile >> buildingnumber[c].name >> buildingnumber[c].yearBuilt >> buildingnumber[c].latCoord >> buildingnumber[c].lonCoord)
{
buildingsloaded++;
c++;
}
cout << buildingsloaded << " buildings have been loaded." << endl;
}
As per WhozCraig's comment, the line under the star only reads in one word for the building's name; you should use cin.getline() instead and change around the loop condition.
You should obviously also take out the data reading section below:
//create array
// loadKbuildings(building, buildingsloaded);
for(int i = 0; i < k; i++)
{
openFile >> buildingnumber[i].name >> buildingnumber[i].yearBuilt >> buildingnumber[i].latCoord >> buildingnumber[i].lonCoord;
}