Memory Heap and Leak Summary on Valgrind - c++

Our school submissions are all through matrix using valgrind, which checks the output line by line. However, when submitting, I'm getting "Memory Error Detected".
Compile result:
Success! No errors or warnings...
Execution:
Script started, file is student_output.txt
Script started, file is student_output.txt
==110143== Memcheck, a memory error detector
==110143== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==110143== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==110143== Command: ms
==110143==
Loading Data
Library Application:
When inputing data:
Publication Title: e
==111103== Conditional jump or move depends on uninitialised value(s)
==111103== at 0x404318: sdds::LibApp::search(int, char) (LibApp.cpp:145)
==111103== by 0x404ABC: sdds::LibApp::removePublication() (LibApp.cpp:329)
==111103== by 0x404DC1: sdds::LibApp::run() (LibApp.cpp:415)
==111103== by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==111103== by 0x405084: main (LibAppMain_prof.cpp:20)
==111103==
Other information
I also get error while adding a publication, (using the newPublication() function), which in the same file below.
==140314== Use of uninitialised value of size 8
==140314== at 0x404926: sdds::LibApp::newPublication() (LibApp.cpp:282)
==140314== by 0x404DAA: sdds::LibApp::run() (LibApp.cpp:411)
==140314== by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==140314== by 0x405084: main (LibAppMain_prof.cpp:20)
==140314==
==140314== Use of uninitialised value of size 8
==140314== at 0x40493F: sdds::LibApp::newPublication() (LibApp.cpp:284)
==140314== by 0x404DAA: sdds::LibApp::run() (LibApp.cpp:411)
==140314== by 0x404F6F: runLibApp(char const*) (LibAppMain_prof.cpp:9)
==140314== by 0x405084: main (LibAppMain_prof.cpp:20)
==140314==
The file is posted below.
LibApp.cpp
#define _CRT_SECURE_NO_WARNINGS
#include <fstream>
#include <iostream>
#include <fstream>
#include <cstring>
#include <iomanip>
#include "LibApp.h"
#include "Book.h"
#include "PublicationSelector.h"
namespace sdds {
int NOLP=0;
int LLRN=0;
bool LibApp::confirm(const char* message)
{
Menu conf(message);
conf<<"Yes";
int t_return = conf.run();
if(t_return) return true;
return false;
}
LibApp::LibApp(const char filename[256])
{
m_mainMenu << "Add New Publication"
<< "Remove Publication"
<< "Checkout publication from library"
<<"Return publication to library";
m_exitMenu << "Save changes and exit" << "Cancel and go back to the main menu";
strcpy(m_filename, filename);
m_publicationMenu << "Book" << "Publication" ;
load();
}
LibApp::~LibApp()
{
for (int i = 0; i< NOLP ; i++) {
delete PPA[i];
}
}
void LibApp::load(){
std::cout<<"Loading Data\n";
std::ifstream infile(m_filename);
char type{};
for (int i = 0; infile ; i++) {
infile >> type;
infile.ignore();
if (infile) {
if (type == 'P')
PPA[i] = new Publication;
else if (type == 'B')
PPA[i] = new Book;
else std::cout<<"no data\n";
if (PPA[i] && i < SDDS_LIBRARY_CAPACITY ) {
infile >> *PPA[i];
LLRN=PPA[i]->getRef();
NOLP++;
}
}
}
}
void LibApp::save(){
std::cout<<"Saving Data\n";
std::ofstream outfile(m_filename);
for (int i = 0; i < NOLP; i++) {
if (PPA[i]->getRef()!=0) {
outfile << *PPA[i] << std::endl;
}
}
}
void prnPub(Publication* p[], int size, int ref) {
int i;
for (i = 0; i < size; i++) {
if (ref == p[i]->getRef()) {
std::cout << *p[i] << std::endl;
i = size;
}
}
}
int LibApp::search(int option,char type){
PublicationSelector ps("Select one of the following found matches:", 15);
std::cout<<"Publication Title: ";
char title[256];
std::cin.getline(title,256);
if(option==1)
{
for (int i = 0; i< NOLP; i++) {
if (strstr(*PPA[i],title) && PPA[i]->getRef()!=0 && type==PPA[i]->type())
ps << PPA[i];
}
}
else if(option==2)
{
for (int i = 0; i< NOLP; i++) {
if (strstr(*PPA[i],title) && !PPA[i]->onLoan() && PPA[i]->getRef()!=0 && type==PPA[i]->type())
ps << PPA[i];
}
}
else if(option==3)
{
for (int i = 0; i< NOLP; i++) {
if (strstr(*PPA[i],title) && PPA[i]->onLoan() && PPA[i]->getRef()!=0 && type==PPA[i]->type())
ps << PPA[i];
}
}
int ref = 0;
if (ps) {
ps.sort();
ref = ps.run();
if (ref) {
prnPub(PPA, NOLP , ref);
}
else {
std::cout << "Aborted!\n";
}
}
else {
std::cout << "No matches to found!" << std::endl;
}
return ref;
}
void LibApp::returnPub()
{
std::cout<<"Return publication to the library\n";
int i=m_publicationMenu.run();
char type;
if(i==1) type='B';
else type='P';
int ref=search(3,type);
if(ref!=0 && confirm("Returning publication?"))
{
Date date=getPub(ref)->checkoutDate();
Date today;
int days=today-date;
days-=15;
if(days>0)
{
std::cout << std::fixed;
std::cout << std::setprecision(2);
std::cout<<"Please pay $"<<float(days)*(0.5)<<" penalty for being "<<days<<" days late!\n";
}
getPub(ref)->set(0);
std::cout<<"Publication returned\n";
m_changed=true;
}
}
void LibApp::newPublication()
{
if( NOLP >= SDDS_LIBRARY_CAPACITY )
{
std::cout<<"Library is at its maximum capacity!\n";
return;
}
std::cout<<"Adding new publication to library\n";
int i=m_publicationMenu.run();
Publication *p=nullptr;
if(i==0)
{ std::cout<<"Aborted!\n";
return;
}
else if(i==1)
{
p = new Book;
std::cin >> *p;
}
else if( i==2 )
{
p = new Publication;
std::cin >> *p;
}
if(std::cin.fail())
{
std::cout<<"\nAborted!\n";
exit(0);
}
if(confirm("Add this publication to library?"))
{
m_changed = true;
PPA[NOLP]=p;
LLRN=PPA[NOLP]->getRef();
NOLP++;
std::cout<<"Publication added\n";
}
if( !*p )
{
std::cout<<"Failed to add publication!\n";
delete p;
}
}
Publication* LibApp::getPub(int libRef)
{
for(int i=0;i<NOLP;i++)
{
if(libRef==PPA[i]->getRef()) return PPA[i];
}
return nullptr;
}
void LibApp::removePublication()
{
//std::cout<<;
std::cout<<"Removing publication from the library\n";
int i=m_publicationMenu.run();
char type;
if(i==1) type='B';
else
{
type='P';
}
int ref=search(1,type);
if(ref!=0 && confirm("Remove this publication from the library?"))
{
m_changed = true;
getPub(ref)->setRef(0);
std::cout<<"Publication removed\n";
}
}
void LibApp::checkOutPub()
{
std::cout<<"Checkout publication from the library\n";
int i=m_publicationMenu.run();
char type;
if(i==1) type='B';
else type='P';
int ref=search(2,type);
if(ref!=0 && confirm("Check out publication?"))
{
m_changed = true;
int mn;
std::cout << "Enter Membership Number: ";
while (1)
{
std::cin>>mn;
if(mn > 9999 && mn <= 99999 ) break;
std::cout<<"Invalid membership number, try again: ";
}
getPub(ref)->set(mn);
std::cout<<"Publication checked out\n";
}
}
LibApp::LibApp()
{
m_mainMenu << "Add New Publication"
<< "Remove Publication"
<< "Checkout publication from library"
<<"Return publication to library";
m_exitMenu << "Save changes and exit" << "Cancel and go back to the main menu";
load();
}
void LibApp::run()
{
while(1)
{
int option = m_mainMenu.run();
if( option == 1 )
{
newPublication();
}
else if( option == 2 )
{
removePublication();
}
else if( option == 3 )
{
checkOutPub();
}
else if( option == 4 )
{
returnPub();
}
else if( option == 0 )
{
if(m_changed)
{
int opn = m_exitMenu.run();
if( opn == 1 )
{
save();
break;
}
else if( opn == 2 )
{
;
}
else if( opn == 0)
{
if(confirm("This will discard all the changes are you sure?"))
break;
}
}
else break;
}
std::cout<<std::endl;
}
std::cout<<std::endl;
std::cout<<"-------------------------------------------\n";
std::cout<<"Thanks for using Seneca Library Application\n";
}
}
Please help me with this. My submission is today idk what the issues are.

