I am fairly new to C++, as I began learning it two days ago, with some very basic background in java and python. I was trying to write a code that could simply store, recall, and delete entries in a class I named address_book. I did it first without using classes (just using the addbook structure I created) and it worked fine, but when I tried to change it into a class, it threw errors while initializing some integer variables. I have no idea how to fix this or what went wrong. I tried moving the initialization of the variables to zero outside of that function but could not get the variables to equal zero outside that. If you wouldn't mind, please help. Thank you in advance for any help you may give me.

Here is the code:

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

struct addBook {
    string name;
    string address;
    string number;
};

//accepts a string and returns with all letters lowercase
void tolowcase (string& str){
    for (int a=0; a<str.length(); a++)
    {
        if (str[a] >= 0x41 && str[a] <= 0x5A)
            str[a]+=0x20;
    }
}

class address_book {
    addBook * book1, * book2;
    int var1 = 0, var2 = 0, choice;
    string retstr, name, address, number;
    public:

        void newEntry(string, string, string);

        void showEntry(string);

        void delEntry(string);

        string readEntry(string);
};

int main()
{
    string choice,input,name,add,num;
    address_book mybook;
    cout << "Welcome to the address book editor\n" << endl;
    while (choice != "quit" && choice != "4")
    {
        cout << "1) Create Entry\n2) Read Entry\n3) Delete Entry\
        \n4) Quit\nInput Choice -> ";
        getline (cin, choice);
        tolowcase(choice);
        if (choice == "1" || choice == "create" || choice == "create entry" || choice == "new")
        {
            cout << "\nName ->"; //get and store the name
        	getline (cin, name);
        	cout << "\nAddress ->"; //get and store the address
        	getline (cin, add);
        	cout << "\nNumber ->"; //get and store the number
        	getline (cin, num);
        	mybook.newEntry(name, add, num);
        }
        else if (choice == "2" || choice == "read" || choice == "read entry")
        {
        	cout << "\nRead Which Entry Number? (all reads all entries)\n->";
        	getline (cin, input);
        	mybook.showEntry(input);
        }
        else if (choice == "3" || choice == "delete" || choice == "delete entry" || choice == "del")
        {
        	cout << "\nDelete Which Entry Number? (all deletes all entries)\n->";
        	getline (cin, input);
        }
        else if (choice != "4" && choice != "quit")
        cout << "Invalid choice\n" << endl;
    }
    return 0;
}


void address_book::newEntry(string name, string address, string number) {
    book1 = new addBook[++var1]; //adds 1 to number of entries in book1
    (book1+var1-1)->name = name;
    (book1+var1-1)->address = address;
    (book1+var1-1)->number = number;
    cout << "\n" << endl;
    if (var1>1)                       //if number of entries in book1 > 1
        for (int a = 1; a < var1; a++)//uses entries in book2 to replace
        {                             //entries lost from book1
            (book1+a-1)->name = (book2+a-1)->name;
            (book1+a-1)->address = (book2+a-1)->address;
            (book1+a-1)->number = (book2+a-1)->number;
        }
        book2 = book1;
        var2 = var1;
}

void address_book::showEntry(string input) {
    if (input == "all")                          // loops each entry and returns
        for (choice = 0; choice < var1; choice++)// the entry in format
        {
            name = (book1+choice)->name;      // stores entries information
            address = (book1+choice)->address;// to corresponding display
            number = (book1+choice)->number;  // variable
            cout << "\nName:\t\t" << name << "\nAddress:\t"
            << address << "\nNumber:\t\t" << number
            << endl << "\nPress Enter to continue...";
            getline (cin, input);
            cout << endl;
        }
    else
    {
        stringstream(input) >> choice;   // if choice != all, selects
        if (choice <= var1 && choice >0) // entry number in choice and
        {                                // prints its values
            choice--;
            name = (book1+choice)->name;
            address = (book1+choice)->address;
            number = (book1+choice)->number;
            cout << "\nName:\t\t" << name << "\nAddress:\t" 
            << address << "\nNumber:\t\t" << number << endl;
            cout << "\nPress Enter to continue...";
            getline (cin, input);
            cout << endl;
        }
        else
            cout << "\nInvalid Choice\n" << endl;
    }
}

void address_book::delEntry(string input) {
    if (input == "all")
    {
        book1 = book2 = new addBook[0];
        var1 = var2 = 0;
    }
    else
    {
        stringstream(input) >> choice;
        if (choice <= var1 && choice > 0)
        {
            book1 = new addBook[--var1];
            for (int a = var2 = 0; a <= var1; a++)
            {
                if (a == (choice-1)) continue;
                (book1+var2)->name = (book2+a)->name;
                (book1+var2)->address = (book2+a)->address;
                (book1+var2)->number = (book2+a)->number;
                var2++;
            }
            book2 = book1;
            var2 = var1;
            cout << "\n" << endl;
        }
        else
            cout << "\nInvalid Choice\n" << endl;
    }
}

