Member Avatar for JE821

So the program makes an inventory from a cvs file. The cvs file consists of dvds and books.
here is the code:

#include "StdAfx.h"

#define     _CRTDBG_MAP_ALLOC   //for memory checking
#include    <iostream>
#include    <stdlib.h>
#include    <crtdbg.h>
#include    <iomanip>
#include    <fstream>
#include    <string.h>

#pragma warning(disable: 4996 4018)
using namespace std;

#define COPYSTR(TARGET, SOURCE) \
    TARGET = new char [strlen(SOURCE)+1]; \
    strcpy(TARGET, SOURCE)
////////////////////////////////////////////////////////////////////-->ERROR
class error
{
    fstream error_file;
    void open_file();
    void close_file();
public:
    error() {open_file();}
    ~error() {close_file();}
    void print_file();
    void clear_file();
    void add_file(int, const char*);
};
void error::open_file()
{
    error_file.open("error_file.txt", ios::in | ios::out | ios::app);
}
void error::print_file()
{
    cout << "\nERRORS:\n";
    char temp[256];
    if(error_file)
    {
        error_file.seekg(0,ios::beg);   
        while(!error_file.eof())
        {
            if(error_file.getline(temp,256))
                cout << temp << endl;
        }
    }
}
void error::clear_file()
{
    if(error_file.is_open())
        error_file.close();
    error_file.open("error_file.txt", ios::out);
    error_file.close();
}
void error::close_file()
{
    if(error_file.is_open())
        error_file.close();
}
void error::add_file(int num, const char* error)
{
    if(error_file)
    {
        error_file << num+1 << ": " << error <<endl;
    }
    else
        cout << "unable to open";
}
////////////////////////////////////////////////////////////////////////-->CONTAINER
class container
{
public:
    virtual void alloc_rows(int n_rows) = 0;
    virtual void insert(void* i) = 0;
    virtual const void* get(int i) const = 0;
    virtual int get_n_rows() const = 0;
    virtual ~container() = 0 {};
};
////////////////////////////////////////////////////////////////////////-->FILE_BUFF
class file_buff: public container
{
    char** line;    
    int n_lines;
    int count;

    int process_file(const char* fn);
    int count_lines(ifstream& file);
    void delete_file_buff();
public:
    file_buff(const char* fn) {process_file(fn);}
    virtual ~file_buff() {delete_file_buff();}
    int get_n_lines() const  {return n_lines;}
    const char* get_line(int index) const {return line[index];}

    virtual void alloc_rows(int n_rows);
    virtual void insert(void* thing);
    virtual const void* get(int i) const {return get_line(i);}
    virtual int get_n_rows() const {return get_n_lines();}
};
void file_buff::alloc_rows(int n_rows) {
    n_lines = n_rows;
    line = new char* [n_lines];
}
void file_buff::insert(void* thing){
    char* temp = (char*)thing;
    line[count] = new char [strlen(temp)+1];
    strcpy(line[count], temp);
    count++;
}
int file_buff::count_lines(ifstream& file)
{
    int pos = 0;
    char temp[256];
    if (file.good()){
        while (!file.eof())
            if (file.getline(temp,256)) 
                pos++;
        file.clear();
        file.seekg(0,ios::beg);
    }
    return pos;
}
int file_buff::process_file(const char* file)
{
    char temp[256];
    ifstream in;
    in.open(file);

    count = 0;
    if (in.good()) {
        alloc_rows(count_lines(in));
        for(int i = 0; i < n_lines; i++) 
            line[i] = NULL;
        while (!in.eof()) {
            if (in.getline(temp, 256)) {
                insert(temp);
            }
        }
    } 
    else 
    {
        cout << "Unable to open file " << file << endl;
        cin.get();
        exit(1);
    }
    in.close();
    return count;
}
void file_buff::delete_file_buff()
{
    int i=0;
    if (line)
    {
        for(i=0; i < n_lines; i++) 
        {
            delete [] line[i];
            line[i] = NULL;
        }
        delete [] line;
        line = NULL;
    }
}
/////////////////////////////////////////////////////////////////////////-->ITEM
class item
{
    char* title;
    int item_num;
    float price;
    int year;
public:
    item() : title(0), item_num(0), price(0), year(0) {};
    virtual ~item();
    void set_title(const char* f_title);
    const char* get_title() const {return title;}
    void set_item_num(int f_item_num) {item_num = f_item_num;}
    int get_item_num() const {return item_num;}
    void set_year(int f_year) {year = f_year;}
    int get_year() const {return year;}
    void set_price(float f_price) {price = f_price;}
    float get_price() const {return price;}