Like the error message says:
Conditional jump or move depends on uninitialised value(s)
==111103== at 0x404318: sdds::LibApp::search(int, char) (LibApp.cpp:145)
There is an if-statement (or something logically equivalent to an if-statement) at line 145 of LibApp.cpp that is basing its decision on which path to take on a variable that was never initialized to any value; as such, the behavior of that if-test is undefined (ie if could go either way depending on what arbitrary data happens to be present at that variable’s memory location at the time).
So you’ll need to look at the variable(s) present in the if-test at line 145 to figure out which ones aren’t being set beforehand, and then fix the error by making sure they do get set first.
If necessary, you can add temporary if-tests just to provoke valgrind into giving you more results:
if (some_suspect_var != 0) fprintf(stderr, “Yea\n”);
else fprintf(stderr, “Nay\n”);
… then if you get a valgrind error on that if-line, you know that some_suspect_var is uninitialized at that point.

Related

How can my code react to unexpected inputs in c++?

Newbe so please don't be to harsh, I'll try to explain my problem as well as possible.
I have a longer code, that receives 0, 1, or n, arguments as input.
These inputs are supposed to be strings, however if I run my program like this:
./task2 ^!..;:
I simply get:
bash: !..: event not found
how can I prevent this error, and just print an error message?
This is task2.cpp
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <array>
#include <functional>
#include <math.h>
#include <stdint.h>
using namespace std;
/// Build suffix array from text.
/// Input is an emtpy suffix array and the text.
/// Output is a suffix array (sorted).
void construct(std::vector<uint32_t>& sa, const std::string& text)
{
if(text.empty()) {
cout << "Text is empty" << endl;
return;
}
if (sa.size()!=0) {
sa.clear();
}
for (uint32_t a = 0; a<text.length(); ++a) {
sa.push_back(a);
}
sort(sa.begin(),sa.end(),[&text] (uint32_t s1, uint32_t s2) {
return(text.substr(s1)<=text.substr(s2));
});
return;
}
//Wir brauchen kein $ am Ende unseres Strings, da wir keinen Suffixbaum aufbauen und wir somit nicht das Problem haben
//werden, dass ein Suffix ein Prefix eines aderen Suffix ist.
/// search for a 'query' string in a suffix array 'sa' build from 'text'.
/// Results are returned in 'hits'.
void findmlr(uint32_t& mlr, const uint32_t L, const uint32_t R, const std::string& query, const std::vector<uint32_t>& sa, const std::string& text) {
uint32_t mlrl = mlr;
uint32_t mlrr = mlr;
/* for L */
for(uint32_t l = mlr; l<query.size(); ++l) {
if (query[mlr] == text[sa[L]+mlrl]) {
mlrl+=1;
}
else{
break;
}
}
/* for R */
for(uint32_t r = mlr; r<query.size(); ++r) {
//cout << query[mlr] << text[sa[R]+mlrr] << endl;
if (query[mlr] == text[sa[R]+mlrr]) {
mlrr+=1;
}
else{
break;
}
}
mlr = min(mlrl,mlrr);
return;
}
void find(std::vector<uint32_t>& hits, const std::string& query, const std::vector<uint32_t>& sa, const std::string& text){
if(hits.size()!=0) {
hits.clear();
}
if (cin.fail()) {
cin.clear();
cout << "unexpected input" << endl;
}
if (text.size()==0) {
cout << "text is empty";
return;
}
else if (query.size()==0) {
cout << "query is empty";
return;
}
/* finding Lp */
uint32_t Lp;
if (query <= text.substr(sa[0])){
Lp = 0;
}
else if (query > text.substr(sa[text.length()-1])){
Lp = text.length();
}
else {
uint32_t L = 0;
uint32_t R = text.length()-1;
uint32_t mlr = 0;
while (R-L > 1) {
uint32_t M = ceil((L+R)/2);
findmlr(mlr,L,R,query,sa,text);
if (query.substr(mlr) <= (text.substr(sa[M]+mlr))) {
R = M;
}
else {
L = M;
}
}
Lp = R;
}
for (uint32_t i = Lp; i < text.length(); ++i) {
if ((text.substr(sa[i])).substr(0,query.length()) == query) {
if(find(hits.begin(), hits.end(), sa[i]) != hits.end()){
//do nothing
}
else{
hits.push_back(sa[i]);
}
}
else {
break;
}
}
sort(hits.begin(), hits.end());
return;
}
and this is task2_main.cpp
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include "aufgabe2.hpp"
#include <stdint.h>
//#include <typeinfo>
using namespace std;
int main(int argc, char* argv[]){
if (argc < 2){
cout << "not enough arguments were given" << endl;
return 1;}
if (argc == 2){
vector<uint32_t> sa;
string input_string(argv[1]);
construct(sa,input_string);
for(uint32_t i = 0; i<input_string.length(); ++i) {
cout << sa[i] << endl;
}
return 0;
}
if (argc > 2){
vector<uint32_t> hits;
string text(argv[1]);
vector<uint32_t> sa;
if (sa.size() != 0) {
sa.clear();
}
if (hits.size() != 0) {
hits.clear();
}
int z;
z = 2;
while(z < argc){
/*
if(typeid(argv[z])!=typeid(text)) {
cout << typeid(text).name() << z << " is not of type string" << endl;
}
*/
if (sa.size()!=0) {
sa.clear();
}
for (int unsigned a = 0; a<text.length(); ++a)
{
sa.push_back(a);
}
sort(sa.begin(),sa.end(),[&text] (uint32_t s1, uint32_t s2) {
return(text.substr(s1)<=text.substr(s2));
});
string query(argv[z]);
string input_string(argv[1]);
if (query.size() == 0) {
//do nothing
}
else if (input_string.size() == 0) {
//do nothing
}
else {
cout << (argv[z]) << ":";
}
find(hits,query,sa,input_string);
for (uint32_t i = 0; i < hits.size(); ++i) {
cout << " " << hits[i];
}
cout << endl;
++z;
}
}
return 0;
}
"Bash event not found" is completely external to your program; GNU Bash has a (mis)feature whereby it reacts to the ! character in a command line, even if that character is in a double-quote.
$ echo "blah!blah!"
bash: !blah!: event not found
$ echo 'blah!blah!'
blah!blah!
Note that in the first case, echo is not even called; Bash failed to process the command line as such, and echo was never invoked. If you see this message, your program is not being called at all and so the situation doesn't speak to how your program handles any kind of input.
You have to escape the ! with single quotes or a backslash. What Bash is trying to do here is to look for blah in the command history for a command which begins with blah and substitute it. This is "history expansion".
The feature is fully described under HISTORY EXPANSION in the Bash manual page.

