Floating Point Exception while reading from file - c++

the program should read from 2 files (author.dat and citation.dat) and save them into a map and set;
first it reads the citationlist without problem, then it seems to properly read the authors and after it went through the whole list (author.dat) a floating point exception arises .. can't quite figure out why
seems to happen in author.cpp inside the constructor for authorlist
author.cpp:
#include <fstream>
#include <iostream>
#include "authors.h"
using namespace std;
AuthorList::AuthorList(char *fileName) {
ifstream s (fileName);
int idTemp;
int nrTemp;
string nameTemp;
try {
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
} catch (EOFException){}
}
author.h:
#ifndef CPP_AUTHORS_H
#define CPP_AUTHORS_H
#include <iostream>
#include <map>
#include <string>
#include "citations.h"
class Author {
public:
Author (int id, int nr, std::string name) :
articleID(id),
authorNR(nr),
authorName(name){}
int getArticleID() const {
return articleID;
}
std::string getAuthorName() const {
return authorName;
}
private:
int articleID;
int authorNR;
std::string authorName;
};
class AuthorList {
public:
AuthorList(char *fileName);
std::pair<std::multimap<int,Author>::const_iterator, std::multimap<int,Author>::const_iterator> findAuthors(int articleID) {
return authors.equal_range(articleID);
}
private:
std::multimap<int,Author> authors;
};
#endif //CPP_AUTHORS_H
programm.cpp:
#include <iostream>
#include <cstdlib>
#include "citations.h"
#include "authors.h"
#include "authorCitation.h"
using namespace std;
int main(int argc, char *argv[]){
CitationList *cl;
AuthorList *al;
//check if argv array has its supposed length
if (argc != 4){
cerr << "usage: programm article.dat citation.dat author.dat";
return EXIT_FAILURE;
}
//inserting citation.dat and author.dat in corresponding lists (article.dat not used)
cl = new CitationList(argv[2]);
al = new AuthorList(argv[3]);
try {
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
acl->printAuthorCitationList2File("authorcitation.dat");
} catch (EOFException){
cerr << "something went wrong while writing to file";
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
All files:
https://drive.google.com/file/d/0B734gx5Q_mVAV0xWRG1KX0JuYW8/view?usp=sharing

I am willing to bet that the problem is caused by the following lines of code:
AuthorCitationList *acl;
acl->createAuthorCitationList(al,cl);
You are calling a member function using an uninitialized pointer. I suggest changing the first line to:
AuthorCitationList *acl = new AuthorCitationList;
Add any necessary arguments to the constructor.
While you are at it, change the loop for reading the data also. You have:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << "WHILE-LOOP_END" << endl;
}
When you do that, you end up adding data once after the end of line has been reached. Also, you seem to have the last line in the wrong place. It seems to me that it should be outside the while loop.
You can use:
while (true){
s >> idTemp >> nrTemp >> nameTemp;
// Break out of the loop when reading the
// data is not successful.
if (!s){
cout << "IF-CLAUSE";
throw EOFException();
}
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;
You can simplify it further by using:
while (s >> idTemp >> nrTemp >> nameTemp){
cout << idTemp << " " << nrTemp << " " << nameTemp << " test_string";
authors.insert(std::make_pair(idTemp,Author(idTemp,nrTemp,nameTemp)));
}
cout << "WHILE-LOOP_END" << endl;

Related

Function return nothing with multiple files?

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

Using virtual functions with classes and constructors to print book info

I'm at the very last step for this project, and I'm stuck on what to do. The project is to take an input file containing book info, like this:
A Book on C
Al Kelly and Ira Pohl
Addison-Wesley, Fifth Edition 1998.
0201183994
C How to Program
Paul Deitel and Harvey Deitel
Prentice Hall Sixth Edition 2010
0136123562
And then print it using several options. I'll put all the code here so you can compile and see what each option does. I'm having trouble with option 5, specifically. For option 5, I need to:
Input more information on each book. I'm required to have two subclasses, InfoBookRecord containing the price and author biography, and TypeBookRecord containing the book genre.
Print the new information using virtual functions. I thought it made sense to make the virtual function in the class ListRecords, but the grading key seems to imply I should be using them for the two subclasses InfoBookRecord and TypeBookRecord. I can't think of any way to do that.
header.h:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
using namespace std;
#define TABLE_SIZE 200
class BookRecord{
public:
BookRecord(string input_title, string input_author, string input_publisher, int input_isbn);
string getTitle();
string getAuthor();
string getPublisher();
int getISBN();
private:
string title;
string author;
string publisher;
int isbn;
};
class InfoBookRecord: public BookRecord {
public:
InfoBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, double input_price, string input_authorBio) : BookRecord(input_title,input_author,input_publisher,input_isbn) {
price=input_price;
authorBio=input_authorBio;}
double getPrice();
string getAuthorBio();
private:
double price;
string authorBio;
};
class TypeBookRecord: public BookRecord {
public:
TypeBookRecord(string input_title, string input_author, string input_publisher, int input_isbn, string input_genre) : BookRecord(input_title,input_author,input_publisher,input_isbn){
input_genre.resize(15);
genre=input_genre;}
string getGenre();
private:
string genre;
};
class ListRecords{
public:
ListRecords(char filename[]);
void insertBookInfo(BookRecord record);
//virtual void printBookInfo(int bookISBN);
void printBookInfo(int bookISBN);
void printListByISBN();
void printListByTitle();
BookRecord ** books;
InfoBookRecord ** books2;
TypeBookRecord ** books3;
int line_num;
int k;
string garbage;
};
// problem here
/*
class extraListRecords: public ListRecords{
public:
extraListRecords();
void printBookInfo(int bookISBN){
cout << "testing 1 2 3 " << endl;
}
};*/
BookRecord.cpp:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
BookRecord::BookRecord(string input_title, string input_author, string input_publisher, int input_isbn){
title=input_title;
author=input_author;
publisher=input_publisher;
isbn=input_isbn;
}
string BookRecord::getTitle() {return title;}
string BookRecord::getAuthor() {return author;}
string BookRecord::getPublisher() {return publisher;}
int BookRecord::getISBN() {return isbn;}
double InfoBookRecord::getPrice() {return price;}
string InfoBookRecord::getAuthorBio() {return authorBio;}
string TypeBookRecord::getGenre() {return genre;}
ListRecords.cpp:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
ListRecords::ListRecords(char filename[]){
ifstream input(filename);
assert(("Error: File does not exist.", input != NULL));
string line;
line_num=0;
while (getline(input,line)){
line_num++;
}
//go back to beginning of file
input.clear();
input.seekg(0, ios::beg);
char lines[TABLE_SIZE][TABLE_SIZE];
int i=0;
// load lines of file into array
while (i < line_num) {
input.getline(lines[i],TABLE_SIZE);
i++;
}
input.close();
books = new BookRecord*[TABLE_SIZE];
books2 = new InfoBookRecord*[TABLE_SIZE];
books3 = new TypeBookRecord*[TABLE_SIZE];
k=0;
for(i=0;i<line_num;i+=5){
// check for duplicate entries
int test=0;
for(int j=0;j<i/5;j++){
if(books[j]->getISBN() == atoi(lines[i+3])){
cout << "Found a duplicate ISBN... ignoring entry " << lines[i+3] << endl;
test=1;
}
}
// if not a duplicate entry, add to array
if(test==0){
int the_price;
cout << "Please enter price of " << lines[i] << ": " << endl;
cin >> the_price;
getline(cin,garbage);
string the_authorBio;
cout << "Please enter author bio of " << lines[i] << ": ";
cin >> the_authorBio;
getline(cin,garbage);
string the_genre;
cout << "Please enter the book genre of " << lines[i] << ": ";
cin >> the_genre;
getline(cin,garbage);
*(books2+k) = new InfoBookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]),the_price,the_authorBio);
*(books3+k) = new TypeBookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]),the_genre);
*(books+k) = new BookRecord(lines[i],lines[i+1],lines[i+2],atoi(lines[i+3]));
k++;
}
else
i+=5;
}
}
void ListRecords::insertBookInfo(BookRecord record){
line_num+=5;
*(books+k) = new BookRecord(record.getTitle(),record.getAuthor(),record.getPublisher(),record.getISBN());
k++;
}
void ListRecords::printBookInfo(int bookISBN){
int found=0;
for(int i=0;i<k;i++){
if(books[i]->getISBN() == bookISBN){
if(to_string(books[i]->getISBN()).length()==9)
cout << endl << books[i]->getTitle() << endl << books[i]->getAuthor() << endl << books[i]->getPublisher() << endl << "0" << books[i]->getISBN() << endl;
if(to_string(books[i]->getISBN()).length()==10)
cout << endl << books[i]->getTitle() << endl << books[i]->getAuthor() << endl << books[i]->getPublisher() << endl << books[i]->getISBN() << endl;
found=1;
break;
}
}
if(found==0)
cout << "The record you requested was not found in the list." << endl;
}
bool compare_by_isbn(BookRecord* x,BookRecord* y) { return (x->getISBN() < y->getISBN()); }
bool compare_by_title(BookRecord* x,BookRecord* y) { return (x->getTitle() < y-> getTitle()); }
void ListRecords::printListByISBN(){
sort(books, books + k, compare_by_isbn);
printf(" %-22s %-22s %-17s %s\n", "Title", "Author", "Publisher", "ISBN");
cout << string(22, '-') << " " << string(22, '-') << " " << string(22, '-') << " " << string(10, '-') << endl;
for(int i=0;i<k;i++){
if(to_string(books[i]->getISBN()).length()==9)
printf("%-22.22s %-22.22s %-22.22s 0%d\n", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
if(to_string(books[i]->getISBN()).length()==10)
printf("%-22.22s %-22.22s %-22.22s %d\n", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
}
}
void ListRecords::printListByTitle(){
sort(books, books + k, compare_by_title);
printf(" %-22s %-22s %-17s %s\n", "Title", "Author", "Publisher", "ISBN");
cout << string(22, '-') << " " << string(22, '-') << " " << string(22, '-') << " " << string(10, '-') << endl;
for(int i=0;i<k;i++){
if(to_string(books[i]->getISBN()).length()==9)
printf("%-22.22s %-22.22s %-22.22s 0%d\n", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
if(to_string(books[i]->getISBN()).length()==10)
printf("%-22.22s %-22.22s %-22.22s %d\n", books[i]->getTitle().c_str(), books[i]->getAuthor().c_str(), books[i]->getPublisher().c_str(), books[i]->getISBN());
}
}
main.cpp:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cassert>
#include <fstream>
#include <algorithm>
#include "header.h"
using namespace std;
#define TABLE_SIZE 200
int main(int argc, char* argv[]){
char filename[50];
cout << "Enter the name of a file to load:" << endl;
cin >> filename;
ListRecords listrecords(filename);
while(true){ // looping for the selection menu
int selection, n;
cout << "Please select a menu option:\n1) Insert a book record into the list\n2) Print information of a book with a given ISBN number\n3) Print the list of books sorted by ISBN\n4) Print the list of books sorted alphabetically by title\n5) Print the books also with info on price, author biography, and genre.\n6) Quit the program" << endl;
cin >> selection;
if(cin.fail()){ // make sure input is a digit
cout << "Invalid selection. Quitting program..." << endl;
break;
}
if(selection==1){
string in_title;
string in_author;
string in_publisher;
int in_isbn;
string junk;
getline(cin, junk);
cout << endl << "Please enter a title: ";
getline(cin, in_title);
cout << "Please enter an author: ";
getline(cin, in_author);
cout << "Please enter a publisher: ";
getline(cin, in_publisher);
cout << "Please enter an ISBN: ";
cin >> in_isbn;
BookRecord new_record(in_title, in_author, in_publisher, in_isbn);
listrecords.insertBookInfo(new_record);
cout << endl << "The record has been added to the list." << endl;
cout << endl << endl;
}
if(selection==2){
int in_isbn;
cout << endl << "Please enter ISBN number: " << endl;
cin >> in_isbn;
listrecords.printBookInfo(in_isbn);
cout << endl << endl;
}
if(selection==3){
cout << endl;
listrecords.printListByISBN();
cout << endl << endl;
}
if(selection==4){
cout << endl;
listrecords.printListByTitle();
cout << endl << endl;
}
if(selection==5){
int in_isbn;
cout << endl << "Please enter ISBN number: " << endl;
cin >> in_isbn;
cout << endl << "List of books also with info on price and author biography: " << endl;
cout << endl << endl;
// problem here
// extraListRecords extras;
//ListRecords *bookextras= &extras;
// bookextras->printBookInfo(in_isbn);
cout << endl << "List of books also with info on genre: " << endl;
}
if(selection==6){
cout << endl << "Program terminating normally..." << endl;
break;
}
} // end of while(true) loop
return 0;
};
Makefile:
LFLAGS = -Wno-write-strings -std=c++11
CFLAGS = -Wno-write-strings -std=c++11 -c
myprogam: main.o BookRecord.o ListRecords.o
g++ $(LFLAGS) -o myprogram main.o BookRecord.o ListRecords.o header.h
main.o: main.cpp header.h
g++ $(CFLAGS) main.cpp
BookRecord.o: BookRecord.cpp header.h
g++ $(CFLAGS) BookRecord.cpp
ListRecords.o: ListRecords.cpp header.h
g++ $(CFLAGS) ListRecords.cpp
clean:
rm *.o
rm myprogram
I commented out the two parts giving me trouble. One is at the end of header.h, and the other is near the end of main.cpp.
When I try to make this, I get the error
main.cpp:(.text+0x4c7): undefined reference to `extraListRecords::extraListRecords()'
collect2: error: ld returned 1 exit status
make: *** [myprogam] Error 1
I've tried a few other attempts at that subclass with the virtual function, such as adding the initialization of book2 and book3 to the body of its constructor, so writing its constructor as extraListRecords(char filename[]) :ListRecords(filename){ / the chunk of code in ListRecords.cpp above around line 55 / }
Thanks a bunch for the help!
You need to provide the constructor definition for extraListRecords
class extraListRecords: public ListRecords {
public:
extraListRecords() = default;
// ^^^^^^^^^^
};
I figured it out. The problem was pretty silly. I just forgot to flush the buffer between cin on an integer and getline.
cin and getline skipping input
The virtual function was completely fine as extraListRecords(char filename[]): ListRecords(filename){;} as the constructor in the header.

ifstream i cant write and read at the same time c++

If i use the switch statementthe read part doenst work
int this code i the same "codigo" cant be used twice
so i'm using the mensage
Feedback
"esse codigo ja existe"
pls help me find whats is wrong with this code
Header 1
#pragma once
#include <stdlib.h>
#include <stdio.h>
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
class Paciente
{
private:
int codigo, fixo, celular;
string nomePaciente, nomeCovenio;
public:
void setCodigo(int x) {
codigo = x;
}
int getCodigo() {
return codigo;
}
void setFixo(int x) {
fixo = x;
}
void setCelular(int x) {
celular = x;
}
void setNomePaciente(string x) {
nomePaciente = x;
}
void setNomeCovenio(string x) {
nomeCovenio = x;
}
int getFixo() {
return fixo;
}
int getCelular() {
return celular;
}
string getNomeCovenio() {
return nomeCovenio;
}
string getNomePaciente() {
return nomePaciente;
}
};
<i>#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <fstream>
#include "Paciente.cpp"
using namespace std;
int main() {
fstream texto1("paciente.txt", ios::in |ios::out| ios::app);
int s;
Paciente p;
string q,z,r;
cout << "1-Cadastramento" << endl << "2-Agendamento" << endl << "3-Alteracao de Paciente" << endl << "4-Vizualizacao de Consultas" << endl;
cin >> s;
switch (s) {
case 1:
int w;
cout << "diga seu codigo" << endl;
cin >> s;
p.setCodigo(s);
cout << "diga seu nome" << endl;
cin >> q;
p.setNomePaciente(q);
cout << "diga seu nome do covenio" << endl;
cin >> q;
p.setNomeCovenio(q);
cout << "diga o seu telefone fixo" << endl;
cin >> w;
p.setFixo(w);
cout << "diga o seu telefone celular" << endl;
cin >> w;
p.setCelular(w);
texto1 << endl << "Paciente " << p.getNomePaciente() << endl;
texto1 << "Covenio " << p.getNomeCovenio() << endl;
texto1 << "Fixo " << p.getFixo() << endl;
texto1 << "Celular " << p.getCelular() << endl;
texto1 << "Codigo " << p.getCodigo() << endl;
texto1.clear();
while (texto1 >> z >> r) {
if (z == "Codigo") {
int x = atoi(r.c_str());
if (x == 12) {
cout << "esse codigo ja existe" << endl;
};
};
};
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
cout << "Nao eh uma opcao" << endl;
break;
};
texto1.close();
system("pause");
return 0;
}</i>,
An fstream only keeps one file position, shared between read and write.
Each time you switch between reading and writing, you have to do a seek to set the position for the next operation. If you really want to use the current position, you can use the minimum seek of
texto1.seekp(0, ios_base::cur);
which "moves" the file position 0 bytes from the current position. But it's still formally a seek, and you can then either read or write from that position.

Function not recognized within scope

I've almost finished writing a program that will detect palindromes from a file and output a new file highlighting the palindromes but I'm stuck on a really dumb error. I'm trying to write a test for one of my methods (TDD) and, for some reason, it's not recognizing the function as within the scope.
I'm calling the isPalindrome(string s) method (declared in PalindromeDetector.h) in my isPalindromeTest() method (declared in PalindromeDetectorTest.h) but, for some reason, it's not recognizing it as within the scoope.
I feel like everything should be working but it just isn't. Any help you can provide would be greatly appreciated. Below is my code:
PalindromeDetector.h
#ifndef PALINDROMEDETECTOR_H_
#define PALINDROMEDETECTOR_H_
#include <iostream>
using namespace std;
class PalindromeDetector {
public:
void detectPalindromes();
bool isPalindrome(string s);
};
#endif /* PALINDROMEDETECTOR_H_ */
PalindromeDetector.cpp
#include "PalindromeDetector.h"
#include "Stack.h"
#include "ArrayQueue.h"
#include <iostream>
#include <fstream>
#include <cassert>
#include <cctype>
#include <string>
using namespace std;
void PalindromeDetector::detectPalindromes() {
cout << "Enter the name of the file whose palindromes you would like to detect:" << flush;
string fileName;
cin >> fileName;
cout << "Enter the name of the file you would like to write the results to: " << flush;
string outFileName;
cin >> outFileName;
fstream in;
in.open(fileName.c_str());
assert(in.is_open());
ofstream out;
out.open(outFileName.c_str());
assert(out.is_open());
string line;
while(in.good()){
getline(in, line);
line = line.erase(line.length()-1);
if(line.find_first_not_of(" \t\v\r\n")){
string blankLine = line + "\n";
out << blankLine;
} else if(isPalindrome(line)){
string palindromeYes = line + " ***\n";
out << palindromeYes;
} else {
string palindromeNo = line + "\n";
out << palindromeNo;
}
if(in.eof()){
break;
}
}
in.close();
out.close();
}
bool PalindromeDetector::isPalindrome(string s){
unsigned i = 0;
Stack<char> s1(1);
ArrayQueue<char> q1(1);
while(s[i]){
char c = tolower(s[i]);
if(isalnum(c)){
try{
s1.push(c);
q1.append(c);
} catch(StackException& se) {
unsigned capS = s1.getCapacity();
unsigned capQ = q1.getCapacity();
s1.setCapacity(2*capS);
q1.setCapacity(2*capQ);
s1.push(c);
q1.append(c);
}
}
i++;
}
while(s1.getSize() != 0){
char ch1 = s1.pop();
char ch2 = q1.remove();
if(ch1 != ch2){
return false;
}
}
return true;
}
PalindromeDetectorTest.h
#ifndef PALINDROMEDETECTORTEST_H_
#define PALINDROMEDETECTORTEST_H_
#include "PalindromeDetector.h"
class PalindromeDetectorTest {
public:
void runTests();
void detectPalindromesTest();
void isPalindromeTest();
};
#endif /* PALINDROMEDETECTORTEST_H_ */
PalindromeDetectorTest.cpp
#include "PalindromeDetectorTest.h"
#include <cassert>
#include <iostream>
#include <fstream>
#include <cctype>
#include <string>
using namespace std;
void PalindromeDetectorTest::runTests(){
cout << "Testing palindrome methods... " << endl;
detectPalindromesTest();
isPalindromeTest();
cout << "All tests passed!\n" << endl;
}
void PalindromeDetectorTest::detectPalindromesTest(){
cout << "- testing detectPalindromes()... " << flush;
fstream in;
string fileName = "testFile.txt";
in.open(fileName.c_str());
assert(in.is_open());
cout << " 1 " << flush;
ofstream out;
string fileOutName = "testFileOut.txt";
out.open(fileOutName.c_str());
assert(out.is_open());
cout << " 2 " << flush;
cout << " Passed!" << endl;
}
void PalindromeDetectorTest::isPalindromeTest(){
cout << "- testing isPalindrome()... " << flush;
// test with one word palindrome
string s1 = "racecar";
assert(isPalindrome(s1) == true); // these are not recognized within the scope
cout << " 1 " << flush;
// test with one word non-palindrome
string s2 = "hello";
assert(isPalindrome(s2) == false); // these are not recognized within the scope
cout << " 2 " << flush;
// test with sentence palindrome
string s3 = "O gnats, tango!";
assert(isPalindrome(s3) == true); // these are not recognized within the scope
cout << " 3 " << flush;
// test with sentence non-palindrome
string s4 = "This is not a palindrome.";
assert(isPalindrome(s4) == false); // these are not recognized within the scope
cout << " 4 " << flush;
cout << " Passed!" << endl;
}
isPalindrome is a member function of PalindromeDetector, but you are trying to call it from within a PalindromeDetectorTest method. If the test class derived from PalindromeDetector this would work, but there isn't (and almost certainly shouldn't be) any such relationship between them.
You need a PalindromeDetector object to call the method on. Probably just as simple as this:
void PalindromeDetectorTest::isPalindromeTest(){
cout << "- testing isPalindrome()... " << flush;
PalindromeDetector sut; // "subject under test"
// test with one word palindrome
string s1 = "racecar";
assert(sut.isPalindrome(s1) == true);
// etc.
}
You could also make the PalindromeDetector methods static since the object doesn't appear to have any state. Then you could simply call PalindromeDetector::isPalindrome(s1); without the need to create an instance.

C++ read/write to binary file. on program exit it gives System.AccessViolationException

This C++ program is created using Visual Studio 2010. It's a group project that has everyone in class stumped.
The program initially starts fine and the user can run through the program and add items that are written out to file. the items are read back in and displayed. When the user is done, on the program exiting return 0; it gives me "An unhandled exception of type System.AccessViolationException occurred. Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
When this happens it opens up a file called utility here => for (_Iterator_base12 **_Pnext = &_Myproxy->_Myfirstiter; *_Pnext != 0; *_Pnext = (*_Pnext)->_Mynextiter) (*_Pnext)->_Myproxy = 0.
I can fix this by replacing return 0; with exit(0);
I know it's not a real fix though and just a band-aid over a bullet hole that is causing this issue.
After fixing (used very loosely here) that, then running the program again, it attempts to load the data file from the file system. It reads and loads the 1st item into a vector correctly but when it goes back to the start of the loop we see the same exception pop up, An unhandled exception of type System.AccessViolationException occurred.
This is the first project we have worked on using fstream and binary i/o. We had worked through a similar program that was just reading and writing strings w/out any issues.I believe that the issue stems from something in the fileHandler class but am having a difficult time pinpointing what is causing this issue.Any advice/help is greatly appreciated.Here is the code.stdafx.h
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include <stdio.h>
#include <iostream>
#include <stdlib.h>
#include <sstream>
#include <fstream>
#include <string.h>
#include <string>
#include <vector>
#include <time.h>
Week2.cpp (the main file for the project)
//Week2.cpp *******************
#include "stdafx.h"
#include "fileHandler.h"
using namespace std;
using namespace System;
int main(array<System::String ^> ^args)
{
fileHandler theFile("store.pkl");
vector<item> itemStack = theFile.getFile();
cout << "SKU Name Dept Vendor Max Order onHand" << endl;
cout << "-------------------------------------------" << endl;
for (int i = 0; i < itemStack.size(); i++)
{
cout << itemStack[i].toString() << endl;
}
vector<item> newStack;
//prompt for input
bool doneEditing = false;
while(!doneEditing)
{
int A;
int E;
int F;
int G;
string B;
string C;
string D;
string tempString;
cout << "Enter item info:" << endl << "Item SKU: ";
cin >> A;
cout << endl << "Item Name: ";
cin >> B;
cout << endl << "Item Dept: ";
cin >> C;
cout << endl << "Vendor Name: ";
cin >> D;
cout << endl << "Max Number: ";
cin >> E;
cout << endl << "Reorder Number: ";
cin >> F;
cout << endl << "OnHand Number: ";
cin >> G;
cout << endl << "Done?? Y/N: ";
cin >> tempString;
cout << endl;
item tempItem = item(A, B, C, D, E, F, G);
newStack.push_back(tempItem);
if (tempString == "Y" || tempString == "y")
{
doneEditing = true;
}
}
cout << "Saving stack to file" << endl;
theFile.putFile(newStack);
cout << "Items written to file" << endl;
vector<item> newFileStack = theFile.getFile();
cout << "After reload: " << endl;
cout << "SKU Name Dept Vendor Max Order onHand" << endl;
cout << "-------------------------------------------" << endl;
for (int i = 0; i < newFileStack.size(); i++)
{
cout << newFileStack[i].toString() << endl;
}
cout << "Thank you for using the Awesome Grocery Inventory Application" << endl;
system("PAUSE");
/*return 0; this breaks with same error as
when reading in saved file after application restart
*/
exit(0);
}
item.h
using namespace std;
#pragma once
class item
{
public:
item();
item(int sku, string name, string dept, string vendor, int max, int reorder, int onhand);
~item(void);
string toString();
int ItemSKU() const;
void ItemSKU(int val);
string ItemName() const;
void ItemName(string val);
string VendorName() const;
void VendorName(string val);
int MaxNumb() const;
void MaxNumb(int val);
int ReorderNumb() const;
void ReorderNumb(int val);
int OnHandNumb() const;
void OnHandNumb(int val);
private:
int itemSKU;
string itemName;
string itemDept;
string vendorName;
int maxNumb;
int reorderNumb;
int onHandNumb;
};
item.cpp
#include "StdAfx.h"
#include "item.h"
using namespace std;
item::item()
{
};
item::item(int sku, string name, string dept, string vendor, int max, int reorder, int onhand)
{
itemSKU = sku;
itemName = name;
itemDept = dept;
vendorName = vendor;
maxNumb = max;
reorderNumb = reorder;
onHandNumb = onhand;
}
item::~item(void)
{
}
string item::toString()
{
stringstream ss;
ss << itemSKU << "\t" << itemName << "\t" << itemDept << "\t" << vendorName << "\t" << maxNumb << "\t" << reorderNumb << "\t" << onHandNumb;
string s = ss.str();
return s;
}
int item::ItemSKU() const { return itemSKU; }
void item::ItemSKU(int val) { itemSKU = val; }
string item::ItemName() const { return itemName; }
void item::ItemName(string val) { itemName = val; }
string item::VendorName() const { return vendorName; }
void item::VendorName(string val) { vendorName = val; }
int item::MaxNumb() const { return maxNumb; }
void item::MaxNumb(int val) { maxNumb = val; }
int item::ReorderNumb() const { return reorderNumb; }
void item::ReorderNumb(int val) { reorderNumb = val; }
int item::OnHandNumb() const { return onHandNumb; }
void item::OnHandNumb(int val) { onHandNumb = val; }
fileHandler.h
#include "item.h"
using namespace std;
#pragma once
class fileHandler
{
public:
fileHandler(string);
~fileHandler(void);
vector<item> getFile();
void putFile(vector<item> &);
private:
string theFileName;
};
fileHandler.cpp
#include "stdafx.h"
#include "fileHandler.h"
using namespace std;
fileHandler::fileHandler(string name)
{
theFileName = name.c_str();
}
fileHandler::~fileHandler(void)
{
}
vector<item> fileHandler::getFile()
{
ifstream inFile;
string fileLine;
vector<item> localStack;
inFile.open(theFileName, ios::in|ios::binary);
if (inFile)
{
cout << "Getting file..." << endl;
cout << endl;
// not working on initial load if file is present at start
inFile.seekg(0);
while(!inFile.eof())
{
item tempItem;
inFile.read(reinterpret_cast< char * >(&tempItem), sizeof(item));
localStack.push_back(tempItem);
cout << "item added to stack" << endl;
} //breaks from here after reading in 1 item from saved file on reopen
} else {
ofstream newFile;
newFile.open(theFileName, ios::out|ios::binary);
newFile.close();
cout << "Creating new file..." << endl;
cout << endl;
inFile.open(theFileName, ios::in|ios::binary);
}
inFile.clear();
inFile.close();
if (localStack.size() > 0)
{
//removes some dirty data from end of stack
localStack.pop_back();
}
return localStack;
}
void fileHandler::putFile( vector<item> &items )
{
ofstream outFile;
outFile.open(theFileName, ios::out|ios::binary);
if(!outFile)
{
cerr<<"File could not be created"<<endl;
system("pause");
exit(1);
}
for (int i = 0; i < items.size(); i++)
{
outFile.write(reinterpret_cast<const char *>(&items[i]), sizeof(item));
}
outFile.clear();
outFile.close();
}
You cannot perform binary I/O this way with an object that contains std::string members. A std::string contains pointer(s) to dynamically allocated memory for its actual contents. You need to perform some type of serialization instead. The usual suggestion is Boost serialization.