    static int compare_item_nums (const void* e1, const void* e2);

    virtual float type_ship() const = 0;
    virtual bool init (const char* temp, int num) = 0;
    virtual ostream& print(ostream& out) = 0;
    virtual item* clone() = 0;
    virtual void show_detail() = 0;
};
void item::set_title(const char* f_title)
{
    if(title)
        delete [] title;
    if(f_title == NULL)
        title = NULL;
    else
        COPYSTR(title, f_title);
}
int item::compare_item_nums(const void* e1, const void* e2)
{
    const item** ptr1 = (const item**) (e1);
    const item** ptr2 = (const item**) (e2);

    int i1 = (*ptr1)->get_item_num();
    int i2 = (*ptr2)->get_item_num();

    if(i1 > i2) return 1;
    if(i1 < i2) return -1;
    return 0;
}
ostream& operator << (ostream& out, item& i)
{
    return i.print(out);
}
item::~item()
{
    if(title) {
        delete [] title;
        title = NULL;
    }
}
/////////////////////////////////////////////////////////////////////////-->BOOK
class book: public item
{
    char* author;
    char* isbn;
    int num_pages;
    char format;
    void delete_book();
public:
    book(): author(0), isbn(0), num_pages(0), format(0) {};
    book (const book& cbk);
    virtual ~book() {delete_book();}
    void show_book();
    void set_isbn(const char* f_isbn);
    void set_author(const char* f_author);
    const char* get_author() const {return author;}
    const char* get_isbn() const {return isbn;}
    book& operator= (const book& cbk);
    friend ostream& operator << (ostream& lhs, book& cbk);

