so I was trying to compile a file and I got this error(mingw-64):
C:\Users\me\AppData\Local\Temp\ccfdOWKk.o:EKLexer.cpp:(.text+0x0): multiple definition of `Lexer::Tokenize(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
C:\Users\me\AppData\Local\Temp\cc9yNSun.o:EnderKnightShell.cpp:(.text+0x0): first defined here
C:\Users\me\AppData\Local\Temp\ccfdOWKk.o:EKLexer.cpp:(.text+0x36a): multiple definition of `Lexer::ProcessVariables(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >)'
C:\Users\me\AppData\Local\Temp\cc9yNSun.o:EnderKnightShell.cpp:(.text+0x36a): first defined here
collect2.exe: error: ld returned 1 exit status
I've tried looking but there's none that seems to fit what issue I'm having(which seems to involve a function being used). I'm not much of a C++ person so I'm not sure what exactly is going on
EnderKnightShell.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "EKLexer.cpp"
#include <C:\EndorCore\EnderKnight Python Port\Full Language\C++ Compiler\Headers\PythonStatements.h>
using std::string;
using std::ifstream;
using std::vector;
using py::Python;
ifstream EnderScript("Test.ek");
int main() {
Lexer EkLexer;
Python python;
cout << "EnderKnight C++ Port Beta 1:" << endl;
for(string CodeLine; getline(EnderScript, CodeLine);){
EkLexer.Tokenize(CodeLine);
}
for (int i = 0; i < python.splitlines.size(); i++){
for (int j = 0; j < python.splitlines[i].size(); j++){
cout << python.splitlines[i][j] << endl;
}
}
}
EKLexer.cpp
class Lexer{
private:
typedef vector<map<string, string>> Tokens;
typedef vector<string> KeyWords;
Tokens tokens;
KeyWords keywords{
"echo",
"goto",
"stop",
"math",
"var",
"edef",
"end_edef",
"/*",
"if",
"end_if_state"};
public:
void Tokenize(string);
void ProcessVariables(string);
Python python;
};
void Lexer::Tokenize(string Code){
stringstream s(Code);
string temp;
while (s >> temp) {
if (temp.compare("echo") == 0) {
map<string, string> EchoMap {{"echo", Code}};
tokens.push_back(EchoMap);
}
else if (temp.compare("var") == 0) {
Lexer::ProcessVariables(Code);
}
// more code
void Lexer::ProcessVariables(string Code){
python.Split(Code, '=');
}
Thanks to templatetypedef's comment, I found that the issue was including a .cpp file. The solution is to use a header and cpp source file combo
Related
I have a homework that requires me to do operations on a string, I used an iterator in the second function to find the last index of a letter in the string and first index of it to find the distance between them.
here is my code, focus on int textProcessing(const string &inputString, char letter); function:
#include <iostream>
#include <fstream>
#include <string>
#include<algorithm>
#include <iomanip>
#include <iterator>
using namespace std;
void textProcessing(string &inputString);
int textProcessing(const string &inputString, char letter);
void textProcessing(string &inputString, char orgChar, char newChar);
int main() {
ofstream out("text.txt");
out<<"the earth is a very small stage in a vast cosmic arena";
out.close();
unsigned short operation;
cin >> operation;
string sentence;
fstream inputstream;
inputstream.open("text.txt");
while (!inputstream.eof()) {
getline(inputstream, sentence);
if (sentence.length() > 0) {
// Your code starts here
if (operation==0){
textProcessing(sentence);
}
else if(operation==1){
char rletter;
cin>>rletter;
if(isupper(rletter)){
cout<<"Invalid";
}
else {
int ans = textProcessing(sentence, rletter);
cout << ans;
}
}
else if(operation==2){
char orignal;
char newl;
cin>>orignal>>newl;
textProcessing(sentence,orignal,newl);
}
else{
cout<<"Invalid";
}
// Your code ends here
}
}
return 0;
}
void textProcessing(string &inputString){
inputString.erase(remove(inputString.begin(),inputString.end(),'a'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'o'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'u'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'w'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'y'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'i'),inputString.end());
inputString.erase(remove(inputString.begin(),inputString.end(),'e'),inputString.end());
cout<<inputString;
};
int textProcessing(const string &inputString, char letter){
int count=0;
auto it=find(inputString.rbegin(),inputString.rend(),letter);
int last_index =distance(inputString.begin(), (it + 1).base());
int first=inputString.find(letter);
int distance=(last_index-first);
return distance;
};
void textProcessing(string &inputString, char orgChar, char newChar){
if((isupper(orgChar))/*||(isupper(newChar))*/){
cout<<"Invalid";
}
else {
for (int i = 0; i <= inputString.length(); i++) {
if (inputString[i] == orgChar) {
inputString[i] = newChar;
}
}
cout<<inputString;
}
}
and here is the error from assignment website:
Your program displayed : student.cpp: In function ‘int textProcessing(const string&, char)’: student.cpp:79:10: error: ‘it’ does not name a type
System Message: ERROR/3 (<string>, line 3)
Unexpected indentation.
auto it=find(inputString.rbegin(),inputString.rend(),letter);
^
System Message: WARNING/2 (<string>, line 5)
Block quote ends without a blank line; unexpected unindent.
student.cpp:80:52: error: ‘it’ was not declared in this scope
int last_index =distance(inputString.begin(), (it + 1).base());
^
The problem ‘it’ does not name a type is most surely caused by the use of auto in a Pre-C++11 standard compiler.
Make sure you're using C++11 or higher as auto is a C++11 feature.
There may be other problems with your code but the question is about the compiler error ‘it’ does not name a type.
There are many other online websites to compile and run your program one of which is this.
I am having what seems to be a common issue however reading through the replies to the similar questions I can't find the solution to my issue at all as I have already done what they are suggesting such as making the variable an array. I have the following code:
#include "stdafx.h"
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <future>
using namespace std;
string eng2Str[4] = { "money", "politics", "RT", "#"};
int resArr[4];
int main()
{
engine2(eng2Str[4], resArr[4]);
system("Pause");
system("cls");
return 0;
}
void engine2(string &eng2Str, int &resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++) {
while (getline(fin, line)) {
if (line.find(eng2Str[i]) != string::npos) {
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
Before you mark as duplicate I have made sure of the following:
The array and variable I am trying to assign are both int
Its an array
The error is:
expression must have pointer-to-object type
The error is occurring at the "resArr[i] = fcount;" line and am not sure why as resArr is an int array and I am trying to assign it a value from another int variable. I am quite new to C++ so any help would be great as I am really stuck!
Thanks!
The problem is that you've declared your function to take a reference to a single string and int, not arrays. It should be:
void engine2(string *eng2Str, int *resArr)
or:
void engine2(string eng2Str[], int resArr[])
Then when you call it, you can give the array names as arguments:
engine2(eng2Str, resArr);
Another problem is the while loop in the function. This will read the entire file during the first iteration of the for() loop. Other iterations will not have anything to read, since it will be at the end of the file already. You could seek back to the beginning of the file, but a better way would be to rearrange the two loops so you just need to read the file once.
while (getline(fin, line)) {
for (int i = 0; i < 4; i++) {
if (line.find(eng2Str[i]) != string::npos) {
resArr[i]++;
}
}
}
I would suggest to use std::vector instead of pure C array.
In your code, there are more issues.
You are passing the fourth element of both arrays to the engine2 function.
From your definition of void engine2(string &eng2Str, int &resArr) you expect reference to a string (not array / vector) and an address / reference of int - you need to pass an pointer to the first element of resArr.
#include <cstring>
#include <fstream>
#include <iostream>
#include <string>
#include <algorithm>
#include <vector>
#include <future>
using namespace std;
vector<string> eng2Str = { "money", "politics", "RT", "#" };
int resArr[4] = {};
void engine2(const vector<string>& eng2Str, int* resArr)
{
ifstream fin;
fin.open("sampleTweets.csv");
int fcount = 0;
string line;
for (int i = 0; i < 4; i++)
{
while (getline(fin, line))
{
if (line.find(eng2Str[i]) != string::npos)
{
++fcount;
}
}
resArr[i] = fcount;
}
fin.close();
return;
}
int main()
{
engine2(eng2Str, resArr);
system("Pause");
system("cls");
return 0;
}
I try to read a large cvs file into Eigen Matrix, below the code found having problem where it can not detect each line of \n in cvs file to create multiple rows in the matrix. (It read entire file with single row). Not sure what's wrong with the code. Can anyone suggest here?
Im also looking for a effective way to read csv file with 10k of rows and 1k of cols. Not so sure the code below will be the best effective way? Very appreciated with your comment.
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>
#include <istream> //DataFile.fail() function
#include <vector>
#include <set>
#include <string>
using namespace std;
#include <Eigen/Core>
#include <Eigen/Dense>
using namespace Eigen;
void readCSV(istream &input, vector< vector<string> > &output)
{
int a = 0;
int b = 0;
string csvLine;
// read every line from the stream
while( std::getline(input, csvLine) )
{
istringstream csvStream(csvLine);
vector<string> csvColumn;
MatrixXd mv;
string csvElement;
// read every element from the line that is seperated by commas
// and put it into the vector or strings
while( getline(csvStream, csvElement, ' ') )
{
csvColumn.push_back(csvElement);
//mv.push_back(csvElement);
b++;
}
output.push_back(csvColumn);
a++;
}
cout << "a : " << a << " b : " << b << endl; //a doen't detect '\n'
}
int main(int argc, char* argv[])
{
cout<< "ELM" << endl;
//Testing to load dataset from file.
fstream file("Sample3.csv", ios::in);
if(!file.is_open())
{
cout << "File not found!\n";
return 1;
}
MatrixXd m(3,1000);
// typedef to save typing for the following object
typedef vector< vector<string> > csvVector;
csvVector csvData;
readCSV(file, csvData);
// print out read data to prove reading worked
for(csvVector::iterator i = csvData.begin(); i != csvData.end(); ++i)
{
for(vector<string>::iterator j = i->begin(); j != i->end(); ++j)
{
m(i,j) = *j;
cout << *j << ", ";
}
cout << "\n";
}
}
I will also attach a sample cvs file. https://onedrive.live.com/redir?resid=F1507EBE7BF1C5B!117&authkey=!AMzCnpBqxUyF1BA&ithint=file%2ccsv
Here's something you can actually copy-paste
Writing your own "parser"
Pros: lightweight and customizable
Cons: customizable
#include <Eigen/Dense>
#include <vector>
#include <fstream>
using namespace Eigen;
template<typename M>
M load_csv (const std::string & path) {
std::ifstream indata;
indata.open(path);
std::string line;
std::vector<double> values;
uint rows = 0;
while (std::getline(indata, line)) {
std::stringstream lineStream(line);
std::string cell;
while (std::getline(lineStream, cell, ',')) {
values.push_back(std::stod(cell));
}
++rows;
}
return Map<const Matrix<typename M::Scalar, M::RowsAtCompileTime, M::ColsAtCompileTime, RowMajor>>(values.data(), rows, values.size()/rows);
}
Usage:
MatrixXd A = load_csv<MatrixXd>("C:/Users/.../A.csv");
Matrix3d B = load_csv<Matrix3d>("C:/Users/.../B.csv");
VectorXd v = load_csv<VectorXd>("C:/Users/.../v.csv");
Using the armadillo library's parser
Pros: supports other formats as well, not just csv
Cons: extra dependency
#include <armadillo>
template <typename M>
M load_csv_arma (const std::string & path) {
arma::mat X;
X.load(path, arma::csv_ascii);
return Eigen::Map<const M>(X.memptr(), X.n_rows, X.n_cols);
}
Read the CSV file into your vector < vector > as you please (e.g. Lucas's answer). Instead of the vector< vector<string> > construct, use a vector< vector<double> > or even better a simple vector< double >. To assign the vector of vectors to an Eigen matrix efficiently using vector< vector< double > >, use the following:
Eigen::MatrixXcd mat(rows, cols);
for(int i = 0; i < rows; i++)
mat.row(i) = Eigen::Map<Eigen::VectorXd> (csvData[i].data(), cols).cast<complex<double> >();
If you opted to use the vector< double > option, it becomes:
Eigen::MatrixXcd mat(rows, cols);
mat = Eigen::Map<Eigen::VectorXd> (csvData.data(), rows, cols).cast<complex<double> >().transpose();
This will read from a csv file correctly:
std::ifstream indata;
indata.open(filename);
std::string line;
while (getline(indata, line))
{
std::stringstream lineStream(line);
std::string cell;
while (std::getline(lineStream, cell, ','))
{
//Process cell
}
}
Edit: Also, since your csv is full of numbers, make sure to use std::stod or the equivalent conversion once you expect to treat them as such.
This question already has answers here:
What is an undefined reference/unresolved external symbol error and how do I fix it?
(39 answers)
Closed 7 years ago.
I'm pretty new to C++, and working through a book called "Accelerated C++." In one of the chapters you are suppose to make a program that, given a string of text, tells you what line(s) each word appears on. To break up all of the words in the string, i used a function called 'split' from a different source file, but included its header file so I could use it. It didn't work though. For the life of me I can't figure out why the linker tells me "undefined reference to 'split(std::string const&)'
split.cpp:
#include <string>
#include <cctype>
#include <vector>
#include "split.h"
using namespace std;
bool space(char c) {
return isspace(c);
}
bool not_space(char c) {
return !isspace(c);
}
vector<string> split(const string& s) {
vector<string> ret;
string::const_iterator i = s.begin();
while (i != s.end()) {
i = find_if(it, s.end(), not_space);
string::const_iterator j = i;
j = find_if(j, s.end(), space);
if (i != s.end())
ret.push_back(string(i, j));
i = j;
}
return ret;
}
split.h:
#ifndef GUARD_split_h
#define GUARD_split_h
#include <string>
#include <vector>
bool space(char);
bool not_space(char);
std::vector<std::string> split(const std::string&);
#endif
Word_Counter.cpp:
#include <iostream>
#include <vector>
#include <string>
#include <map>
#include "split.h"
using namespace std;
map<string, vector<int> > xref(istream& in, vector<string>
find_words(const string&) = split) {
string line;
int line_number = 0;
map<string, vector<int> > ret;
while (getline(in, line)) {
++line_number;
vector<string> words = find_words(line);
for (vector<string>::const_iterator it = words.begin();
it != words.end(); it++)
ret[*it].push_back(line_number);
}
return ret;
}
int main() {
map<string, vector<int> > ret = xref(cin);
for(map<string, vector<int> >::const_iterator it = ret.begin();
it != ret.end(); it++) {
cout << it->first << "occurs on line(s): ";
vector<int>::const_iterator line_it = it->second.begin();
cout << *line_it;
line_it++;
while(line_it != it->second.end()) {
cout << ", " << *line_it;
line_it++;
}
cout << endl;
}
return 0;
}
I've been having a tough time with headers in general lately. Any help is greatly appreciated!
If you have sources split in several files, you need to make the compiler aware of all them. The simplest way is to list all .cpp files (not .h files!) on the command line:
g++ Word_Counter.cpp split.cpp -o Word_Counter
The following code gives me 2 errors when i compile
#include <iostream>
#include <fstream>
#include <cstring>
#include "Translator.h"
using namespace std;
void Dictionary::translate(char out_s[], const char s[])
{
int i;
char englishWord[MAX_NUM_WORDS][MAX_WORD_LEN];
for (i=0;i < numEntries; i++)
{
if (strcmp(englishWord[i], s)==0)
break;
}
if (i<numEntries)
strcpy(out_s,elvishWord[i]);
}
char Translator::toElvish(const char elvish_line[],const char english_line[])
{
int j=0;
char temp_eng_words[2000][50];
//char temp_elv_words[2000][50]; NOT SURE IF I NEED THIS
std::string str = english_line;
std:: istringstream stm(str);
string word;
while( stm >> word) // read white-space delimited tokens one by one
{
int k=0;
strcpy (temp_eng_words[k],word.c_str());
k++;
}
for (int i=0; i<2000;i++) // ERROR: out_s was not declared in this scope
{
Dictionary::translate (out_s,temp_eng_words[i]); // ERROR RELATES TO THIS LINE
}
}
Translator::Translator(const char dictFileName[]) : dict(dictFileName)
{
char englishWord[2000][50];
char temp_eng_word[50];
char temp_elv_word[50];
char elvishWord[2000][50];
int num_entries;
fstream str;
str.open(dictFileName, ios::in);
int i;
while (!str.fail())
{
for (i=0; i< 2000; i++)
{
str>> temp_eng_word;
str>> temp_elv_word;
strcpy(englishWord[i],temp_eng_word);
strcpy(elvishWord[i],temp_elv_word);
}
num_entries = i;
}
str.close();
}
}
The first one is at std::string istringstream stm(str); where it says it the variable has an initializer but incomplete type. If I put in std::string istringstream stm(str); it says expected initializer before stm andstm was not declared in the scope.
It also says out_s was not declared in this scope at Dictionary::translate (out_s,temp_eng_words[i]);. I don't see why one parameter is recognisied and one is not?
Thanks in advance.
You have to include header file:
#include <sstream>
#include <string>
when you want to use stringstream and string.
Meanwhile:
Dictionary::translate (out_s,temp_eng_words[i]);
If out_s is not a member of the class, you seems forgot to define out_s before using it inside toElvish.
Meanwhile:
while( stm >> word) // read white-space delimited tokens one by one
{
int k=0; //^^Why do you initialize k everytime you read a word?
strcpy (temp_eng_words[k],word.c_str());
k++;
}
You just need to include sstream
Your translator would be much simpler if you used std::map.
#include <map>
#include <string>
// map[english word] returns the elvish word.
typedef std::map<std::string, std::string> Dictionary;
// Define the dictionary
Dictionary english_to_elvish_dictionary;
std::string To_Elvish(const std::string& english_word)
{
Dictionary::iterator iter;
std::string elvish_word;
iter = english_to_elvish_dictionary.find(english_word);
if (iter != english_to_elvish_dictionary.end())
{
// English word is in dictionary, return the elvish equivalent.
elvish_word = *iter;
}
return elvish_word;
}
The above code fragment replaces most of your code and reduces your issues with arrays of arrays of C-strings. Less code == less problems.
To see a list of issues your having, search StackOverflow for "[c++] elvish english".