I've created a class patient that contains some information about patients such as Name, Age, Adress etc.
When I try to compile the program I get an
Debug Assertion Failed (Expression String != NULL) and I can't seem to find why is this happening.
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
class pacient{
protected:
int colesterol;
int tensiune_arteriala;
char * nume;
char * prenume;
int varsta;
char * adresa;
char * data_analiza;
public:
//constructor cu toti parametrii
pacient(){};
pacient(int colesterol, int tensiune_art, char * nume, char *prenume,
int varsta, char * adresa, char *data_analiza)
{
(*this).colesterol = colesterol;
tensiune_arteriala = tensiune_art;
strcpy((*this).nume, nume);
strcpy((*this).prenume, prenume);
(*this).varsta = varsta;
strcpy((*this).adresa, adresa);
strcpy((*this).data_analiza, data_analiza);
}
//destructor
~pacient(){
colesterol = 0;
tensiune_arteriala = 0;
strcpy(nume, "");
strcpy(prenume, "");
varsta = 0;
strcpy(adresa, "");
strcpy(data_analiza, "");
}
//functie virtuala
virtual char * get_name() { return "Este pacient"; }
//citirea si afisarea obiectelor
friend istream &operator>> (istream&in, pacient&ob);
friend ostream &operator<< (ostream&out, const pacient&ob);
};
istream& operator>>(istream &in, pacient &ob){
cout << "Nume: "; gets(ob.nume); cout << endl;
cout << "Prenume: "; gets(ob.prenume); cout << endl;
cout << "Varsta: "; cin >> ob.varsta; cout << endl;
cout << "Adresa: "; gets(ob.adresa); cout << endl;
cout << "Data analiza: "; gets(ob.data_analiza); cout << endl;
cout << "Colesterol: "; cin>>ob.colesterol; cout << endl;
cout << "Tensiune arteriala: "; cin>>ob.tensiune_arteriala; cout << endl;
return in;
}
ostream &operator<< (ostream&out, const pacient&ob){
cout << "Nume: "; puts(ob.nume); cout << endl;
cout << "Prenume: "; puts(ob.prenume); cout << endl;
cout << "Varsta: "; cout << ob.varsta; cout << endl;
cout << "Adresa: "; puts(ob.adresa); cout << endl;
cout << "Data analiza: "; puts(ob.data_analiza); cout << endl;
cout << "Colesterol: "; cout << ob.colesterol; cout << endl;
cout << "Tensiune arteriala: "; cout << ob.tensiune_arteriala; cout << endl;
return out;
}
int main()
{
pacient a;
cin >> a;
cout << a;
}
That's because you have members that are pointers:
char * nume;
char * prenume;
...
But you don't initalize them, and don't allocate memory, but netvertheless try to use them:
pacient(int colesterol, int tensiune_art, char * nume, char *prenume,
int varsta, char * adresa, char *data_analiza)
{
...
strcpy((*this).nume, nume); ///<======= OUCH !!!!
Consider using string instead of char*:
you won't have to manage memory, it's automatic
you can use = instead of strcpy
you can return string without having to worry about leaking memory
Related
I am using Code::Blocks to write this C++ program, but everytime I do a 3rd Insert on the Link List, and when I use the Display option to check my work, I get a strange error. I have encountered no build errors. Please help check and advise when you have the chance, thank you.
#include <iostream>
#include <fstream>
#include <cmath>
using namespace std;
typedef struct student
{
string name;
int quiz1, quiz2, quiz3;
struct student *nxt;
} STUDENT;
class studentsStruct
{
private:
STUDENT *S; //Header of the Student List
public:
void init();
void add(string n, int a, int b, int c);
void del(string n);
void update(string n);
void save();
void retrieve();
void display();
};
int menu();
int updatemenu();
float round2(float x); // function to round the average and limit to 2 decimal points
int main()
{
studentsStruct ars;
string nm;
int a, b, c;
ars.init(); // Initialize the S Header of the Student List
ars.retrieve(); // Check if the "studentsdb.txt" is available and load the data as needed
while (1)
{
switch (menu())
{
case 1:
system("cls");
cout << "Insert Mode" << endl;
cout << "Name: ";
cin >> nm;
cout << "Input Quiz 1: ";
cin >> a;
cout << "Input Quiz 2: ";
cin >> b;
cout << "Input Quiz 3: ";
cin >> c;
ars.add(nm, a, b, c);
break;
case 2:
system("cls");
cout << "Update Mode" << endl;
cout << "Input Students Name: ";
cin >> nm;
ars.update(nm);
break;
case 3:
system("cls");
cout << "Delete Mode" << endl;
cout << "Enter Name: ";
cin >> nm;
ars.del(nm);
break;
case 4:
ars.display();
break;
case 5:
ars.save();
exit(0);
default:
cout << "1 to 5 only. ";
system("pause");
}
}
return 0;
}
void studentsStruct::init()
{
S = NULL;
}
void studentsStruct::add(string n, int a, int b, int c)
{
STUDENT *p, *q, *temp;
p = q = S;
temp = new STUDENT;
temp->name = n;
temp->quiz1 = a;
temp->quiz2 = b;
temp->quiz3 = c;
while (p != NULL)
{
q = p;
p = p->nxt;
}
if (p == S)
{
S = temp;
}
else
{
q->nxt = temp;
temp->nxt = p;
}
}
void studentsStruct::del(string n)
{
STUDENT *p, *q;
p = q = S;
while (p != NULL && p->name != n)
{
q = p;
p = p->nxt;
}
if (p == NULL)
{
cout << n << (" is not found.") << endl;
system("pause");
}
else
{
if (p == S)
{
S = S->nxt;
}
else
{
q->nxt = p->nxt;
delete (p);
cout << n << (" is deleted from the student records") << endl;
}
}
}
void studentsStruct::update(string n)
{
STUDENT *p, *q;
p = q = S;
int ua, ub, uc;
while (p != NULL && p->name != n)
{
q = p;
p = p->nxt;
}
if (p == NULL)
{
cout << ("Not Found") << endl;
system("pause");
}
else
{
while (1)
{
cout << "Update Mode" << endl;
cout << "Student : " << p->name << endl;
cout << "Quiz 1 Grade: " << p->quiz1 << endl;
cout << "Quiz 2 Grade: " << p->quiz2 << endl;
cout << "Quiz 3 Grade: " << p->quiz3 << endl;
switch (updatemenu())
{
case 1:
cout << "Quiz 1 Grade: ";
cin >> ua;
p->quiz1 = ua;
save();
break;
case 2:
cout << "Quiz 2 Grade: ";
cin >> ub;
p->quiz2 = ub;
save();
break;
case 3:
cout << "Quiz 3 Grade: ";
cin >> uc;
p->quiz3 = uc;
save();
break;
case 4:
main();
save();
break;
default:
cout << "Select an option between 1 to 3" << endl;
cout << "or select 4 to exit the Update Menu: " << endl;
}
}
}
}
int updatemenu()
{
int um;
cout << "Update Menu" << endl;
cout << "1.) Update Quiz 1 Grade" << endl;
cout << "2.) Update Quiz 2 Grade" << endl;
cout << "3.) Update Quiz 3 Grade" << endl;
cout << "4.) Return to the Main Menu" << endl;
cout << "Select an option between 1 to 3" << endl;
cout << "or select 4 to exit the Update Menu: ";
cin >> um;
return (um);
}
void studentsStruct::display()
{
STUDENT *p;
int i = 1;
p = S;
float ave;
string remarks;
system("cls");
cout << "No.\tName\tQuiz 1\tQuiz 2\tQuiz 3\tAverage\tRemarks\n";
while (p != NULL)
{
ave = (p->quiz1 + p->quiz2 + p->quiz3) / 3.0;
remarks = ave >= 75 ? "Passed" : "Failed";
cout << i++ << ".)\t" << p->name << "\t" << p->quiz1 << "\t" << p->quiz2 << "\t" << p->quiz3 << "\t" << round2(ave) << "\t" << remarks << endl;
p = p->nxt;
}
system("pause");
}
int menu()
{
int op;
cout << "Menu" << endl;
cout << "1.) Insert" << endl;
cout << "2.) Update" << endl;
cout << "3.) Delete" << endl;
cout << "4.) Display" << endl;
cout << "5.) Exit" << endl;
cout << "Select(1-5): ";
cin >> op;
return (op);
}
// Save the student data to "studentdb.txt" if available and create a file if needed
void studentsStruct::save()
{
STUDENT *p;
p = S;
ofstream stuData;
stuData.open("studentdb.txt");
while (p != NULL)
{
stuData << p->name << " " << p->quiz1 << " " << p->quiz2 << " " << p->quiz3 << endl;
p = p->nxt;
}
stuData.close();
}
// Check if the "studentdb.txt" is available and load the data as needed
void studentsStruct::retrieve()
{
ifstream fp;
string n;
int ax, by, cz;
fp.open("studentdb.txt");
if (fp.peek() != std::ifstream::traits_type::eof())
{
while (fp >> n >> ax >> by >> cz)
{
add(n, ax, by, cz);
}
}
else
{
cout << "The file is available but contains no records" << endl;
}
fp.close();
}
// function to round the average and limit to 2 decimal points
float round2(float x)
{
return trunc(x * 100.0) / 100.0;
}
And this is the error I am encountering (see screenshot below):
In my assignment I was asked to create the Product class, and I have finished all the implementations except the "non-member IO operator". The question I found it very vague, it asks me to overload the << and >> operators to work with ostream and istream to read a Product from and print a Product to the console in order to make this main function work.
Here I see the main function has cout or cin to Product's derived class SItem, I wonder how I should implement the << >> operators to make the main work.
My main:
#include <iostream>
#include <iomanip>
#include <cstdlib>
#include "Product.h"
#include <fstream>
#ifdef TAB
# undef TAB
#endif
#define TAB '\t'
using namespace std;
namespace sict {
class SItem :public Product {
public:
SItem(const char* theSku, const char * theName) :Product(theSku, theName) {}
SItem() {}
virtual std::fstream& store(std::fstream& file, bool addNewLine = true)const {
if (!isEmpty()) {
file.open("ms4.txt", ios::out | ios::app);
file << sku() << TAB << name() << TAB << quantity() << TAB << qtyNeeded() << TAB
<< int(taxed()) << TAB << price() << endl;
file.clear();
file.close();
}
return file;
}
virtual std::fstream& load(std::fstream& file) {
file.open("ms4.txt", ios::in);
char buf[2000];
double dbuf;
int ibuf;
file >> buf;
sku(buf);
file >> buf;
name(buf);
file >> ibuf;
quantity(ibuf);
file >> ibuf;
qtyNeeded(ibuf);
file >> ibuf;
taxed(ibuf != 0);
file >> dbuf;
price(dbuf);
file.clear();
file.close();
return file;
}
virtual std::ostream& write(std::ostream& os, bool linear)const {
return isEmpty() ? os : (os << sku() << ": " << name() << ", qty: "
<< quantity() << ", qtyNeeded:" << qtyNeeded()
<< ", Cost: " << fixed << setprecision(2) << cost());
}
virtual std::istream& read(std::istream& is) {
char buf[2000];
double dbuf;
int ibuf;
cout << "Sku: ";
is >> buf;
sku(buf);
cout << "Name (no spaces): ";
is >> buf;
name(buf);
cout << "Qty: ";
is >> ibuf;
quantity(ibuf);
cout << "Qty Needed: ";
is >> ibuf;
qtyNeeded(ibuf);
cout << "Is taxed? (1/0): ";
is >> ibuf;
taxed(ibuf != 0);
cout << "Price: ";
is >> dbuf;
price(dbuf);
return is;
}
};
}
void dumpFile(fstream& f) {
f.open("ms4.txt", ios::in);
char ch;
while (!f.get(ch).fail()) {
cout.put(ch);
}
f.clear();
f.close();
}
using namespace sict;
void test() {
double res, val = 0.0;
fstream F("ms4.txt", ios::out);
F.close();
SItem S;
SItem T;
SItem U;
cout << "Enter Product info: " << endl;
cin >> S;
SItem V = S;
S.store(F);
T.load(F);
cout << "T: (store, load)" << endl;
cout << T << endl;
cout << "S: " << endl;
cout << S << endl;
cout << "V(S): " << endl;
cout << V << endl;
cout << "U=T & op= :" << endl;
U = T;
cout << U << endl;
cout << "Operator == :" << endl;
cout << "op== is " << (T == "1234" ? "OK" : "NOT OK") << endl;
cout << "op+=: " << endl;
U += 10;
cout << U << endl;
cout << "op+=double : " << endl;
res = val += U;
cout << res << "=" << val << endl;
}
int main() {
fstream F("ms4.txt", ios::out);
F.close();
SItem S;
SItem U("4321", "Rice");
cout << "Empty Prouduct:" << endl << S << endl;
cout << "U(\"4321\", \"Rice\"):" << endl << U << endl;
cout << "Please enter the following information:" << endl;
cout << "Sku: 1234" << endl;
cout << "Name(no spaces) : Blanket" << endl;
cout << "Qty : 12" << endl;
cout << "Qty Needed : 23" << endl;
cout << "Is taxed ? (1 / 0) : 1" << endl;
cout << "Price : 12.34" << endl;
test();
cout << "Please enter the following information:" << endl;
cout << "Sku: 1234" << endl;
cout << "Name(no spaces) : Jacket" << endl;
cout << "Qty : 12" << endl;
cout << "Qty Needed : 23" << endl;
cout << "Is taxed ? (1 / 0) : 0" << endl;
cout << "Price : 12.34" << endl;
test();
dumpFile(F);
cout << "----The End" << endl;
return 0;
}
This is my Product.h:
namespace sict {
class Product : public Streamable {
char sku_[MAX_SKU_LEN + 1];
char * name_;
double price_;
bool taxed_;
int quantity_;
int qtyNeeded_;
public:
Product();
Product(const char*, const char*, bool = true, double = 0, int = 0);
Product(const Product&);
virtual ~Product();
Product& operator=(const Product&);
//setters
void sku(const char*);
void price(double);
void name(const char*);
void taxed(bool);
void quantity(int);
void qtyNeeded(int);
//getters
const char* sku()const;
double price()const;
const char* name()const ;
bool taxed()const;
int quantity()const;
int qtyNeeded()const;
double cost()const;
bool isEmpty()const;
//member operators
bool operator==(const char*);
int operator+=(int);
int operator-=(int);
};
double operator+=(double, const Product&);
std::ostream& operator<<(std::ostream& ostr, const Product& p);
std::istream& operator >> (std::istream& istr, Product& p);
}
All the functions have been implemented except the last two, which are the IO operators.
Streamable class is an abstract class that has no implementations.
You did this wrong in many ways.
Best approach in your case is do it like that.
First define interfaces for stream operations, for your products:
class IStreamPrintable
{
public:
virtual std::ostream& PrintToStream(std::ostream& outStream) const = 0;
};
class IStreamReadable
{
public:
virtual std::istream& ReadFromStream(std::istream& inputStream) = 0;
};
Secondly define stream operators which will use this interfaces.
std::ostream& operator<<(std::ostream& out, const IStreamPrintable& printObject)
{
return printObject.PrintToStream(out);
}
std::istream& operator>>(std::istream& input, IStreamReadable& readObject)
{
return printObject.ReadFromStream(input);
}
Now you Product can inherit this interfaces:
class Product
: public IStreamPrintable
, public IStreamReadable
{
…
};
You do not have to implement it immediately. You can implement those methods in specific product classes SItem and it will work out of the box.
Your method virtual std::fstream& store(std::fstream& file, bool addNewLine = true) is total mess. You are passing fstream object and opening some specific file on it. This is wrong since you are unable to write multiple objects to single file. Keep there ostream object and do not change is state (do only writing), so you could cascade calls and so you could avoid hard-coding a file name.
In CPP file #1, I'm trying to loop through the array to see if any of the inputed names match Mordor or the_Vale (from CPP file #2 towards the bottom), however my loop is not working and I only know how to loop through a string array, not a char
#Header File#
#ifndef KINGDOM_H
#define KINGDOM_H
namespace westeros
{
class Kingdom
{
public: //Makes this class public to the rest of the code
char m_name[32];
int m_population;
int count = 0;
};
void display(Kingdom&);
void display(Kingdom* k, int x);
void display(Kingdom* k, int x, int z);
void display(Kingdom* k, int x, char foo[]);
}
#endif
#CPP FIle #1#
#include <iostream>
#include "kingdom.h"
void display(Kingdom* k, int x, char foo[])
{
int a = 0;
int found = 0;
cout << "Searching for kingdom " << foo << " in Westeros" << endl;
for (a; a < x; a++)
{
if (k[a].m_name == foo)
//(strcmp(k[a].m_name) == 0)//Not working
{
cout << k[a].m_name << ", population " << k[a].m_population << endl;
found = 1;
}
}
if (found == 0)
{
cout << foo << " is not part of Westeros." << endl;
}
}
}
## CPP File (main) #2##
#include <iostream>
#include "kingdom.h"
using namespace std;
using namespace westeros;
int main(void)
{
int count = 0; // the number of kingdoms in the array
// TODO: declare the kingdoms pointer here (don't forget to initialize it)
Kingdom* pKingdoms = nullptr;
cout << "==========" << endl
<< "Input data" << endl
<< "==========" << endl
<< "Enter the number of kingdoms: ";
cin >> count;
cin.ignore();
pKingdoms = new Kingdom[count];
for (int i = 0; i < count; ++i)
{
// TODO: add code to accept user input for the kingdoms array
int x = 0;
x++;
cout << "Enter the name for kingdom #" << x + i << ": ";
cin >> pKingdoms[i].m_name;
cout << "Enter the number people living in " << pKingdoms[i].m_name << ": ";
cin >> pKingdoms[i].m_population;
}
cout << "==========" << endl << endl;
// testing that "display(...)" works
cout << "------------------------------" << endl
<< "The first kingdom of Westeros" << endl
<< "------------------------------" << endl;
display(pKingdoms[0]);
cout << "------------------------------" << endl << endl;
// This is where I am having the problem
display(pKingdoms, count, "Mordor");
cout << endl;
display(pKingdoms, count, "The_Vale");
cout << endl;
cout << endl;
delete[] pKingdoms;
pKingdoms = nullptr;
return 0;
}
if (k[a].m_name == foo)
This is not how you compare two C-Style strings. This only compares the pointers, which should result in false almost certainly. You could use strcmp (#include <string.h>):
if (!strcmp(k[a].m_name, foo))
A better way, though, since you're programming in C++, use std::string:
std::string m_name;
and the comparison would have worked flawlessly.
I've searched through the already asked questions, but I haven't found what I'm looking for.
I'm working with structures, where I store a person's details (first name, last name, birth date and so on...). The goal is then to create an array of pointers to these structures and make a list containing a group of people's information. the main function is vary basic so far.
#include <iostream>
#include "methods.h"
using namespace std;
void printMenu() {
cout << "\n Welcome to the Person program!" << endl
<< " Choose what you would like to do: " << endl
<< " 1. Insert person" << endl
<< " 2. Show person" << endl
<< " 3. Exit" << endl;
}
int main() {
char choice;
person p;
do {
printMenu();
cout << "\n Your choice: ";
cin >> choice;
cin.ignore();
switch(choice) {
case '1': setPerson(p); break;
case '2': getPerson(p); break;
default: cout << "\n Exiting..." << endl;
}
} while(choice == '1' || choice == '2');
return 0;
}
here's the methods.cc file
// methods.cc
#include <iostream>
#include "methods.h"
using namespace std;
static char dummy; // catches the '\n' left in the stream after the usage of cin >>
void setFirstName(char s[]) {
cout << "\n First name: ";
cin.getline(s, 25);
}
void getFirstName(const char s[]) {
cout << "\n First name: " << s << endl;
}
void setLastName(char s[]) {
cout << "\n Last name: ";
cin.getline(s, 25);
}
void getLastName(const char s[]) {
cout << "\n Last name: " << s << endl;
}
void setAddress(address & a) {
cout << "\n Street: ";
cin.getline(a.street, 25);
cout << "\n Number: ";
cin.getline(a.number, 6);
cout << "\n Town: ";
cin.getline(a.town, 25);
cout << "\n Zip code: ";
cin.getline(a.zip, 25);
cout << "\n Province: ";
cin.getline(a.province, 25);
}
void getAddress(const address & a) {
cout << "\n Street: " << a.street << endl;
cout << "\n Number: " << a.number << endl;
cout << "\n Town: " << a.town << endl;
cout << "\n Zip code: " << a.zip << endl;
cout << "\n Province: " << a.province << endl;
}
void setBirthDate(birthdate & bd) {
cout << "\n Day: ";
cin >> bd.day;
cin.get(dummy);
cout << "\n Month: ";
cin >> bd.month;
cin.get(dummy);
cout << "\n Year: ";
cin >> bd.year;
cin.get(dummy);
}
void getBirthDate(const birthdate & bd) {
cout << "\n Day: " << bd.day << endl;
cout << "\n Month: " << bd.month << endl;
cout << "\n Year: " << bd.year << endl;
}
void setGender(char & g) {
cout << "\n Gender: ";
cin >> g;
cin.get(dummy);
}
void getGender(const char & g) {
cout << "\n Gender: " << g << endl;
}
void setPerson(person & p) {
setFirstName(p.firstName);
setLastName(p.lastName);
setAddress(p.location);
setBirthDate(p.bd);
setGender(p.gender);
}
void getPerson(const person & p) {
getFirstName(p.firstName);
getLastName(p.lastName);
getAddress(p.location);
getBirthDate(p.bd);
getGender(p.gender);
}
The program works fine, but, after entering all the information and prompting the program to display the entered data, the first three fields (first name, last name and street) all show the same output, that is, the street's name... somehow the first and last names are not saved into the respective char arrays...
for example, say I enter A and B as first and last name then C as the street name, the output will be
First name: C
Last name: C
Street: C
... then from here, the output is correct...
EDIT: btw, I haven't used the string type on purpose. Being it object-oriented, it is not covered in the programming course, so I'm stuck with the c string type (arrays of chars or pointers to char)
EDIT 2: here's the methods.h file. I've found the error myself. see comments in the code in struct person
// methods.h
#ifndef METHODS_H
#define METHODS_H
struct address {
char street[15];
char number[6];
char town[15];
char zip[6];
char province[3];
};
struct birthdate {
int day;
int month;
int year;
};
struct person {
char firstName[25]; // error due to me omitting the array length.
char lastName[25]; // same here, I had written char firstName[] & char lastName[]
address location;
birthdate bd;
char gender;
};
// base methods
void setFirstName(char s[]);
void getFirstName(const char s[]);
void setLastName(char s[]);
void getLastName(const char s[]);
void setAddress(address & a);
void getAddress(const address & a);
void setBirthDate(birthdate & bd);
void getBirthDate(const birthdate & bd);
void setGender(char & g);
void getGender(const char & g);
void setPerson(person & p);
void getPerson(const person & p);
#endif
thanks for all your advice!
Here is my code, I was trying to allocate memory to an object by asking size from the user. I dont know where I am going wrong. The error the compiler is giving me is "void value not ignored as it ought to be". Please help me. Thanks in advance.
#include <iostream>
using namespace std;
class test
{
char name[20];
char address[30];
char desig[20];
public:
void getData();
void display();
~test()
{
cout << "Destructor is invoked";
}
};
void test::getData()
{
cout << "Enter your name" << endl;
cin >> name;
cout << "Enter address" << endl;
cin >> address;
cout << "Enter designation" << endl;
cin >> desig;
}
void test::display()
{
cout << "name" << endl;
cout << name << endl;
cout << "address" << endl;
cout << address;
cout << "Enter designation" << endl;
cout << desig;
}
int main()
{
int s;
cout << "Enter the size of an array" << endl;
cin >> s;
test* p1 = new test[s];
for (int i = 0; i < s; i++)
{
*p1[i].getData();
}
for (int i = 0; i < s; i++)
{
*p1[i].display();
}
delete[] p1;
return 0;
}
You need to change:
*p1[i]
To:
p1[i]
Here:
*p1[i].display();
You're calling member function display that returns void and try to dereference that.