C++ program doesn't print out strings but does output double value - c++

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();
}
}

Related

How to initialize private variables in a different file and make it so it holds the value for other functions?

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]}
{
...
}

How to prevent stack smashing detected?

I am trying to write a program to get student data (student id, subject results) from user input and align them based on their total marks. But when I try to input till the 5th student the stack smashing detected the error that occured. And I can't find a way to solve this problem...
It would be really helpful if anyone can give me some advice about it. Thanks in advance
My code:
h file
#include <string>
#include <iostream>
using namespace std;
class student
{
private:
char id[100];
int eng, math, jan, total;
public:
void getInput(void);//ユーザーから学生のデータを入力してもらう
void putInput(void);//最後の結果を表示する
friend void sort(student std[]);//総得点の高い順に各人のデータを並べ替える
friend void avg(student std[]);//各科目と総得点の平均値を計算する
};
cpp file
#include <string>
#include <iostream>
#include "report1.h"
using namespace std;
#define MAX 10
void student::getInput(void)//ユーザーから学生のデータを入力してもらう
{
cout << "IDを入力してください:";
cin >> id;
cout << "英語の点数:";
cin >> eng;
cout << "数学の点数:";
cin >> math;
cout << "国語の点数:";
cin >> jan;
total = eng + math + jan;
}
void student::putInput(void)//最後の結果を表示する
{
cout << id << "\t" << eng << "\t" << math << "\t" << jan << "\t" << total << endl;
}
void sort(student std[])//総得点の高い順に各人のデータを並べ替える
{
int i, j;
for ( i = 0; i < MAX-1; i++)
{
for ( j = i+1; j < MAX; j++)
{
if (std[i].total < std[j].total)//一つ後ろのデータが確認中のデータより大きいなら、並べ替える
{
student temp;
temp = std[i];
std[i] = std[j];
std[j] = temp;
}
}
}
}
void avg(student std[])//各科目と総得点の平均値を計算する
{
int i;
int eng_total, math_total, jan_total, total_total;
double eng_avg, math_avg, jan_avg, total_avg;
eng_total = 0;
math_total = 0;
jan_total = 0;
total_total = 0;
for ( i = 0; i < MAX; i++)
{
eng_total += std[i].eng;
math_total += std[i].math;
jan_total += std[i].jan;
total_total += std[i].total;
}
eng_avg = (double)eng_total/MAX;
math_avg = (double)math_total/MAX;
jan_avg = (double)jan_total/MAX;
total_avg = (double)total_total/MAX;
cout << "Avg\t" << eng_avg << "\t" << math_avg << "\t" << jan_avg << "\t" << total_avg << endl;
}
int main()
{
student std[MAX-1];
int i, j;
for ( i = 0; i < MAX; i++)
{
cout << i+1 << "番目の学生データを入力してください。" << endl;
std[i].getInput();
}
sort(std);
cout << endl;
cout << "ID_No" << "\tEng" << "\tMath" << "\tJan" << "\tTotal" << endl;
for ( i = 0; i < MAX; i++)
{
std[i].putInput();
}
avg(std);
return 0;
}

Adding conditions to a conditional statement

I am messing around with dynamic arrays for a user defined amount of inputs for an and gate.
The issue I am running into is that I don't know how many inputs the user is going to test and I need to be able to have an if-else statement that tests each input.
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
class logic_gate {
public:
int x = 0;
};
int main() {
int userInput = 0;
cout << "How many inputs do you want on your and gate?: ";
cin >> userInput;
cout << endl;
logic_gate *and_gate = new logic_gate[userInput];
cout << endl << "Please enter the values of each bit below . . ." << endl <<
endl;
int userTest1 = 0;
for (int i = 0; i < userInput; i++) {
cout << "#" << i + 1 << ": ";
cin >> userTest1;
and_gate[i].x = userTest1;
}
return 0;
}
Here is the code that I am currently trying to find a solution for.
To implement an AND gate with n inputs you can simply do:
int output = 1;
for (int i = 0; i < n; ++i)
{
if (!and_gate [i])
{
output = 0;
break;
}
}
// ...
Use Vector data structure, you don't need to tell its size while declaring, unlike array, and it can grow automatically.
To read input till it's arriving, put cin inside while loop condition. I used getline to read whole line and work with it, so that whenever user presses enter button at empty line, program will think that no more input is coming anymore, and will start calculating 'And' of inputs.
//don't forget to import vector
#include <iostream>
#include <vector>
#include <string>
using namespace std;
class logic_gate {
public:
int x = 0;
logic_gate(){ //default constructor
}
logic_gate(int k){ //another constructor needed
x = k;
}
};
int main(){
cout << endl << "Please enter the values of each bit below . . ." << endl;
vector<logic_gate> and_gate; //no need to tell size while declaration
string b;
while(getline(cin, b)){ //read whole line from standard input
if (b == "\0") //input is NULL
break;
and_gate.push_back(logic_gate(stoi(b))); //to convert string to integer
}
if (!and_gate.empty()){
int output = and_gate[0].x;
for (int i = 1; i < and_gate.size(); i++){
output = output & and_gate[i].x;
}
cout << "And of inputs is: " << output << endl;
}
else{
cout << "No input was given!\n";
}
return 0;
}
Feel free to ask if some doubts linger
I figured out what I wanted to do. Thanks to everyone who helped and especially Paul Sanders. Below is my final code.
#include <iostream>
using namespace std;
class logic_gate {
public:
int x = 0;
};
int main() {
int userInput;
int output = 1;
cout << "How many inputs do you want on your and gate?: ";
cin >> userInput;
cout << endl;
logic_gate *and_gate = new logic_gate[userInput];
cout << endl << "Please enter the values of each bit below . . ." << endl <<
endl;
int userTest1;
for (int i = 0; i < userInput; i++) {
cout << "#" << i + 1 << ": ";
cin >> userTest1;
and_gate[i].x = userTest1;
}
if (userInput == 1) {
output = userTest1;
cout << "The test of " << userTest1 << " is " << output << endl << endl;
}
else if (userInput > 1) {
for (int i = 0; i < userInput; i++) {
if (!and_gate[i].x)
{
output = 0;
break;
}
}
cout << "The test of ";
for (int i = 0; i < userInput; i++) {
cout << and_gate[i].x;
}
cout << " is " << output << endl << endl;
}
return 0;
}

Multiple errors with function header, and overloaded functions

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.

How to display my Queue & Stack?

I Wanna display my EvenQueue, EvenStack, OddQueue & EvenQueue? I already try some methods but the compiler gave me some errors.
Any help would be appreciated... Or any tips.
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
int main()
{
stack<int> OddStack;
queue<int> OddQueue;
stack<int> EvenStack;
queue<int> EvenQueue;
int MyNumbers[10];
int InNum;
for(int i = 0; i < 10; i++)
{
cout << "Enter Number " << i << ": ";
cin >> InNum;
MyNumbers[i] = InNum;
if(InNum % 2 == 0)
{
EvenQueue.push(InNum);
EvenStack.push(InNum);
}
else
{
OddQueue.push(InNum);
OddStack.push(InNum);
}
}
cout << "Stack" << "\t\t" << "Queue" << endl;
return 0;
}
Assign it to tempstack
stack<int>tempStack = OddStack
and start poping from it and see what is inside
while(tempStack.empty() == false){
int x = tempStack.top();
cout << x << endl;
tempStack.pop();
}
same goes for the queue