    virtual float type_ship() const {return 3.00;}
    virtual bool init(const char* buff, int num);
    virtual ostream& print(ostream& out);
    virtual item* clone() {return new book(*this);}
    virtual void show_detail();
};
book::book(const book& cbk) : num_pages(cbk.num_pages), format(cbk.format)
{
    set_item_num(cbk.get_item_num()); 
    if(cbk.get_title())
        set_title(cbk.get_title());
    if(cbk.get_author())
        set_author(cbk.get_author());
    set_isbn(cbk.get_isbn());
    set_year(cbk.get_year());
    set_price(cbk.get_price());
}
book& book::operator = (const book& cbk)
{
    if(this != &cbk) 
    {
        set_title(cbk.get_title());
        set_author(cbk.get_author());
        set_year(cbk.get_year());
        set_item_num(cbk.get_item_num());
        set_price(cbk.get_price());
        format = cbk.format;
        num_pages = cbk.num_pages;
    }
    return *this;
}
ostream& operator << (ostream& lhs, book& cbk)
{
    return cbk.print(lhs);
}
ostream& book::print(ostream& out)
{
    cout << "Item " << get_item_num() << " \"" << get_title();
    cout << "\" by " << get_author() << ". $";
    cout << fixed << setprecision(2) << get_price() << endl;
    return out;
}
void book::set_isbn(const char* f_isbn)
{
    if(isbn)
        delete [] isbn;
    if(f_isbn == NULL)
        isbn = NULL;
    else
        COPYSTR(isbn, f_isbn);
}
void book::set_author(const char* f_author)
{
    if(author)
        delete [] author;
    if(f_author == NULL)
        author = NULL;
    else
        COPYSTR(author, f_author);
}
bool book::init(const char* buff, int num)
{
    error txt;

    char temp[256];
    strcpy(temp, buff);

    char* fitem_num = strtok(temp, ",");
    if(strlen(fitem_num) != 4) {
        txt.add_file(num+1,"item number must have 4 digits");
        return false;}
    if(fitem_num[0] != '4') {
        return false;}
    set_item_num(atoi(fitem_num));

    char* fisbn = strtok(NULL, ",");
    set_isbn(fisbn);
    if(strlen(isbn)>10||strlen(isbn)<9) {
        txt.add_file(num+1,"isbn must be 10 or least digits");
        return false;}

    char* ftitle = strtok(NULL, ",");
    set_title(ftitle);

    char* fauthor = strtok(NULL, ",");
    set_author(fauthor);

    char* fyear = strtok(NULL, ",");
    if(strlen(fyear)!=4 || atoi(fyear)==0){
        txt.add_file(num+1,"year must be 4 digits");
        return false;}
    set_year(atoi(fyear));

    char* fformat = strtok(NULL, ",");
    format = *fformat;
    if(!(format=='H'||format=='P') || strlen(fformat)!=1){
        txt.add_file(num+1,"format must be P or H");
        return false;}

    char* fnum_pages = strtok(NULL, ",");
    if(atoi(fnum_pages)<=0){
        txt.add_file(num+1,"number of pages must be more than 0");
        return false;}
    num_pages = atoi(fnum_pages);

    float price;
    char* fprice = strtok(NULL, "\n");
    sscanf(fprice, "%f", &price);
    if(price<=0){
        txt.add_file(num,"price can't be less than 0");
        return false;}
    set_price(price);
    return true;
}
void book::show_book()
{
    cout << "Item " << get_item_num() << ": ";
    cout << "\"" << get_title() << "\" by " << get_author() << ". $";
    cout << fixed << setprecision(2) << get_price() << endl;
}
void book::show_detail()
{
    cout << "Item # " << get_item_num() << endl; 
    cout << "----------" << endl;
    cout << "Title: " << get_title() << endl;
    cout << "Author: " << get_author() << endl;
    cout << "Format: "; 
    if(format == 'P')
        cout << "Paperback" << endl;
    else
        cout << "Hardback" << endl;
    cout << "Year: " << get_year() << endl;
    cout << "Pages: " << num_pages << endl;
    cout << "ISBN: " << get_isbn() << endl;
    cout << "Price: $" << get_price() << endl;
}
void book::delete_book()
{
    if (author) {
        delete [] author;
        author = NULL;
    }
    if (isbn) {
        delete [] isbn;
        isbn = NULL;
    }
}
/////////////////////////////////////////////////////////////////////////-->DVD
class dvd: public item
{
    char* upc;
    char* star1;
    char* star2;
    void delete_dvd();
public:
    dvd(): upc(0), star1(0), star2(0) {};
    dvd(const dvd& cdv);
    virtual ~dvd() {delete_dvd();}
    void show_dvd();
    void set_upc(const char* f_upc);
    const char* get_upc() const {return upc;}
    void set_star1(const char* f_star1);
    const char* get_star1() const {return star1;}
    void set_star2(const char* f_star2);
    const char* get_star2() const {return star2;}
    dvd& operator = (dvd&);
    friend ostream& operator << (ostream& out, item& cdv);

