Getting a "Use of undeclared identifier" error - c++

I am to create a custom String class in C++ with different methods in it.
The problem I have is that I get a "Use of undeclared identifier" error with a method that is declared in another file:
#include <iostream>
#include "String.h"
int main() {
std::cout << "Hello World!\n";
char str[] = "Today I am happy.";
cout<<strlen(str); // error
strlwr(str); //error
}
This is the other file, String.h:
#include <iostream>
using namespace std;
class Strings
{
public:
char *s;
Strings(char *a){
int l=0;
for(int i=0;a[i]!='\0';i++)
l++;
/*The length of string a*/
s=new char[l+1];
for(int i=0;a[i]!='\0';i++)
s[i]=a[i];
}
void strlwr(char *s1){ //method
for(int i=0;s1[i]!='\0';i++)
{
if(s1[i]>='A' && s1[i]<='Z')
s1[i]=(char)(s1[i]+32);
}
for(int i=0;s1[i]!='\0';i++)
cout<<s1[i];
}
int strlen(char *s1) //method
{
int l=0;
for(int i=0;s1[i]!='\0';i++)
{
l++;
}
return l;
}
int strcmp(char *s1,char *s2){
while(*s1 != '\0' && *s2 != '\0' && *s1 == *s2){
s1++;
s2++;
}
if(*s1 == *s2){
cout<<"They are equal";
return 0;
}
else if(*s1 >= *s2)
return 1;
else
return -1;
}
};
This has worked fine with other programs. I don't know why I have this problem now.