string address_book::readEntry(string input) {
    return retstr;
}

The errors returned are the same for var1 and var2 and all 6 errors returned on line 23.

ISO C++ forbids initialization of member `var1'
making `var1' static
ISO C++ forbids in-class initialization of non-const static member `var1'

I am using CodeBlocks and Windows XP if that makes any difference at all.

I know it is likely not the most efficient way to do this, but I was trying to do it with what knowledge I have. If you have any questions, suggestions, tips, comments, or critiques please let me know, all comments are welcome. Thanks again for any help.

Recommended Answers

All 17 Replies

Don't put the initialization in the class description:

int var1 = 0, var2 = 0, choice;

Just declare the members:

int var1, var2, choice;

Use the constructor for initialization.

Thank you, I had tried that earlier but while editing it I must have added something else because it didn't work. This time it did though :) . Thanks again.

I was trying to add an overloaded operator to the aforementioned code in order to use '+' to append two books. I put the appropriate things in place to overload the operator in the class definition etc., but when I tried to access the pointers of variables in the operator definition I received errors. Again any help, suggestions, tips would be greatly appreciated.

Here is the definition code:

address_book address_book::operator+ (address_book part) {
    address_book temp;
    temp.var1 = var1 + part.var1;
    for (int a =0; a < temp.var1;  a++)
    {
        if (a < var1)
        {
        	temp.(book1+a)->name = (book1+a)->name;
        	temp.(book1+a)->address = (book1+a)->address;
        	temp.(book1+a)->number = (book1+a)->number;
        }
        else
        {
        	temp.(book1+a)->name = part.(book1+a)->name;
        	temp.(book1+a)->address = part.(book1+a)->address;
        	temp.(book1+a)->number = part.(book1+a)->number;
        }
    }
    temp.book2 = temp.book1;
    temp.var2 = temp.var1;
    return temp;
}

I received the same error for each part, one error on each of the first three lines in the if statement, 2 on each of the three lines in the else statement. error: expected unqualified-id before '(' token Thanks in advance for any help.

Try this kind of syntax

temp.book1[a].name = book1[a].name;

Instead of this stuff

temp.(book1+a)->name = (book1+a)->name;

I tried that and recieved the following error

error: base operand of `->' has non-pointer tupe `addBook'

I also tried the following syntax

(temp.book1+a)->name = (book1+a)->name;

It compiled fine using that syntax, but when I called the overloaded operator, it caused an error and aborted the execution.

I really do appreciate your help for everything so far.

I tried that and recieved the following error

error: base operand of `->' has non-pointer tupe `addBook'

With the code from Dave this error wouldn't come up.. Can you post your entire new code?

Niek

Sure thing, I really do appreciate all of your help from both of you.

#include <iostream>
#include <string>
#include <sstream>
using namespace std;

struct addBook {
    string name;
    string address;
    string number;
};

//accepts a string and returns with all letters lowercase
void tolowcase (string& str){
    for (int a=0; a<str.length(); a++)
    {
        if (str[a] >= 0x41 && str[a] <= 0x5A)
            str[a]+=0x20;
    }
}

class address_book {
    addBook * book1, * book2;
    int var1, var2, choice;
    string retstr, name, address, number;
    public:

        address_book ();

        address_book (int);

        address_book operator + (address_book);

        void newEntry(string, string, string);

        void showEntry(string);

        void delEntry(string);

        string readEntry(string);
};

int main()
{
    string choice,input,name,add,num;
    address_book mybook;
    cout << "Welcome to the address book editor\n" << endl;
    while (choice != "quit" && choice != "4")
    {
        cout << "1) Create Entry\n2) Read Entry\n3) Delete Entry\
        \n4) Quit\nInput Choice -> ";
        getline (cin, choice);
        tolowcase(choice);
        if (choice == "1" || choice == "create" || choice == "create entry" || choice == "new")
        {
            cout << "\nName ->"; //get and store the name
        	getline (cin, name);
        	cout << "\nAddress ->"; //get and store the address
        	getline (cin, add);
        	cout << "\nNumber ->"; //get and store the number
        	getline (cin, num);
        	mybook.newEntry(name, add, num);
        }
        else if (choice == "2" || choice == "read" || choice == "read entry")
        {
        	cout << "\nRead Which Entry Number? (all reads all entries)\n->";
        	getline (cin, input);
        	mybook.showEntry(input);
        }
        else if (choice == "3" || choice == "delete" || choice == "delete entry" || choice == "del")
        {
        	cout << "\nDelete Which Entry Number? (all deletes all entries)\n->";
        	getline (cin, input);
        	mybook.delEntry(input);
        }
        else if (choice != "4" && choice != "quit")
        cout << "Invalid choice\n" << endl;
    }
    mybook = mybook + mybook;
    mybook.showEntry("all");
    return 0;
}