Terminate called after throwing an instance of std::bad_alloc. Using two classes, one with a pointer to the other

My program keeps getting me bad alloc error when I use a normal function that contains a member function.
The program is about taking some specific inputs from the command line and printing the elements of an array of pointers. This has to be done with array of pointers.
To begin with, I created a class that needs to have 2 strings. One for the name and one for the room. Then I created another class with a size and a pointer to my first class in order to create an array.
My main is at the end, and above main are the 2 normal functions. What is wrong with this code? When I type the commands for the first time of the loop it works until I enter a command that connects to a normal function. Probably something is wrong there but I can't seem to find it.
#include <iostream>
#include <string>
using namespace std;
class Address
{
private:
string name;
string room;
public:
Address(){};
Address(string, string);
string get_name();
string get_room();
void change_room(string);
};
Address::Address (string n, string r)
{
name = n;
room = r;
}
string Address::get_name()
{
return name;
}
string Address::get_room()
{
return room;
}
void Address::change_room(string change)
{
room = change;
}
//end of Address class
class Address_Book
{
private:
int size;
Address* addresses;
public:
Address_Book();
~Address_Book(){ delete[] addresses;}
void add(Address);
void move(string, string);
int get_size();
Address location(int);
int find(string);
void clear();
void remove_address(string);
int exists(string);
void sort();
};
Address_Book::Address_Book()
{
int s = 0;
size = s;
addresses = new Address[s];
}
void Address_Book::add(Address add)
{
Address* temp = new Address [size + 1];
for (int i = 0; i < size; i++)
{
temp[i] = addresses[i];
}
temp[size] = add;
delete[] addresses;
addresses = temp;
size ++;
}
void Address_Book::move(string name, string newroom)
{
for (int i = 0; i < size ; i++)
{
if (addresses[i].get_name() == name )
{
addresses[i].change_room(newroom);
}
}
}
void Address_Book::remove_address(string name)
{
Address* temp = new Address [size - 1];
for (int i = 0; i < size; i++)
{
if (addresses[i].get_name() != name)
{
temp[i] = addresses[i];
}
else if (addresses[i].get_name() == name)
{
for (int j = i + 1; j < size; j++)
{
temp[i] = addresses[j];
i++;
}
break;
}
}
delete[] addresses;
addresses = temp;
size--;
}
int Address_Book::get_size()
{
return size;
}
Address Address_Book::location(int index)
{
return addresses[index];
}
void Address_Book::sort()
{
Address temp;
for (int i = 0; i < size; i++)
{
for(int j = 0; j < size - 1; j++)
{
if (addresses[j].get_room() > addresses[j + 1].get_room())
{
temp = addresses[j];
addresses[j] = addresses[j + 1];
addresses[j + 1] = temp;
}
}
}
for (int i = 0; i < size; i++)
{
if (addresses[i].get_room() == addresses[i + 1].get_room())
{
if (addresses[i].get_name() > addresses[i + 1].get_name())
{
temp = addresses[i];
addresses[i] = addresses[i + 1];
addresses[i + 1] = temp;
}
}
}
}
void Address_Book::clear()
{
Address * temp = new Address[0];
delete[] addresses;
addresses = temp;
size = 0;
}
int Address_Book::find(string name)
{
for (int i = 0; i < size; i++)
{
if (addresses[i].get_name() == name)
{
return i;
}
}
return -1;
}
//end of Address_Book class
void find(string name, Address_Book addbook)
{
int index = addbook.find(name);
cout << index << endl;
if (index > -1)
{
cout << addbook.location(index).get_name() << " is in room " <<
addbook.location(index).get_room() << endl;
}
else
{
throw runtime_error("entry does not exist.");
}
}
void remove_add(string name, Address_Book book)
{
int exist = book.find(name);
if (exist > -1)
{
book.remove_address(name);
}
else
{
throw runtime_error("entry does not existt.");
}
}
int main()
{
Address_Book addbook;
string action, in_name, in_room;
do
{
try
{
cout << "> ";
cin >> action;
if (action == "add")
{
cin >> in_name >> in_room;
Address newadd(in_name, in_room);
addbook.add(newadd);
}
else if (action == "move")
{
cin >> in_name >> in_room;
addbook.move(in_name, in_room);
}
else if (action == "remove")
{
cin >> in_name;
remove_add(in_name, addbook);
}
else if (action == "find")
{
cin >> in_name;
find(in_name, addbook);
}
else if (action == "list")
{
addbook.sort();
for (int i = 0; i < addbook.get_size(); i++)
{
cout << addbook.location(i).get_name() << " is in room
" << addbook.location(i).get_room() << endl;
}
}
else if (action == "clear")
{
addbook.clear();
}
else
{
throw runtime_error("input mismatch.");
}
}
catch (runtime_error& e)
{
cerr << "error: " << e.what() << endl;
}
}while (action != "exit");
return 0;
}
The function remove_add needs to get the address book object by reference or by pointer.
The way it is now, it removes from a copy of the address book.
It should look like this:
void remove_add(string name, Address_Book& book)
{
int exist = book.find(name);
if (exist > -1)
{
book.remove_address(name);
}
else
{
throw runtime_error("entry does not existt.");
}
}
Also, you should probably do something different in case size == 1 in the following function. e.g. set addresses to NULL, zero or nullptr if your compiler supports it.
void Address_Book::remove_address(string name)
{
Address* temp = new Address[size - 1];
for (int i = 0; i < size; i++)
{
if (addresses[i].get_name() != name)
{
temp[i] = addresses[i];
}
else if (addresses[i].get_name() == name)
{
for (int j = i + 1; j < size; j++)
{
temp[i] = addresses[j];
i++;
}
break;
}
}
delete[] addresses;
addresses = temp;
size--;
}
Have fun learning the language and good luck :)
The exact commands that lead to your problem are not specified in your question, so I poked around a little bit until the code crashed with a segmentation fault.
Valgrind and Dr. Memory are awesome tools for finding root causes of such problems. In your case:
$ g++ -g 46865300.cpp
$ valgrind ./a.out
> add foo bar
> list
==102== Invalid read of size 8
==102== at 0x4EF4EF8: std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(std::string const&) (in /usr/lib64/libstdc++.so.6.0.19)
==102== by 0x401354: Address::get_room() (46865300.cpp:33)
==102== by 0x401C05: Address_Book::sort() (46865300.cpp:152)
==102== by 0x4026A3: main (46865300.cpp:262)
==102== Address 0x5a17410 is 8 bytes after a block of size 24 alloc'd
==102== at 0x4C2A8A8: operator new[](unsigned long) (vg_replace_malloc.c:423)
==102== by 0x4014BF: Address_Book::add(Address) (46865300.cpp:74)
==102== by 0x40245C: main (46865300.cpp:243)
It says that the following code performs out-of-bounds access:
150 for (int i = 0; i < size; i++)
151 {
152 if (addresses[i].get_room() == addresses[i + 1].get_room())
153 {
154 if (addresses[i].get_name() > addresses[i + 1].get_name())
I guess the loop condition should use "size - 1" instead of "size".

Error with strcoll (C++)

I want to sort a vector of strings into order alphabetically. I have coded thus far and I can not resolve the error for strcoll. Also, I am not allowed to use algorithm library. The error can be seen in the bubbub function where I am trying to bubble sort.
I have a few functions that should explain themselves with their names
#include <iostream>
#include <string.h>
#include <vector>
#include <stdio.h>
using namespace std;
inline void swap(string & a, string & b)
{
string c = b;
b = a;
a = c;
return;
}
void input_name(string&);
void sort_names(string&);
void repeat_pro(int&);
void sortArray(string, int);
void print_names(vector<string>& b_list);
void bubbub(vector<string> & b_list);
int main() {
vector<string> b_list;
string name;
int choice;
int count=0;
cout << "Welcome to the Business Sorting Program!" << endl;
do{
input_name(name);
b_list.push_back(name);
count++;
repeat_pro(choice);
bubbub(b_list);
cout<<"\n \n Your Businesses are:"<<endl;
for(int i=0; i < b_list.size() ; i++){
cout<<b_list[i]<<"\n";
}
cout << "\n\n";
}while(choice == 0);
cout << "Thanks for using this program"<<endl;
return 0;
}
void input_name(string &name){
cout << "Enter in the name of the business: ";
getline(cin, name);
}
void sort_names(string &name){
}
void repeat_pro(int &choice){
cout << "Do you want to enter in more names: ";
string answ;
cin>>answ;
cin.ignore(1000,'\n');
for (int x=0; x<answ.size(); x++){
answ[x] = tolower(answ[x]);
}
if (answ == "yes" || answ == "y"){
choice = 0;
}
else {
choice = 1;
}
}
void bubbub(vector<string> & b_list)
{
vector<string>::size_type loop = 0;
bool done = false;
while ((loop+1 < b_list.size()) && ! done)
{
done = true;
for (vector<string>::size_type count = 0;
count+1 != b_list.size(); count++)
{
string x;
string z;
x = b_list[count];
z= b_list[count+1];
if ( strcoll (x,z) < 0 )
{
swap( b_list[count], b_list[count+1] ); // swap
done = false;
}
}
loop++;
}
return;
}
I fixed it by converting my string into a list of chars. then compared them and swapped the vector based on the results. Thanks for the help guys
void bubbub(vector<string> & b_list)
{
vector<string>::size_type loop = 0;
bool done = false;
while ((loop+1 < b_list.size()) && ! done)
{
done = true;
for (vector<string>::size_type count = 0;
count+1 != b_list.size(); count++)
{
string x;
string z;
char array[50];
char array2[50];
x = b_list[count];
z= b_list[count+1];
strncpy(array, x.c_str(), sizeof(x));
strncpy(array2, z.c_str(), sizeof(z));
if ( strcoll (array,array2) > 0 )
{
swap(b_list[count+1], b_list[count] ); // swap
done = false;
}
}
loop++;
}
return;
}
You can use std::string::compare instead of strcoll
#include <iostream>
#include <vector>
#include <stdio.h>
#include <cstring>
using namespace std;
inline void swap(string & a, string & b)
{
string c = b;
b = a;
a = c;
return;
}
void input_name(string&);
void sort_names(string&);
void repeat_pro(int&);
void sortArray(string, int);
void print_names(vector<string>& b_list);
void bubbub(vector<string> & b_list);
int main() {
vector<string> b_list;
string name;
int choice;
int count=0;
cout << "Welcome to the Business Sorting Program!" << endl;
do{
input_name(name);
b_list.push_back(name);
count++;
repeat_pro(choice);
bubbub(b_list);
cout<<"\n \n Your Businesses are:"<<endl;
for(int i=0; i < b_list.size() ; i++){
cout<<b_list[i]<<"\n";
}
cout << "\n\n";
}while(choice == 0);
cout << "Thanks for using this program"<<endl;
return 0;
}
void input_name(string &name){
cout << "Enter in the name of the business: ";
getline(cin, name);
}
void sort_names(string &name){
}
void repeat_pro(int &choice){
cout << "Do you want to enter in more names: ";
string answ;
cin>>answ;
cin.ignore(1000,'\n');
for (int x=0; x<answ.size(); x++){
answ[x] = tolower(answ[x]);
}
if (answ == "yes" || answ == "y"){
choice = 0;
}
else {
choice = 1;
}
}
void bubbub(vector<string> & b_list)
{
vector<string>::size_type loop = 0;
bool done = false;
while ((loop+1 < b_list.size()) && ! done)
{
done = true;
for (vector<string>::size_type count = 0;
count+1 != b_list.size(); count++)
{
string x;
string z;
x = b_list[count];
z = b_list[count+1];
if (z.compare(x) != 0 )
{
swap( b_list[count], b_list[count+1] ); // swap
done = false;
}
}
loop++;
}
return;
}
Output
Welcome to the Business Sorting Program!
Enter in the name of the business: hello
Do you want to enter in more names: yes
Your Businesses are:
hello
Enter in the name of the business: apple
Do you want to enter in more names: no
Your Businesses are:
apple
hello
Thanks for using this program
Program ended with exit code: 0

C++ Stack values not working correctly

I am trying to implement a system that would perform something like say the user enters 4 5 +. It would add the 4 and 5 (9) and push 9 into the stack.
For some reason the values in the stack are huge numbers so I believe it has something to do with a pointer or accessing a wrong field but I'm pulling my hair out trying to find the error. Any help on what I'm doing wrong?
#include "stack.h"
int main()
{
stack Test;
bool stop = false;
float runningtotal = 0;
while (stop == false)
{
char input;
cin >> input;
if (input == '+') {
int value1 = Test.top();
Test.pop();
int value2 = Test.top();
Test.pop();
cout << value1+value2 << endl;
Test.push(value1 + value2);
}
cout << Test.top();
std::getchar();
std::getchar();
}
And the implementation of stack
#include "stack.h"
stack::stack()
{
maxsize = MaxSize;
currentsize = 0;
sptr = new StackElement[maxsize];
}
stack::~stack()
{
delete [] sptr;
}
void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++;
} else {
cout << "Stack is full ;-;";
}
}
void stack::pop()
{
if (currentsize == 0) {
cout << "Empty stack? ;-;";
return;
}
currentsize--;
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);
}
}
void stack::push(StackElement data)
{
if (currentsize < maxsize)
{
sptr[currentsize] = data;
currentsize++; //<--- incrementing after so nothing in [currentsize] now
} else {
cout << "Stack is full ;-;";
}
}
StackElement stack::top()
{
if (currentsize == 0) {
cout << "Empty stack u ninja ;-;";
return NULL;
} else {
return (sptr[currentsize]);// should use currentsize-1
// latest filled cell
// since its pushing from top
}
}
Be sure to convert those ascii codes(49 ish) from keyboard to integer type explanations.
input - 48 should do it.

