0
votes

So ive been writing my code for a bit now and im not the best coder in the world. im still learning and consider myself a beginner. im writing a lexical analysis for a concepts class in c++. Ive tried the solutions ive seen on websites like this such as using extern in the header file and using const in the cpp files, but noting works.when i include my header file in 2 separate .cpp files i get this error for all the ints in the header file:

tokens.obj : error LNK2005: "int eND" (?eND@@3HA) already defined in main.obj

header file=

#include <string.h>
#include <map>

using namespace std;

extern int lANGLE=1, rANGLE=2,iD=3, eQ=4, sLASH=5, qSTRING=6, oTHER=7, eND=8, tEXT=9;

map <int, int> counter;

extern int getToken(istream *br, string& lexeme);

token.cpp(declaring what getToken does)

#include "suffix.h"
#include <iostream>
#include <fstream>
#include <map>
#include <cctype>

bool slash = false;
bool text = false;
bool quote = false;
bool id = false;
bool equ =  false;
bool other = false;
bool qstring = false;
char prev=NULL;

int getToken(istream *in, string& lexeme)
{
    char c;
    char prev;
    lexeme="";

    int intSlash = 0;

    int intText = 0;

    int intQuote = 0;

    int intId = 0;

    int intEqual = 0;

    int intOther = 0;

    int intQstring = 0;

    int langlec = 0;
    int  intLangle = 0;

    int ranglec = 0;
    int  intRangle = 0;

    if (in->eof())
        return eND;

    while (in->get(c))
    {
        switch (c)
        {
            case '/' :
                if (quote == false && langlec > 0)
                {
                slash = true;
                intSlash++;
                return 5;
                }
                break;

            case '=' :
                if (quote == false && langlec > 0)
                {
                 equ = true;
                intEqual++;
                return 4;
                }
                break;

            case '<' :

                if (  prev != ' '  && langlec == 0) 
                    {intText++ ;
                return 9;}

                if (quote == false)
                {
                    langlec ++;
                    intLangle ++;
                    id = true;
                    return 1;
                }


                break;


            case '>' :

                if (quote != true)
                {
                    ranglec++;
                    intRangle++;
                    return 2;

                    if (langlec > 0)
                    {
                        langlec--;
                        id = false;
                    }
                }   
                break;

            case '"' :
                if (langlec > 0 && quote == true)
                {
                    quote = false;
                    id = true;
                    intQstring ++;
                    intOther--;
                    return 6;
                }
                else if (langlec > 0)
                {
                    intOther++;
                    quote = true;   
                    return 7;
                }



                break;

            case ' ':
                if ( prev != ' ' && prev != '<' && prev != '>' && quote == false){
                    if (langlec == 0){
                        intText++;
                        return 9;
                    }
                }
                    else if ( prev != '/' && prev != '=')
                        {intId++;
                        return 3;
                    }

                break;

            default:

                if (quote == true)
                    {
                        id = false;
                    }

                else if (id==true) 
                    {
                        intId++;
                        id=false;
                        return 3;
                    }
                prev=c;

        }
    }
return 0;
}

main.cpp

#include <iostream>
#include <fstream>
#include <map>
#include <cctype>
#include <string>
#include <algorithm>
#include "suffix.h"

using namespace std;

int
main( int argc, char *argv[] )
{
 istream *br;
 ifstream infile;
 // check args and open the file
if( argc == 1 )


br = &cin;
 else if( argc != 2 ) {
cout<<"THERE IS A FATAL ERROR"<<endl; 
return 1; // print an error msg
 } else {
 infile.open(argv[1]);
 if( infile.is_open() )
 br = &infile;
 else {
 cout << argv[1] << " can't be opened" << endl;
 return 1;

 }
}
string tokens="";
int typeOfToken;

while(true){
    typeOfToken=getToken(br,tokens);
    if (counter.count(typeOfToken))
        counter[typeOfToken]+=1;
    else
        counter[typeOfToken]=1;

    if(typeOfToken==8)
        break;
}
cout<<"total token count: "<<endl;
if (counter[1]!=0)
    cout<<"LANGLE: "<<counter[1]<<endl;
if (counter[2]!=0)
    cout<<"RANGLE: "<<counter[2]<<endl;
if (counter[9]!=0)
    cout<<"TEXT: "<<counter[9]<<endl;
if (counter[3]!=0)
    cout<<"ID: "<<counter[3]<<endl;
if (counter[4]!=0)
    cout<<"EQ: "<<counter[4]<<endl;
if (counter[5]!=0)
    cout<<"SLASH: "<<counter[5]<<endl;
if (counter[6]!=0)
    cout<<"QSTRING: "<<counter[6]<<endl;
if (counter[7]!=0)
    cout<<"OTHER: "<<counter[7]<<endl;

return 0;
}
1
You're defining it in the header, so it gets defined in both files. You need to declare it in the header, and define it in only one of them. - Crowman

1 Answers

0
votes
extern int lANGLE=1, ...  eND=8

This is supposed to be extern declaration, but due to explicit initialization it's actually a definition. So you end up defining all these variables in several translation units, leading to violation of One Definition Rule.

When you fix this, you'll have the same problem with map <int, int> counter;

What you should do is to answer yourself the question, why do you have to declare all of these in a header file. map <int, int> counter; is used only in main.cpp, so move it there. And the int variables can be replaced with one enum, because it seems you are going to use them as return values for getToken().

So it will be something like

enum Token {
    lANGLE=1, rANGLE=2,iD=3,...
};

Token getToken(istream *br, string& lexeme);