address_book::address_book () {
    var1=var2=0;
}

address_book::address_book (int a) {
    var1=var2=a;
}

address_book address_book::operator+ (address_book part) {
    address_book temp;
    temp.var1 = var1 + part.var1;
    for (int a = 0, b = 0; a < temp.var1;  a++)
    {
        if (a < var1) // stores to temp until a is = to number of entries in 
        {             // book1 then goes to part.book1 and starts over with b
        	temp.book1[a]->name = (book1+a)->name;
        	temp.book1[a]->address = (book1+a)->address;
        	temp.book1[a]->number = (book1+a)->number;
        }
        else
        {
        	temp.book1[a]->name = part.book1[b]->name;
        	temp.book1[a]->address = part.book1[b]->address;
        	temp.book1[a]->number = part.book1[b]->number;
        	b++;
        }
    }
    temp.book2 = temp.book1;
    temp.var2 = temp.var1;
    return temp;
}

void address_book::newEntry(string name, string address, string number) {
    book1 = new addBook[++var1]; //adds 1 to number of entries in book1
    (book1+var1-1)->name = name;
    (book1+var1-1)->address = address;
    (book1+var1-1)->number = number;
    cout << "\n" << endl;
    if (var1>1)                       //if number of entries in book1 > 1
        for (int a = 1; a < var1; a++)//uses entries in book2 to replace
        {                             //entries lost from book1
            (book1+a-1)->name = (book2+a-1)->name;
            (book1+a-1)->address = (book2+a-1)->address;
            (book1+a-1)->number = (book2+a-1)->number;
        }
        book2 = book1;
        var2 = var1;
}

void address_book::showEntry(string input) {
    if (input == "all")                          // loops each entry and returns
        for (choice = 0; choice < var1; choice++)// the entry in format
        {
            cout << "\n" << readEntry(input) << endl
            << "\nPress Enter to continue...";
            getline (cin, input);
            cout << endl;
        }
    else
    {
        stringstream(input) >> choice;   // if choice != all, selects
        if (choice <= var1 && choice >0) // entry number in choice and
        {                                // prints its values
            choice--;
            cout << "\n" << readEntry(input) << endl
            << "\nPress Enter to continue...";
            getline (cin, input);
            cout << endl;
        }
        else
            cout << "\nInvalid Choice\n" << endl;
    }
}

void address_book::delEntry(string input) {
    if (input == "all")
    {
        book1 = book2 = new addBook[0];
        var1 = var2 = 0;
    }
    else
    {
        stringstream(input) >> choice;
        if (choice <= var1 && choice > 0)
        {
            book1 = new addBook[--var1];
            for (int a = var2 = 0; a <= var1; a++)
            {
                if (a == (choice-1)) continue;
                (book1+var2)->name = (book2+a)->name;
                (book1+var2)->address = (book2+a)->address;
                (book1+var2)->number = (book2+a)->number;
                var2++;
            }
            book2 = book1;
            var2 = var1;
            cout << "\n" << endl;
        }
        else
            cout << "\nInvalid Choice\n" << endl;
    }
}

string address_book::readEntry(string input) {
    name = (book1+choice)->name;      // stores entries information
    address = (book1+choice)->address;// to corresponding display
    number = (book1+choice)->number;  // variable
    retstr = "Name:\t\t" + name + "\nAddress:\t"
    + address + "\nNumber:\t\t" + number;
    return retstr;
}

These lines (99 - 101) as well as others look illegal to me:

temp.book1[a]->name = (book1+a)->name;
temp.book1[a]->address = (book1+a)->address;
temp.book1[a]->number = (book1+a)->number;

temp is of type address_book. address_book has a data member called book1, whose type is "pointer to addBook". I do not understand what you are referring to with this:

temp.book1[a]

It appears that you are treating "book1" as an array of type addBook*. However "book1" is not an array as defined in your class:

class address_book {
    addBook * book1, * book2;
    int var1, var2, choice;
    string retstr, name, address, number;

// class continues below
}

book1 is of type addBook*, but you are treating it as if it were an ARRAY of addBook*. You are trying to dereference something that cannot be dereferenced with the brackets here:

temp.book1[a]

I believe that is your error.

One : I thought it was possible to reference a pointer using array syntax since an array is a version of a pointer who's address cannot be changed, and therefore can be referenced with similar syntax. If this is not true, please let me know.

Two : If I cannot call it like that, how else can I reference it? I also tried the following code for the operator definition:

address_book address_book::operator+ (address_book part) {
    address_book temp;
    temp.var1 = var1 + part.var1;
    for (int a = 0, b = 0; a < temp.var1;  a++)
    {
        if (a < var1) // stores to temp until a is = to number of entries in
        {             // book1 then goes to part.book1 and starts over with b
        	(temp.book1+a)->name = (book1+a)->name;
        	(temp.book1+a)->address = (book1+a)->address;
        	(temp.book1+a)->number = (book1+a)->number;
        }
        else
        {
        	(temp.book1+a)->name = (part.book1+b)->name;
        	(temp.book1+a)->address = (part.book1+b)->address;
        	(temp.book1+a)->number = (part.book1+b)->number;
        	b++;
        }
    }
    temp.book2 = temp.book1;
    temp.var2 = temp.var1;
    return temp;
}

That code compiled just fine, but when I ran it and it reached the overloaded operator at the end of the code, the program experienced an error and crashed. (No explanation was included, but I was given a prompt to send the error report to Microsoft).

Yes, you sometimes can reference a pointer using array brackets. It depends on how things are set up. I'm not sure if this example is what you have in mind, but consider the following:

#include <iostream>
using namespace std;

int main ()
{
    char a[5] = {'f', 'g', 'h', 'i', 'j'};

    char b = a[3];
    char* c = a+3;
    
    cout << b << " " << *c << endl;
       
    return 0;
}

Running that program will yield the result:

i i

The array a takes up consecutive bytes. Say those bytes are at addresses 100 through 104:

100 f
101 g
102 h
103 i
104 j

a[0] will point to address 100, as will a. a[3] will point to address 103. a+3 will also point to 100 + 3 = 103. The letter i is stored at address 103. So a[3] and *(a+3) would be equivalent here.

This works because the five characters are stored in memory consecutively and each element is one byte, which is a known, constant size. In your case, you asked the compiler to create a single variable called "temp". You have no idea where in memory "temp" will be located, and more importantly where temp.book1 is stored or what it points to. You never assign it to anything in your constructor so it could be anywhere and probably contains jibberish. So I don't understand what you are trying to accomplish by adding to it.

As far as how to "reference it", I'm not clear on what "it" refers to. What are you trying to reference? Are you trying to assign part.book1->name to book1->name or something? Are you trying to access the individual characters within the two "name" strings? I'm not clear.

I'm reading your code again and it looks like book1 might be intended as an array after all. Hadn't noticed that before. Sorry. Probably posted too early. Still kind of going over it in my mind.

My initial intention was to make book1 a resizable array containing three variables in each entry of the array (name, address, and number).

I understood the referencing of pointers and the similarity to arrays and thats what I was trying to accomplish, but that clears things up for me a little bit, thank you Vernon. Actually, you asking me what I was trying to accomplish told me what I was lacking to fix my program. Thank you all very much.

This is what it was missing in the operator definition

temp.var1 = var1 + part.var1;
    temp.book1 = new addBook[temp.var1];

Thank you all once again, it is working now how i want it to.

O.K. I think I understand it a little better now. You have this:

temp.book1[a]->name = (book1+a)->name;
temp.book1[a]->address = (book1+a)->address;
temp.book1[a]->number = (book1+a)->number;

I think the problem is on the right side of the equation. If temp.book1 and book1 are BOTH arrays, you're probably looking to do this:

temp.book1[a]->name = book1[a]->name;
temp.book1[a]->address = book1[a]->address;
temp.book1[a]->number = book1[a]->number;

which is what a prior poster suggested here:

http://www.daniweb.com/forums/post532708-5.html

However it looks to me like temp.book1 is NOT an array since it was never declared to be one. If I am following the thinking correctly, I believe that if you added this line:

temp.book1 = new addBook[temp.var1];

after these lines in your + function:

address_book temp;
    temp.var1 = var1 + part.var1;

you would have temp.book1 be an array of the size that you want and the code block that Dave originally suggested would work.

temp.book1 is intended to be a variable that copies all the entries firs from book1 then from part.book1 and then return that book to the operator call. I now have the code fixed, thank you very much. To everybody.

As for the previous syntax working

temp.book1[a]->name = book1[a]->name;

That still won't compile for me and still gives me the same errors.

Instead I did this syntax (since all book1 variables are actually pointers not true arrays)

(temp.book1+a)->name = (book1+a)->name;

Not necessary for ya'll to read it, but it may be useful if someone else reads this post. Although I don't fully understand why the bracket syntax didn't work.

The -> identifies a member if the lhs is a pointer to an object. temp.book1[a] is an object, not a pointer. So you use the . operator. (temp.book1+a) is a pointer.

The former is more understandable IMO than the latter.

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.