    virtual float type_ship() const {return 1.00;}
    virtual bool init(const char* buff, int num);
    virtual ostream& print(ostream& out);
    virtual item* clone() {return new dvd (*this);}
    virtual void show_detail();
};
dvd::dvd(const dvd& cdv)
{   
    set_item_num(cdv.get_item_num());
    if(cdv.get_title())
        set_title(cdv.get_title());
    if(cdv.get_star1())
        set_star1(cdv.get_star1());
    if(cdv.get_star2())
        set_star2(cdv.get_star2());
    if(cdv.get_upc())
        set_upc(cdv.get_upc());
    set_year(cdv.get_year());
    set_price(cdv.get_price());
}
dvd& dvd::operator = (dvd& cdv)
{
    if(this != &cdv)
    {
        set_title(cdv.get_title());
        set_item_num(cdv.get_item_num());
        set_year(cdv.get_year());
        set_star1(cdv.get_star1());
        set_star2(cdv.get_star2());
        set_upc(cdv.get_upc());
        set_price(cdv.get_price());
    }
    return *this;
}
ostream& operator << (ostream& lhs, dvd& cdv)
{
    return cdv.print(lhs);
}
ostream& dvd::print(ostream& out)
{
    cout << "Item " << get_item_num() << " \"" << get_title();
    cout << "\" <" << get_year() << "> starring: " << get_star1() << " and " << get_star2();
    cout << ". $" << fixed << setprecision(2) << get_price() << endl;
    return out;
}
void dvd::set_upc(const char* f_upc)
{
    if(upc)
        delete [] upc;
    if(f_upc == NULL)
        upc = NULL;
    else
        COPYSTR(upc, f_upc);
}
void dvd::set_star1(const char* f_star1)
{
    if(star1)
        delete [] star1;
    if(f_star1 == NULL)
        star1 = NULL;
    else
        COPYSTR(star1, f_star1);
}
void dvd::set_star2(const char* f_star2)
{
    if(star2)
        delete [] star2;
    if(f_star2 == NULL)
        star2 = NULL;
    else 
        COPYSTR(star2, f_star2);
}
bool dvd::init(const char* buff, int num)
{
    error txt;

    char temp[256];
    strcpy(temp, buff);

    char* fitem_num = strtok(temp, ",");
    if(strlen(fitem_num) != 4){
        txt.add_file(num+1,"item number must have 4 digits");
        return false;}
    if(fitem_num[0] != 7)
        return false;
    set_item_num(atoi(fitem_num));

    char* fupc = strtok(NULL, ",");
    set_upc(fupc);
    if(strlen(fupc)>12||strlen(fupc)<11){
        txt.add_file(num+1,"upc must be 12 digits");
        return false;}

    char* ftitle = strtok(NULL, ",");
    set_title(ftitle);

    char* fyear = strtok(NULL, ",");
    if(strlen(fyear)!=4 || atoi(fyear)>0){
        txt.add_file(num+1,"year must be 4 digits");
        return false;}
    set_year(atoi(fyear));

    char* fstar1 = strtok(NULL, ",");
    set_star1(fstar1);

    char* fstar2 = strtok(NULL, ",");
    set_star2(fstar2);

    float price;
    char* fprice = strtok(NULL, "\n");
    sscanf(fprice, "%f", &price);
    if(price<=0){
        txt.add_file(num,"price can't be less than 0");
        return false;}
    set_price(price);
    return true;
}
void dvd::show_dvd()
{
    cout << "Item " << get_item_num() << ": " << "\"" << get_title() << "\" <" << get_year() << ">";
    cout << " Staring: " << star1 << " and " << star2 << ". $" << fixed << setprecision(2) << get_price() << endl;
}
void dvd::show_detail()
{
    cout << "Item # " << get_item_num() << endl;
    cout << "----------" << endl;
    cout << "Title: " << get_title() << endl;
    cout << "Year: " << get_year() << endl;
    cout << "UPC: " << get_upc() << endl;
    cout << "Starring: " << get_star1() << " and " << get_star2() << endl;
    cout << "Price: $" << get_price() << endl;
}
void dvd::delete_dvd()
{
    if(upc) {
        delete [] upc;
        upc = NULL;
    }
    if(star1) {
        delete [] star1;
        star1 = NULL;
    }
    if(star2) {
        delete [] star2;
        star2 = NULL;
    }
}
////////////////////////////////////////////////////////////////////-->ITEM_HOLDER
class item_holder: public container
{
    item** arr_items;
    int n_items;
    const int max;
public:
    void init_ary(int n);
    item_holder(int n): n_items(0), max(n) {init_ary(n);};
    virtual ~item_holder() {delete_ary();}
    void delete_ary();
    void set_n_items(int n) {n_items = n;}
    int get_n_items() const {return n_items;}
    item* get_item(int i) const {return arr_items[i];}
    int search_item(int i);
    void sort_item_nums();
    bool add_item_ih(item* item_ptr);

