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;
}
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);
Related
I am trying to find the minimum vertex cover by giving the vertex and edge input in specific format from the user using threads. Here is my code:
#include <iostream>
#include <string>
#include <sstream>
#include <fstream>
#include <cctype>
#include <list>
#include <set>
#include <vector>
#include <climits>
#include <memory>
#include <algorithm>
#include <pthread.h>
#include <unistd.h>
#include "minisat/core/Solver.h"
using namespace std;
static void *AVC2_Vertex_Cover(void *);
void min_vertex_cover_algorithm(Graph &graph_builder){
int ret;
pthread_t AVC2_thread;
ret = pthread_create(&AVC2_thread, NULL, AVC2_Vertex_Cover, &graph_builder);
if(ret)
exit(1);
pthread_join(AVC2_thread, NULL);
pthread_exit(NULL);
}
struct Edge{
unsigned v1,v2;
};
typedef std::vector<unsigned> Vertex_vector;
typedef std::list<unsigned > Vertex_Adjacency_list;
typedef std::vector<Vertex_Adjacency_list> Adjacency_Traversal_list;
struct Graph{
std::size_t no_of_edges;
Adjacency_Traversal_list adjacency_list;
void initialize_graph(unsigned vertices_number);
void construct_edge(Edge edge);
void clear(unsigned vertex);
};
void Graph::initialize_graph(unsigned num){
adjacency_list.clear();
no_of_edges = 0;
adjacency_list.resize(num,{});
}
void Graph::construct_edge(Edge edge) {
auto &literal_1 = adjacency_list[edge.v1];
auto &literal_2 = adjacency_list[edge.v2];
literal_1.push_back(edge.v2);
literal_2.push_back(edge.v1);
no_of_edges ++;
}
void *AVC2_Vertex_Cover(void *input)
{
Graph g = *(const Graph *)input;
unsigned int V = g.adjacency_list.size();
bool visited[V];
for (int i=0; i<V; i++)
visited[i] = false;
for (int u=0; u<V; u++)
{
if (visited[u] == false)
{
for(int x : g.adjacency_list[u])
{
int v = x;
if (visited[v] == false)
{
visited[v] = true;
visited[u] = true;
break;
}
}
}
}
// Print the vertex cover
std::cout << "APPROX-VC-2: ";
for (int i=0; i<V; i++){
if (visited[i])
if(i == V-1)
cout << i << std::endl;
else
cout << i << ",";
}
}
void *IO_thread(void *)
{
Graph &graph_builder = *new Graph();
char character_input;
string my_input;
unsigned int no_of_vertices = 0;
string edge_stream;
char prev_choice = ' ';
while (getline(cin, my_input))
{
istringstream stream_string(my_input);
while (stream_string >> character_input)
{
character_input=(toupper(character_input));
try
{
switch (character_input)
{
case 'V' :
if (prev_choice == 'V')
{
cerr << "Error: V must be followed by E only.\n";
break;
}
else
{
stream_string >> no_of_vertices;
if(no_of_vertices <= 0)
{
throw "Invalid number of vertices";
}
graph_builder.initialize_graph(no_of_vertices);
prev_choice = 'V';
break;
}
case 'E' :
{
unsigned int flag_Entry = 0;
if ( prev_choice == 'E')
{
cerr << "Error: V and E always occur together.\n ";
break;
}
else
{
stream_string >> edge_stream;
istringstream edge_stream_character(edge_stream);
char edg_char;
unsigned int temp = 0;
unsigned int v1;
unsigned int v2;
edge_stream_character >> edg_char;
while (edg_char != '}')
{
edge_stream_character >> edg_char;
if (edg_char == '}')
{
flag_Entry = 1;
break;
}
else
{
edge_stream_character >> temp;
v1 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> temp;
v2 = temp;
edge_stream_character >> edg_char;
edge_stream_character >> edg_char;
if (v1 >= no_of_vertices || v2 >= no_of_vertices)
{
cerr << "Error: Vertex out of range.\n";
graph_builder.adjacency_list.clear();
break;
}
graph_builder.construct_edge({v1,v2});
}
}
if(flag_Entry == 1)
{
prev_choice = 'E';
break;
}
min_vertex_cover_algorithm(graph_builder);
prev_choice = 'E';
break;
}
}
}
}
catch (const char* err)
{
cerr << "Error:" << err << endl;
}
}
}
return 0;
}
int main(int argc, char **argv){
int ret;
pthread_t IO_thread;
ret = pthread_create(&IO_thread, NULL, IO_thread,NULL);
if(ret)
return 1;
pthread_join(IO_thread,NULL);
pthread_exit(NULL);
}
I am getting an error:
unknown type name 'Graph'
void min_vertex_cover_algorithm(Graph &graph_builder){
I am not able to find why this error is occuring. It will be very helpful if I get some solutions.
Just like you, the compiler will read from top to bottom. When it reaches the line:
void min_vertex_cover_algorithm(Graph &graph_builder){
It has to go, ok, lets use a Graph reference. It will look for the declaration of a Graph, which it cannot find, because you have declared (and defined) it below. To solve this, give the compiler a hint. Declare the Graph above the function with:
struct Graph;
void min_vertex_cover_algorithm(Graph &graph_builder){
Or simply move the whole struct definition above the function.
So I programmed a simple lexer which I currently studying is Language Implementation Patterns.
The codes in the said book is written in JAVA and I've tried to code it using C++.
It just have to recognized the tokens i provided in the program for example and spaces will be skipped:
'[ABCDE , EFGH]'
[ - LBRACK
ABCDE - NAME
, - COMMA
EFGH - NAME
So I build different classes as I convert the classes in JAVA to C++.
Token.h
#pragma once
#include <string>
#include <vector>
using namespace std;
constexpr auto NAME = 2;
constexpr auto COMMA = 3;
constexpr auto LBRACK = 4;
constexpr auto RBRACK = 5;
class Token
{
public:
Token();
~Token();
Token(int , const char * text );
char * to_string();
string tokenNames[6] = { "n/a" , "<EOF>", "NAME", "COMMA", "LBRACK", "RBRACK" };
int token_type() { return this->type; }
private:
int type = 0;
char * text = NULL;
};
Token.cpp
#include "Token.h"
Token::Token() {
}
Token::~Token(){
}
Token::Token(int type, const char * text) {
this->text = (char *)text;
this->type = type;
}
char* Token::to_string() {
char* out_buffer = new char[255];
vector <string> tokenNames;
int size = sizeof(this->tokenNames) / sizeof(this->tokenNames[0]);
for (int i = 0; i <size; i++)
{
tokenNames.push_back(this->tokenNames[i]);
}
printf("%s", this->text);
sprintf(out_buffer, "%s , %s \n", this->text, tokenNames[this->type].c_str());
return out_buffer;
}
Lexer.h
#pragma once
#include <string>
#include <vector>
#include "Token.h"
#define EOF -1
constexpr auto EOF_TYPE = 1;;
using namespace std;
class Lexer
{
public:
Lexer();
~Lexer();
Lexer(vector <char> input);
void consume();
void match(char x);
char get_c() {
return c;
}
vector<char> input;
char c;
private:
int p = 0;
};
Lexer.cpp
#include "Lexer.h"
Lexer::Lexer()
{
}
Lexer::~Lexer()
{
}
Lexer::Lexer(vector <char> input) {
this->input = input;
c = input.at(p);
}
void Lexer::consume() {
p++;
if (p >= this->input.size()) c = EOF;
else c = this->input.at(p);
}
void Lexer::match(char x) {
if (this->c == x) consume();
else throw "wrong input";
}
ListLexer.h
#pragma once
#include <vector>
#include "Token.h"
#include "Lexer.h"
class ListLexer : public Lexer, Token
{
public:
ListLexer();
~ListLexer();
Lexer* lexer;
ListLexer(vector <char> x) {
lexer = new Lexer(x);
c = lexer->get_c();
}
char* get_token_names(int x);
Token* next_token();
void skip_space();
bool is_letter();
char * name();
private:
char c = NULL;
};
ListLexer.cpp
#include "ListLexer.h"
ListLexer::ListLexer()
{
c = lexer->c;
}
ListLexer::~ListLexer()
{
}
char* ListLexer::get_token_names(int x) {
char out_buffer[100];
sprintf(out_buffer, "%s", Token::tokenNames[x]);
return out_buffer;
}
Token* ListLexer::next_token() {
while ((c= lexer->c) != EOF) {
switch (c) {
case ' ': case '\t': case '\n': case '\r': skip_space(); continue;
case '[':
lexer->consume();
return new Token(LBRACK, "LBRACK");
case ']':
lexer->consume();
return new Token(RBRACK, "RBRACK");
case ',':
lexer->consume();
return new Token(COMMA, "COMMA");
default:
if (is_letter()) return new Token(NAME, name());
throw "wrong input";
}
}
return new Token(EOF_TYPE, "EOF");
}
void ListLexer::skip_space() {
while (c == ' ' || c == '\t' || c == '\n' || c == '\r')
consume();
}
bool ListLexer::is_letter() {
return (lexer->c >= 'a' && lexer->c <= 'z') || (lexer->c >= 'A' && lexer->c <= 'Z');
}
char* ListLexer::name() {
vector <char> buffer;
char out_buffer[255];
while (is_letter()) {
buffer.push_back(lexer->c);
lexer->consume();
}
buffer.push_back('\x00');
std::copy(buffer.begin(), buffer.end(), out_buffer);
printf("%s", out_buffer);
return out_buffer;
}
main.cpp
#include <stdio.h>
#include <vector>
#include "Token.h"
#include "Lexer.h"
#include "ListLexer.h"
using namespace std;
int main(int argc, char* argv[])
{
vector <char> vec;
vec.push_back('a');
vec.push_back('b');
vec.push_back('c');
vec.push_back('d');
vec.push_back(',');
vec.push_back('e');
vec.push_back('f');
vec.push_back('g');
vec.push_back('h');
vec.push_back('\xff');
ListLexer* listlexer = new ListLexer(vec);
try {
Token* t = listlexer->next_token();
while (t->token_type() != EOF_TYPE)
{
printf("%s", t->to_string());
t = listlexer->next_token();
}
printf("%s", t->to_string());
}
catch (const char * e) {
printf("Error: %s \n", e);
}
return 0;
}
However, everytime it calls the t->to_string(), the value of text which is should be name "ABCD" or "EFGH" is different.
The highlighted figures are from the ListLexer::name().
The value of the text which is private from the instantiated token class is modified.
Did I miss something? Please help me. Im just learning OOP through this.
I have to write a program which balances a string with brackets.I wrote the program but it doesn't matter which string I enter because the program always says that the string is good.
Here's the code:
header file
#ifndef HEADER_H_
#define HEADER_H_
#include <string>
struct Element {
char data;
Element* link;
};
typedef Element* Stack;
void initStack(Stack& S);
void push(Stack& S, int a);
void pop(Stack &S);
int top(Stack& S);
bool isEmpty(Stack &S);
bool goodPair(char deschis, char inchis);
bool check(std::string s);
#endif
functions file
#include <iostream>
#include <string>
#include "header.h"
using namespace std;
void initStack(Stack& S)
{
S = nullptr;
}
void push(Stack& S, int a)
{
Element*nou = new Element;
nou->data = a;
nou->link = S;
S = nou;
}
void pop(Stack& S)
{
Stack aux = S;
S = S->link;
delete(aux);
}
int top(Stack& S)
{
if (isEmpty(S))
return int();
return S->data;
}
bool isEmpty(Stack &S)
{
if (S == 0)
return true;
else
return false;
}
bool goodPair(char deschis, char inchis)
{
if (deschis == '(' && inchis == ')')
return true;
else if (deschis == '[' && inchis == ']')
return true;
else if (deschis == '{' && inchis == '}')
return true;
else if (deschis == '<' && inchis == '>')
return true;
else
return false;
}
bool check(std::string s)
{
Element* S;
for (int i = 0; i < s.length(); i++)
{
if (s[i] == '(' || s[i] == '[' || s[i] == '{' || s[i] == '<')
push(S, s[i]);
else
{
if (s[i] == ')' || s[i] == ']' || s[i] == '}' || s[i] == '>')
if (isEmpty(S) || !goodPair(top(S), s[i]))
return false;
else
pop(S);
}
}
if (isEmpty(S))
return false;
else
return true;
}
main file
#include <iostream>
#include <string>
#include "header.h"
using namespace std;
int main()
{
Stack S;
initStack(S);
string s;
cout << "Write the string:";
cin >> s;
if (check(s))
cout << "Good";
else
cout << "Bad";
return 0;
}
I used a stack and I traversed each character.If the character is an opening bracket I put it in the stack.When the character is a closing bracket, I compare it with the top of the stack.If it's good I pop the top of the stack.
You create a pointer to Element (aliased as Stack) S in main() and initialize it with nullptr using initStack() and then you do not use this variable anymore. Instead you create a local S in function check() and use it uninialized, which leads to UB.
Looks like you get confused by naming as you call of them S (variable in main(), variable in check(), all reference parameters all called S). It is not illegal to do so, but looks like you confused yourself. (you even called std::string lowercase s to increase confusion)
Also you have logical error in your function:
if (isEmpty(S))
return false;
else
return true;
should be opposite, if stack is empty then string is balanced, not vice versa. So replace it with:
return isEmpty( S );
Aim is to make sure that the user entered input for string 1 and string 2 contains only characters A,T,G or C in any order. If either string contains another other character then error should be displayed. Example:
Input contains error
Error in String #1: aacgttcOgMa
Error in String #2: ggataccaSat
This is my attempt at LCS.cpp file code:
#include "LCS.h"
#include <string>
using namespace std;
bool validate(string strX, string strY)
{
string x = strX;
string y = strY;
char searchItem = 'A';
char searchItem = 'C';
char searchItem = 'G';
char searchItem = 'T';
int numOfChar = 0;
int m = strX.length();
int n = strY.length();
for (int i = 0; i < m; i++)
{
if (x[i] == searchItem)
{
numOfChar++;
}
for (int i = 0; i < n; i++)
{
if (y[i] == searchItem)
{
numOfChar++;
}
}
}
This is my LCS.h file code:
#pragma once
#ifndef LCS_H
#define LCS_H
#include <string>
using namespace std;
bool validate(string strX, string strY);
#endif
And my driver file "Driver6.cpp" has this code:
#include "LCS.h"
#include <iostream>
#include <string>
using namespace std;
int main()
{
string strX, strY;
cout << "String #1: ";
cin >> strX;
cout << "String #2: ";
cin >> strY;
//validate the input two strings
if (validate(strX, strY) == false)
{
return 0;
}
int m = strX.length();
int n = strY.length();
}
Didn't really want to do this but it seems like the best bet rather than going round the houses in the comments:
#include <string>
#include <iostream>
bool validate( const std::string & s ) {
for ( auto c : s ) {
if ( c != 'A' && c != 'T' && c != 'C' && c != 'G' ) {
return false;
}
}
return true;
}
int main() {
std::string s1 = "ATGCCCG";
std::string s2 = "ATGfooCCCG";
if ( validate( s1 ) ) {
std::cout << "s1 is valid\n";
}
else {
std::cout << "s1 is not valid\n";
}
if ( validate( s2 ) ) {
std::cout << "s2 is valid\n";
}
else {
std::cout << "s2 is not valid\n";
}
}
Another technique:
bool validate(const std::string& s)
{
const static std::string valid_letters("ATCGatcg");
for (auto c: s)
{
std::string::size_type position = valid_letters.find_first_of(c);
if (position == std::string::npos)
{
return false;
}
}
return true;
}
The above code searches a container of valid letters.
I'm writing a program that uses stacks to evaluate infix expressions read in from a file. Here is the code:
ptStack.h
#ifndef STACK
#define STACK
#include <cstdlib>
#include <iostream>
using namespace std;
template <class Item>
class Stack
{
public:
// CONSTRUCTOR
Stack( ) {top = NULL; count = 0;} // Inline
// MODIFIER MEMBER FUNCTIONS
void push( const Item& entry);
Item pop( );
// CONSTANT MEMBER FUNCTIONS
int size( ) {return count;} // Inline
bool is_empty( ) {return count == 0;} // Inline
private:
// DATA MEMBERS
struct Node
{
Item element;
Node *next;
};
Node *top;
int count;
};
#endif
ptStack.cpp
#include <cassert>
#include "ptStack.h"
using namespace std;
// MODIFIER MEMBER FUNCTIONS
template <class Item>
void Stack<Item>::push(const Item& entry)
{
Node *temp;
temp = new Node;
temp->element = entry;
temp->next = top->next;
top->next = temp;
count++;
}
template <class Item>
Item Stack<Item>::pop( )
{
Item value;
Node *temp;
value = top->next->element;
temp = top->next;
top->next = top->next->next;
delete temp;
count--;
return value;
}
infix.cpp
#include <iostream>
#include <fstream>
#include <cstdlib>
#include "ptStack.h"
using namespace std;
// PRECONDITION: op must be an operator
// POSTCONDITION: returns precedence of operator
int pr(char op)
{
int precedence = 0;
switch (op)
{
case '+':
case '-': precedence = 1;
case '*':
case '/': precedence = 2;
default : precedence = 0;
}
return precedence;
}
// PRECONDITIONS: optr is one of the following: + - * /
// opnd1 and opnd2 are numbers from 1-9
// POSTCONDITIONS: returns the result of the chosen mathematical operation
int apply(char optr, int opnd1, int opnd2)
{
int result;
switch (optr)
{
case '+': result = opnd2+opnd1;
case '-': result = opnd2-opnd1;
case '*': result = opnd2*opnd1;
default : result = opnd2/opnd1;
}
return result;
}
int main()
{
Stack<int> numbers;
Stack<char> operators;
char ch, optr;
int num, opnd1, opnd2, prec = 0, newprec;
ifstream in_file; // input file
char in_file_name[20]; // name of input file (20 letter max)
cout << "Enter input file name: ";
cin >> in_file_name;
in_file.open(in_file_name); // opens file to read equations
while (!in_file.eof())
{
cout << "Expression: ";
while(in_file >> ch)
{
if (ch == ' ')
{}
else
{
num = ch - '0';
if((num < 10) && (num > 0))
{
cout << num << " ";
numbers.push(num);
}
else if((ch == '+') || (ch == '-') || (ch == '*') || (ch == '/'))
{
cout << ch << " ";
newprec = pr(ch);
if(newprec >= prec)
{
prec = newprec;
operators.push(ch);
}
else if(newprec < prec)
{
optr = operators.pop( );
opnd1 = numbers.pop( );
opnd2 = numbers.pop( );
num = apply(optr, opnd1, opnd2);
numbers.push(num);
operators.push(ch);
}
}
}
if(in_file.peek() == '\n')
break;
}
num = operators.size();
while(num != 0)
{
optr = operators.pop( );
opnd1 = numbers.pop( );
opnd2 = numbers.pop( );
num = apply(optr, opnd1, opnd2);
numbers.push(num);
num = operators.size( );
}
num = numbers.pop( );
cout << endl << "Value = " << num << endl << endl;
}
return 0;
}
It looks like everything should work but when I compile it, I get this error message.
> g++ -c ptStack.cpp
> g++ infix.cpp ptStack.o
Undefined first referenced
symbol in file
_ZN5StackIcE4pushERKc /var/tmp//ccwhfRAZ.o
_ZN5StackIiE4pushERKi /var/tmp//ccwhfRAZ.o
_ZN5StackIcE3popEv /var/tmp//ccwhfRAZ.o
_ZN5StackIiE3popEv /var/tmp//ccwhfRAZ.o
ld: fatal: symbol referencing errors. No output written to a.out
I've been able to pinpoint the errors to the callings of the push and pop member functions in the main of the infix file. I tried defining them inline in the header file like the size function and it compiles just fine using g++ infix.cpp ptStack.h, but then I get a segmentation fault when I run it.
Does anyone know how to fix either of these errors? Thanks in advance.
Just compile all the .cpp files with g++
g++ ptStack.cpp infix.cpp