C++ Infix to Postfix program, Stack is continuously empty?

I'm working on a program for a computer science class. I have everything completed and separated into the interface/implementation and for some reason, the program loops infinitely and says "Stack is empty!" after the peek() function is called.
I've tried inserting cout << statements to see if I can pinpoint the issue, however, no luck. I would appreciate it if someone else could take a look at it.
Thank You
Header
#ifndef STACK_H
#define STACK_H
/////////////////////////////////////////////////////
////Includes/////////////////////////////////////////
/////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <stdlib.h>
#include <iomanip>
#include <sstream>
#include <stdio.h>
/////////////////////////////////////////////////////
using namespace std;
/*-------------------------------------------------------------------------------------------------------------*/
template <typename Object>
class Stack
{
private:
class stackListNode
{
public:
Object data;
stackListNode *next;
private:
//Nothing to declare-->placeholder since class
//sets data members to private initially
};
stackListNode *top;
public:
/////////////////////////////////////////////////
//Constructor Function//////////////////////////
Stack() {top = NULL;}
/////////////////////////////////////////////////
//Rest of functions defined inline for simplicity
void push(char token) // Push token onto the stack and create new node for top of stack
{
stackListNode *newNode = new stackListNode;
newNode->data = token;
newNode->next = top;
top = newNode;
}
int pop()
{
if(empty())
{
cout << "Stack is empty!\n" << endl;
return NULL;
}
stackListNode *temp = top;
top = temp->next;
}
char peek()
{
if(empty())
{
cout << "Stack is empty!\n" << endl;
return NULL;
}
return top->data;
}
int empty()
{
return top == NULL;
}
};
#endif
Main File:
/////////////////////////////////////////////////////
////Includes/////////////////////////////////////////
/////////////////////////////////////////////////////
#include <iostream>
#include <fstream>
#include <string>
#include "Stack.h"
/////////////////////////////////////////////////////
using namespace std;
int precendence(char stack_beginning); //ensures order of operations.
int precendence(char*myArray);
void InFixToPostfix(ifstream& in_file);
double EvaluatePostfix(double first_operand, double second_operand, char*myArray);
int main()
{
////VARS/////////////////////////////////////////////
string absolutePath;
cout << endl;
cout << "Please type in the name of the file you would to open \n";
cin >> absolutePath;
ifstream in_file;
in_file.open(absolutePath.c_str());
if(!in_file)
{
cout << "failed to open input file\n" ;
return 1 ;
}
else
{
InFixToPostfix(in_file); //kicks off program
}
}
void InFixToPostfix(ifstream& in_file)
{
string infix;
int right_parentheses =0;
int left_parentheses =0;
while(getline(in_file, infix))
{
char myArray[infix.size()];
strcpy(myArray, infix.c_str());
for(int i = 0; i < sizeof(myArray); i++)
{
if(myArray[i] == '(')
{
right_parentheses++;
}
if(myArray[i] == ')')
{
left_parentheses++;
}
}
if(right_parentheses!=left_parentheses)
{
cout << endl;
cout << "There is a typo in one of the expressions in your file \n";
cout << "Please fix it and rerun the program \n";
exit(1);
}
for(int i = 0; i < sizeof(myArray); i++)
{
//int number = int(myArray[i]);
//deferences the pointer and reads each char in the array
//as an int rather than a character.
//int number = myArray[i];
if(isxdigit(myArray[i]) > 0) //function used to check for hexidecimal values (i.e. int's)
{
goto exit_out;
}
else if(myArray[i] == '(' || myArray[i] == ')' || myArray[i] == '+' || myArray[i] == '-' || myArray[i] == '*' || myArray[i] == '/' || myArray[i] == '\\' || myArray[i] == '\n')
{
goto exit_out;
}
else if(myArray[i] == char(32)) //checks to see if there is a space
{
goto exit_out;
}
else
{
cout << endl;
cout << "There is an invalid character in the file\n";
exit(1);
}
exit_out:;
}
////////Declares a STRING Stack////////////////////////////////
Stack<char> stack_string;
////////Declares an Int Stack/////////////////////////////////
Stack<int> stack_int;
//////////////////////////////////////////////////////////////
for(int i = 0; i < sizeof(myArray); i++)
{
int number = isxdigit(myArray[i]);
if(number > 0)
{
cout << number;
//outputs the number b/c it is an operand
}
if(myArray[i] == '(')
{
stack_string.push(myArray[i]);
}
if(myArray[i] == ')')
{
//cout << "test";
while(stack_string.peek() != '(')
{
cout << stack_string.peek();
stack_string.pop(); //pops to the peek
}
stack_string.pop(); // if there is a ), pops to the peek
}
if(myArray[i] == '+' || myArray[i] == '-' || myArray[i] == '/' || myArray[i] == '*')
{
if(stack_string.empty())
{
stack_string.push(myArray[i]); //if there's nothing on the stack, pushes the current character
//goto done;
break; //breaks out of the statement
}
char stack_beginning = stack_string.peek();
int stack_top = precendence(stack_beginning);
//int stack_top = precendence(stack_string.peek());
int operatorHierarchy = precendence(myArray);
//must be declared here because i will have been interated through array
if(operatorHierarchy > stack_top)
{
stack_string.push(myArray[i]);
}
else if(operatorHierarchy <= stack_top) //could also be an if
{
dump_out:;
cout << stack_string.peek();
stack_string.pop();
int rerunThroughStack =0;
char new_stack_beginning = stack_string.peek();
rerunThroughStack = precendence(new_stack_beginning);
if(operatorHierarchy < stack_top)
{
stack_string.push(myArray[i]);
goto done; //could break
}
if(stack_string.peek() == '(')
{
stack_string.push(myArray[i]);
goto done;
}
if(stack_string.empty())
{
stack_string.push(myArray[i]);
goto done;
}
goto dump_out;
}
}
done:;
}
cout << stack_string.peek() << endl;
//////////Evaluate Section/////////////////////////////
for(int i = 0; i < sizeof(myArray); i++)
{
if(isxdigit(myArray[i]) > 0) //this is a number
{
stack_int.push(isxdigit(myArray[i]));
goto end;
}
else if(myArray[i] == '*' || myArray[i] == '+' || myArray[i] == '-' || myArray[i] == '/')
{
double first_operand;
first_operand = stack_int.peek(); //fetches first operand on the stack_int
stack_int.pop();
//////////////////
double second_operand;
second_operand = stack_int.peek();
stack_int.pop();
//////////////////
double answer;
answer = EvaluatePostfix(first_operand, second_operand, myArray); //THIS PROBABLY IS NOT RIGHT
stack_int.push(answer);
}
end:;
}
/*
int size_of_stack;
size_of_stack = stack_int.size();
if(size_of_stack == 1)
{
cout << stack_int.peek();
}
*/
}
}
double EvaluatePostfix(double first_operand, double second_operand, char* myArray) //might have to pass array as reference
{
/*
Cycle through the characters passed in through myArray[i];
*/
for(int i = 0; i < sizeof(myArray); i++)
{
if(myArray[i] == '*')
{
double first_answer;
first_answer = (second_operand * first_operand);
return first_answer;
}
else if(myArray[i] == '/')
{
double second_answer;
second_answer = (second_operand / first_operand);
return second_answer;
}
else if(myArray[i] == '+')
{
double third_answer;
third_answer = (second_operand + first_operand);
return third_answer;
}
else if(myArray[i] == '-')
{
double fourth_answer;
fourth_answer = (second_operand - first_operand);
return fourth_answer;
}
/*
else
{
cout << "There must be an error in your file" <<endl;
break;
exit(1);
}
*/
}
}
int precendence(char stack_beginning)
{
int precendence;
if(stack_beginning == '*' || stack_beginning == '/')
{
precendence = 2;
return precendence;
}
//by making it 2, the precendence is dubbed less than +/-
if(stack_beginning == '+' || stack_beginning == '-')
{
precendence = 1;
return precendence;
}
} //by making it 1, the precendence is dubbed greater than */"/"
int precendence(char*myArray)
{
int precendence;
for(int i = 0; i < sizeof(myArray); i++)
{
if(myArray[i] == '*' || myArray[i] == '/')
{
precendence = 2;
return precendence;
}
//by making it 2, the precendence is dubbed less than +/-
if(myArray[i] == '+' || myArray[i] == '-')
{
precendence = 1;
return precendence;
}
} //by making it 1, the precendence is dubbed greater than */"/"
}