    virtual void alloc_rows(int n_rows) {init_ary(n_rows);}
    virtual void insert(void* thing) {add_item_ih((item*)thing);}
    virtual const void* get(int i) const {return get_item(i);}
    virtual int get_n_rows() const {return n_items;}
};
void item_holder::init_ary(int n)
{
    arr_items = new item* [n];
    for (int i = 0; i < n; i++)
        arr_items[i] = NULL;
}
void item_holder::delete_ary()
{
    if(arr_items)
    {
        for(int i = 0; i < n_items; i++) 
        {
            if(arr_items[i])
            {
                delete arr_items[i];
                arr_items[i] = NULL;
            }
        }
        delete [] arr_items;
        arr_items = NULL;
    }
}
int item_holder::search_item(int i)
{
    for(int j = 0; j < n_items; j++) 
    {
        if(arr_items[j]->get_item_num() == i)
            return j;
    }
    return -1;
}
void item_holder::sort_item_nums()
{
    qsort(arr_items, n_items, sizeof(item*), &item::compare_item_nums);
}
bool item_holder::add_item_ih(item* item_ptr)
    {
        if(n_items = max)
            return false;
        arr_items[n_items] = item_ptr->clone();
        n_items++;
        return true;
    }
////////////////////////////////////////////////////////////////////--> CART
class cart: public item_holder
{
public:
    cart(): item_holder(10) {};
    virtual ~cart() {delete_ary();}
    void show_cart();
};
void cart::show_cart()
{
    double subt = 0.0;
    double ship = 0.0;
    double rate = 0.0825;
    double tax = 0.0;

    cout << "Cart\t" << endl;
    for(int i = 0; i < get_n_items(); i++)
    {
        cout << *(get_item(i));
        subt += get_item(i)->get_price();
        ship += get_item(i)->type_ship();
    }
    tax = rate*(subt+ship);
    cout << "\n\nSubtotal: \t" << subt << endl;
    cout << "Shipping: \t" << ship << endl;
    cout << "Taxes: \t" << tax << endl;
    cout << "Total: \t" << subt+ship+tax << endl;
}
////////////////////////////////////////////////////////////////////-->INVENTORY
class inventory: public item_holder
{
    bool add_item_inv_bk(const char* buff, int num);
    bool add_item_inv_dv(const char* buff, int num);
public:
    inventory(int n): item_holder(n) {};
    virtual ~inventory() {delete_ary();}
    void fill_inventory(container* cp);
    void show_inventory();
};
bool inventory::add_item_inv_bk(const char* buff, int num)
{
    error txt;

    item* pbook = new book;
    if(pbook->init(buff, num))
    {
        if(search_item(pbook->get_item_num()) == -1)
        {
            bool i_ptr = add_item_ih(pbook);
            delete pbook;
            return i_ptr;
        } 
        else 
        {
            txt.add_file(num+1, "item number already exists");
            delete pbook;
            return false;
        }
    }
    delete pbook;
    return false;
}
bool inventory::add_item_inv_dv(const char* buff, int num)
{
    error txt;

    item* pdvd = new dvd;
    if(pdvd->init(buff, num))
    {
        if(search_item(pdvd->get_item_num()) == -1)
        {
            bool i_ptr = add_item_ih(pdvd);
            delete pdvd;
            return i_ptr;
        }
        else 
        {
            txt.add_file(num+1, "item number already exists");
            delete pdvd;
            return false;
        }
    }
    delete pdvd;
    return false;
}
void inventory::fill_inventory(container* cp)
{
    int current = 0;
    for (current = 0; current < cp->get_n_rows(); current++) 
    {
        char type = ((char*)cp->get(current))[0];
        if(type == '4') 
        {
            if(!(add_item_inv_bk((char*)cp->get(current),current)))
                continue;
        } 
        else if(type == '7') 
        {
            if(!(add_item_inv_dv((char*)cp->get(current),current)))
                continue;
        }
        else
        {
            error txt;
            txt.add_file(current+1, "invalid inventory entry");
        }

    } return;
}
void inventory::show_inventory()
{
    sort_item_nums();

    cout << "\nBOOKS" << endl;
    for(int i = 0; i < get_n_items(); i++)
    {
        if(get_item(i)->get_item_num() > 4999) 
        {
            cout << "\nDVDS" << endl;
        }
        cout << *(get_item(i));
    }
    cout << endl;
}
////////////////////////////////////////////////////////////////////////////////-->MENU
class menu_manager
...
////////////////////////////////////////////////////////////////////////////////-->MAIN
void main()
{
    {
        const char* FILE_NAME = "inventory1.csv";
        cout <<"Processing file from: " << FILE_NAME << "...\n\n";
        container* fb = new file_buff(FILE_NAME);
        inventory inv(fb->get_n_rows());
        inv.fill_inventory(fb);

        error txt;
        txt.print_file();
        txt.clear_file();

        menu_manager mgr(inv);
        mgr.manage();

        delete fb;
    }
        _CrtDumpMemoryLeaks();      //check for mem leaks
    cout << "\nPress Enter to Exit...";
    cin.get();
}

