0

I am working on a project for my c++ class and although my code looks fine to me (a beginner) whenever I run it I get error C2065 undeclared identifier in almost every line. I have done my research and have a feeling it has something to do with using namespace std; but I am not sure. Any help would be greatly appreciated.

The project is to create a vector that store a book list and then offer the user the ability to add a book to the list, display the list using an iterator, remove a book using an iterator, or store the data in an external file. Here is what I have so far:

#include <iostream>
#include <vector>
#include <string>
#include "bookColl.h"
#include <algorithm>
#include <fstream>

using namespace std;

int main()
{
    vector <string> bookCollection;
    string book1, book2, book3;

    cout << "Enter the first book in your book collection: " << endl;
    getline(cin, book1);

    cout << "\nEnter the second book in your book collection: " << endl;
    getline(cin, book2);

    cout << "\nEnter the third book in your book collection: " << endl;
    getline(cin, book3);

    bookCollection.push_back(book1);
    bookCollection.push_back(book2);
    bookCollection.push_back(book3);

    vector <string> ::iterator myITER;
    vector <string> ::const_iterator cITER;

    double decide;

    do
    {
        int choice = 0;
        cout << "What would you like to do?/n1.Add a book to your collection." <<
            "/n2.Display your book collection." << "/n3.Remove a book from your collection" << "/n4. Stop adding books and store the data in an external file" << "/nChoose a number 1 through 4: " << endl;

        if (choice == 1)
        {
            string addNew;
            addBook(&addNew);
            bookCollection.push_back(addNew);
        }

        else if (choice == 2)
        {
            cout << "Here are your books: " << endl;
            for (cITER = bookCollection.begin(); cITER != bookCollection.end(); cITER++)
            {
                cout << *cITER << endl;
            }
        }

        else if (choice == 3)
        {
            int removeBook;
            myITER = bookCollection.erase(bookCollection.begin() + removeBook);
            cout << "enter the numbered book position for the book you would like to remove: " <<
                "/n(The books in your book collection are labels for 0 up)" << endl;
            cin >> removeBook;
            cout << *myITER << endl;
        }

        else if (choice == 4)
        {
            sort(bookCollection.begin(), bookCollection.end());

            ofstream bookFile;
            bookFile.open("BookCollection.txt", ios::out | ios::app);
            bookFile << " This is a line of text. \n";
            bookFile << " This is a second line of text. \n";
            bookFile.close();
        }

        cout << "\nWould you like to run this program again? If so select 1 for Yes, and 0 for No" << endl;
        cin >> decide;

    } while (decide > 0);
}

bookColl.h

string addBook(string* pValOne);

bookColl.cpp

#include <iostream>
#include <vector>
#include <string>
#include "bookColl.h"

using namespace std;

string addBook(string* pValOne)
{
    string newBook;
    *pValOne = newBook;
    cout << "What is the name of the book you would like to add?" << endl;
    getline(cin, *pValOne);
    return newBook;
}
Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Brian Roper
  • 528
  • 7
  • 13
  • What is the undeclared identifier ? That will help a lot. It probably isn't related to the `using namespace std;` though. Please have a look at http://stackoverflow.com/q/1452721/3233393 nonetheless. And welcome to StackOverflow ! – Quentin Jul 16 '15 at 19:41
  • 2
    Sounds like a *compiler error*, not a runtime error (i.e. the error happens while compiling, so there is nothing to run). Make sure you update your question with the *exact* error message. – crashmstr Jul 16 '15 at 19:43
  • Your code compiles for me. Please post the exact error you're getting. – Barry Jul 16 '15 at 19:46
  • 1
    Apart from building a dependency on include-ordering (which you should not do) and implementing a non-inline/non-template function in a header file (likewise, don't do), ... – WhozCraig Jul 16 '15 at 19:47
  • `bookColl.h` has no includes at all. How is it supposed to know what a `string` is?? – scohe001 Jul 16 '15 at 19:53
  • 1
    @scohe001 thus the ill-advised dependency on header ordering from the including.cpp file I mentioned. – WhozCraig Jul 16 '15 at 19:54

2 Answers2

2

bookColl.h must look like this:

#ifndef BOOK_COLL_H
#define BOOK_COLL_H

#include <string>

std::string addBook(std::string* pValOne);

#endif

You need an include guard, and the full name of the class is std::string, not string; that's what you get with #include <string>. Your code does not compile because the using namespace std; comes after the #include "bookColl.h".

Speaking of using namespace, my advice would be to forget about it, at least for now. Just use std:: everywhere.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • There's also `#pragma once` as an alternative to include guards. I don't know how widely supported it is now. – celticminstrel Jul 16 '15 at 20:50
  • @celticminstrel: The problem with this is that it possibly does not work reliably when the same file is accessed by the system in a different way (think of network drives). Include guards do not have that problem. – Christian Hackl Jul 17 '15 at 04:30
  • @celticminstrel: Not that the include guard in my example is particularly great. A good include guard should name should have a long randomised part, generated automatically by your editor, to avoid collisions. – Christian Hackl Jul 17 '15 at 04:36
  • This fixed everything for me. Once I put in the include guard the program compiled with no errors. Thank you, from now on I will try to avoid using namespace. – Brian Roper Jul 17 '15 at 14:16
  • If your source filenames are unique, and you put a project-specific prefix on the include guard, it should be fine without an editor-generated random portion. – celticminstrel Jul 17 '15 at 17:57
1

Avoid using namespace std; in header files like it was the plague. Read here for why.

After editing by Nathan, it is obvious that string isn't sufficient for your prototype. The compiler hasn't a clue what that type is, as std:string isn't made available as simply string until the subsequent using namespace std;. The solution is NOT to move the header include below using namespace std; rather you would never rely on using namespace std; or the .cpp file for header inclusion dependencies in the first place. In other words, That header is wrong to begin with. It should look something like this:

#ifndef MYAPP_BOOKCOLL_H
#define MYAPP_BOOKCOLL_H

#include <string>

std::string getBook();

#endif

Debate about #pragma once left out, and I refuse to participate in it. From there, your .cpp file can look like this:

#include "bookColl.h"
#include <iostream>
#include <string>

std::string getBook()
{
    std::string newBook;
    std::cout << "What is the name of the book you would like to add?" << std::endl;
    std::getline(std::cin, newBook);
    return newBook;
}

The inclusion of bookColl.h as the first header ensures your user-defined header file bookColl.h is properly implemented and has no reliance on the .cpp file including something the header itself relies on (and should therefore be including itself). It cannot (and should not) depend on the consuming .cpp file's previous declarations of system header includes.

I leave how to include bookColl.h in your main.cpp file and the slurry of errors in that file for you to address.

WhozCraig
  • 65,258
  • 11
  • 75
  • 141