If these functions are independent of the class, you can declare them static.
static void strlwr(char *s1){ //method
static int strlen(char *s1) //method
And them use them like this:
cout<<String::strlen(str); // error
String::strlwr(str); //error

Related

Unknown Type Name when using threads

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.

C++ OOP private variable changes the value itself

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.

undefined reference to CLASS::function()

So when I try to simply compile my code using "g++ Asg5.cpp" I receive the following error
/tmp/cczhpSGO.o: In function 'main':
Asg5.cpp:(.text+0x2fb): undefined reference to 'BinomialTree::insert(int)'
collect2: ld returned 1 exit status
If anyone's wondering why I'm not using a makefile, my professor simply wants to type g++ <.cpp with main()> to compile..
Anyway here's my code I really appreciate the assistance!
Asg5.cpp
#include "BinomialTree.h"
#include "BinomialNode.h"
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
#include <stdlib.h>
#include <string>
#include <stdio.h>
using namespace std;
int main(int argc, char* argv[])
{
//input handling
if(argc != 2)
{
cout << "Incorrect Usage. \n Example: ./a.out <filename>" << endl;
exit(1);
}
BinomialTree *tree = new BinomialTree();
char *buffer;
char *token;
//read file into buffer.**************************************
string input;
ifstream file;
file.open(argv[1]);
if(file.is_open())
{
string str;
while(file.good())
{
getline(file,str);
input += " " + str;
}
}
else{
cout << "File not found"<< endl;
return 1;
}
file.close();
int buf;
stringstream ss(input);
vector<int> tokens;
while(ss >> buf)
{
tokens.push_back(buf);
}
int i = 0;
for(i = 0; i < tokens.size(); i++)
tree->insert(tokens[i]);
//end file reading *******************************************
delete tree;
}
BinomialNode.h
#ifndef _BINOMIALNODE_H_
#define _BINOMIALNODE_H_
#include "BinomialTree.h"
class BinomialNode
{
public:
int k;
BinomialNode *children[20];
int data;
BinomialNode();
};
#endif
BinomialNode.cpp
class BinomialNode
{
BinomialNode::BinomialNode(int n)
{
this->k = 0;
this->data = n;
}
}
BinomialTree.h
#ifndef _MULTIMAP_H_
#define _MULTIMAP_H_
#include "BinomialNode.h"
class BinomialTree
{
public:
BinomialNode * BQ[20];
void insert(int n);
void merge(BinomialNode *queue, BinomialNode *in, int k);
void print(BinomialNode *root, int tab);
};
#endif
BinomialTree.cpp
#include "BinomialNode.h"
#include "BinomialTree.h"
#include <iostream>
#include <cstdlib>
class BinomialTree
{
void BinomialTree::insert(int n)
{
BinomialNode *in = new BinomialNode(n);
if(BQ[0] == NULL)
{
BQ[0] = in;
return;
}
else
merge(BQ[0], in, 0);
}
void BinomialTree::merge(BinomialNode *queue, BinomialNode *in, int k)
{
if(queue == NULL)
{
BQ[k] = in;
return;
}
if(n == NULL)
{
BQ[k] = queue;
return;
}
if(queue->data > in->data)
{
merge(in, queue);
return;
}
queue->k++;
BinomialNode* temp[queue->k];
int i;
for(i = 0; i < queue->k-1; i++)
temp[i] = queue->children[i];
temp[queue->k-1] = in;
for(i = 0; i < queue->k; i++)
queue->children[i] = temp[i];
if(BQ[queue->k] == NULL)
{
BQ[queue->k] = queue;
return;
}
else
merge(queue, BQ[queue->k]);
}
void BinomialTree::print(BinomialNode *root, int tab)
{
if(root == NULL)
return;
int i;
for(i = 0; i < tab*5; i++) cout << " ";
cout << root->data << endl;
for(i = 0; i < root->k; i++) print(root->children[i], tab+1);
}
}
You cpp files shouldn't have Class in them. They should look more like:
BinomialNode.cpp
#include "BinomialNode.h"
BinomialNode::BinomialNode(int n) :
k(0)
{
data = n;
}
And of course the corollary for the much longer BinomialTree.cpp. Also, you should compile it with something like:
g++ BinomialTree.cpp BinomialNode.cpp Asg5.cpp -o asg5
Also you're going to run into a lot of other problems with you code. For instance:
BinomialNode * BQ[20];
I don't see BQ being initialized anywhere, which means you're pretty much guaranteed a seg fault if you were to run this. You need to initialize this or allocate it. Seeing lines like:
if(BQ[0] == NULL)
Makes me think you really wanted:
BinomialNode BQ[20];
Though you would still need to initialize it to all NULLs since you aren't guaranteed that will be full of NULLs when you run the program. Also, this is recursive and infinite and can't possibly work (in BinomialNode.h):
BinomialNode *children[20];
There are likely more issues with this code, but that wasn't your question, so I'll stop now!
You need to compile all the .cpp files into one program. You're not using BinomialTree.cpp anywhere right now. If your project requires that you simply type g++ Asg5.cpp then you need to #include your .cpp files or move their contents to your .h files. But the normal solution would be to build all the .cpp files together, not just the one containing main().

error LNK2001: unresolved external symbol _Main

I have some code here that doesn't seem to be linking properly. I have searched, and several places have suggested it is a problem with int main(). Not really sure what my problem is. I am pretty new to programming, and I have tried a few different things. Any help would be great!
I have four files: Wire.h, Wire.cpp, Gate.h, and Gate.cpp.
This is the Wire.h
#ifndef WIRE_H
#define WIRE_H
#include <iostream>
#include<vector>
#include<map>
#include<string>
#include "Gate.h"
using namespace std;
class Gate;
class Wire {
public:
// constructors
Wire();
// destructor
~Wire();
//functions
int getState();
void setState(int s);
private:
int State;
vector<Gate*> Gates;
vector<int> History;
};
#endif //WIRE_H
This is Wire.cpp:
#include "Wire.h"
#include<iostream>
using namespace std;
int main() {
cout << "Hello World";
return 0;
}
Wire::Wire(){
State = UNKNOWN;
}
Wire::~Wire(){
for (int i = 0; i < 1/*Gates.size()*/; i++){
Gates.pop_back();
}
for (int i = 0; i < 1/*History.size()*/; i++){
History.pop_back();
}
}
int Wire::getState() {
return State;
}
void Wire::setState(int s) {
State = s;
}
This is Gate.h:
#ifndef GATE_H
#define GATE_H
#include "Wire.h"
#include <iostream>
#include<vector>
#include<map>
#include<string>
using namespace std;
const int HI = 1;
const int LOW = 0;
const int UNKNOWN = -1;
class Wire;
class Gate {
public:
// destructor
~Gate();
//functions
void logic();
void setType(string);
void setDelay(int);
void setAIO(int i, int o); //Only for the NOT gate
void setBIO(int ain, int bin, int o); //For all gates except for NOT
private:
string Type;
Wire* inputA;
Wire* inputB;
Wire* output;
int delay;
};
#endif //GATE_H
This is Gate.cpp
#include "Gate.h"
#include<iostream>
using namespace std;
Gate::Gate(){
inputA = new Wire();
}
Gate::~Gate(){
delete inputA;
delete inputB;
delete output;
}
void Gate::logic(){
if (Type == "NOT"){
if (inputA->getState() == UNKNOWN){
}
if (inputA->getState() == HI){
output->setState(LOW);
}
if (inputA->getState() == LOW){
output->setState(HI);
}
}
if (Type == "AND") {
if (inputA->getState() == HI && inputB->getState() == HI){
output->setState(HI);
}
else {
output->setState(LOW);
}
}
if (Type == "OR") {
if (inputA->getState() == HI || inputB->getState() == HI){
output->setState(HI);
}
else {
output->setState(LOW);
}
}
if (Type == "XOR"){
if (inputA->getState() != inputB->getState()){
output->setState(HI);
}
else
{
output->setState(LOW);
}
}
if (Type == "NAND"){
if (inputA->getState() == HI && inputB->getState() == HI){
output->setState(LOW);
}
else{
output->setState(HI);
}
}
if (Type == "NOR"){
if (inputA->getState() == LOW && inputB->getState() == LOW){
output->setState(HI);
}
else{
output->setState(LOW);
}
}
if (Type == "XNOR"){
if (inputA->getState() == inputB->getState()){
output->setState(HI);
}
else
{
output->setState(LOW);
}
}
}
void Gate::setType(string t){
Type = t;
}
void Gate::setDelay(int d){
delay = d;
}
In c++, when compiling an executable, the compiler needs to know where to start execution. In order to make this happen, you need a function called main with this signature:
int main() { ... }
OR
int main(int argc, char** argv){ ... }
You don't have this function. Add it to one of your cpp files.

Redefinition and previous definition error

hpp file :
#pragma once
#include <string>
using namespace std;
class LiczbaException: public exception{
private:
string s;
public:
LiczbaException(string ss) :
s(ss){
};
virtual ~ LiczbaException() throw () {
};
virtual const char * erorrr() const throw () {
return s.c_str();
}
};
class RzymArab {
private:
static string liczby[13];
static int arabliczby[13];
public:
static int rzym2arab (string rzym);
static string arab2rzym (int arab) throw(LiczbaException);
};
string RzymArab::liczby[13] = {"I","IV","V","IX","X","XL","L","XC","C","CD","D","CM","M"};
int RzymArab::arabliczby[13] = {1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000};
test cpp :
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "RzymArab.hpp"
using namespace std;
int main(int argc, char * argv[]) {
bool sprawdz = true;
int t = 0;
string pom;
for (int l = 1; l < argc; l++) {
try {
t = atoi(argv[l]);
if (t == 0)
throw pom;
else
sprawdz = true;
} catch (string pom){
sprawdz = false;
}
if (sprawdz == false){
try{
int wynikk = RzymArab::rzym2arab(argv[l]);
if (argv[l] != RzymArab::arab2rzym(wynikk))
cout << "Nieistniejaca liczba" << endl;
else
cout << wynikk << "\n";
} catch (LiczbaException& w) {
cout << w.what() << endl;
}
} else {
try {
string wynik = RzymArab::arab2rzym(t);
cout << wynik << "\n";
} catch (LiczbaException& w){
cout << w.what() << endl;
}
}
}
return 0;
}
cpp file:
#include <iostream>
#include <cstdlib>
#include <cstring>
#include "RzymArab.hpp"
using namespace std;
class RzymArab
{
static int rzym2arab(string rzym) {
int wynik = 0;
for (int i = 0; i < rzym.length(); i++) {
int wart1 = 0;
int wart2 = 0;
for (int j = 0; j < 13; j++) {
if (rzym.at(i)==liczby[j].at(0)) {
wart1 = arabskie[j];
}
}
for (int k = 0; k < 13; k++) {
if (i<rzym.length()-1) {
if (rzym.at(i+1)==liczby[k].at(0))
wart2 = arabskie [k];
}
}
if (wart1 >= wart2) {
wynik+=wart1;
}else {
wynik+=(wart2 - wart1);
i = i + 1;
}
}
if (wynik > 3999)
cout << "Za duza liczba!";
if (wynik == 0)
cout << "Something get's wrong!";
return wynik;
}
static string arab2rzym(int arab) throw (LiczbaException) {
string wynik = "";
if (arab < 1 || arab > 3999)
throw LiczbaException("Zla podstawa");
for (int i = 0; i < 13; i++) {
while (arab >= arabskie[i]) {
wynik += liczby[i];
arab -= arabskie[i];
}
}
return wynik;
}
};
I got the errors while compiling:
" RzymArab.cpp:10:7: error: redefinition of 'class RzymArab'
class RzymArab
In file included form RzymArab.cpp:5:0:
RzymArab.hpp:26:7: error: previous definition of 'class RzymArab'
class RzymArab"
I don't know what is wrong, maybe something with pragma once but when i use old guard nothing change.
The class RzymArab is defined in the header (hpp) and in the body (cpp), this violates the one definition rule of C++ (ODR).
In the body, delete the class definition and define the members as following:
int RzymArab::rzym2arab(string rzym)
{
....
}
string RzymArab::arab2rzym(int arab) throw (LiczbaException)
{
....
}
Furthermore, defining RzymArab::liczby and RzymArab::arabliczby in the header also violates the ODR once the header is included more than once. So, move these definitions to the body too.
Finally, don't import namespaces in a header file (using namespace xxx). Generally, users of a header file expect their namespaces not to be polluted by including a header.
PS: You want to use a named constant instead of the magic number 13.
Exception specifications (throw (xx)) are an obsolete feature of C++. Since C++11 they have been superceded by noexcept specifiers. One reason that exception specifications have been made obsolete is that it is generally difficult to ensure that none but the specified exceptions are thrown. If the specification is violated, your program will by default terminate().