The problems appear at:
(1)

class item
{
    variables
    ...
public:
    ...
    -->>int get_item_num() const {return item_num;}
    ...
};

(2)

int item_holder::search_item(int i)
    {
        for(int j = 0; j < n_items; j++) 
        {
            if(arr_items[j]->get_item_num() == i)
                return j;
        }
        return -1;
    }

And consequently all the functions that use item_holder::search_item
which are:

class inventory: public item_holder
    {
        bool add_item_inv_bk(const char* buff, int num);
        bool add_item_inv_dv(const char* buff, int num);
        ...
    }

best regards,
JE821.

What error are you getting? To try and make finding the problem easier you should try to skim the code down to the smallest thing you can get that still produces the error. Try to fix that and then implement the fix into the larger code that you have. Seeing 800 lines of code with virtually no comments and no mention of what the error is wont get you very far.

Member Avatar for JE821

Sorry for that.
So i get:

Unhandled exception at 0x77c415de in lab4.exe: 0xC0000005: Access violation reading location 0xcdcdcdc1.

and when i tried printing the array, i only got the first two items.
should i post the cvs file too?

thanks for the reply.

There must be something related to memory allocation or space in your array. The

Unhandled exception at 0x77c415de

shows you that you have mistreated some memory allocation. Frankly I didn't look up closly over your code, but in most cases there are problems with either allocating space in the arrays, or accessing something you shouldn't.

Access violation reading location 0xcdcdcdc1.

This shows you that you have tried to access something that you weren't suppose to. Either, your printing tries to access blocks of memory from somewhere else, and that's why it prints out only 2 items, or it's something wrong as I stated before, with the size/memory allocation/etc.

Try doing a debug on the program, that will definitely show you the speciffic point in your program where it crashes.

Member Avatar for JE821

So i changed a few lines but still have the memory allocation problem. However, a mlock.c file appears whenever i run the program. Im using Microsoft Visual Studio 2010 and there is a option Call Stack and it tells me the error are on the mlock.c file.

msvcr100d.dll!_unlock(int locknum) Line 375 C

msvcr100d.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 507 + 0x7 bytes C++

msvcr100d.dll!_heap_alloc_dbg_impl(unsigned int nSize, int nBlockUse, const char * szFileName, int nLine, int * errno_tmp) Line 504 + 0xc bytes C++

So I think I will go through the whole code, line by line again.
Thanks for the replies.

can u post the latest code I can go through it with ya

I know you already have a lot of code invested in this but it might be worth it to change what you are using for your arrays. I would suggest using a vector. You dont ned to worry about any memory managment or sizing issues. Why rewrite it if you dont have to.

Member Avatar for JE821

We haven't talked about vectors yet in my class so I don't think we are supposed to use that.
What file formats can be uploaded? I'm trying to upload a .cpp file because I don't want to post the whole code in a comment (hard to read).

Thanks for the replies.

Member Avatar for JE821

The problem was that i had memory allocated but didn't set to anything so it was set to "0xcdcdcdcdcd" which is a value and not a value at the same time. What I mean is that it is a value that can't be deleted and that what i was trying to do. I didn't know it was initialized with " 0xcdcdcdcdcd".

The program runs and does what is supposed to do.
Thanks for the replies.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.