I am stuck with the error "string subscript out of range".
After testing, I am pretty sure that it's because of this function, which is used for reading values in a file, but have no idea what's wrong:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
string read(string value) {
ifstream input;
string line="", output="";
size_t pos;
bool a = true;
int i = 0;
input.open("pg_options.txt");
if (!input.is_open()) {
cout << "pg_options.txt missing.";
return "error";
}
while (getline(input, line)) { //get file lines
pos = line.find(value);
if (pos == string::npos) { //if value in line
while (a == true) {
if (line[i] == '=') { //after "="
i++;
break;
}
else {
i++;
}
}
for (i; line[i] != ' '; i++) {
output += line[i]; //put value to output
}
}
}
input.close();
return output;
}
pg_options.txt:
include_special_characters=true
include_upper_case=true
include_lower_case=true
include_numbers=true
digits=10
cout << read("digits") returns the error mentioned above.
Thank you for your comments. I solved this by editing the for loop:
string read(string value) {
ifstream input;
int olength;
string line = "", output = "";
size_t pos;
bool a = true;
int i = 0;
input.open("pg_options.txt");
if (!input.is_open()) {
cout << "pg_options.txt missing.";
return "error";
}
while (getline(input, line)) {
pos = line.find(value);
if (pos != string::npos) {
while (a == true) {
if (line[i] == '=') {
i++;
break;
}
else {
i++;
}
}
olength = line.length() - value.length() - 1;
for (int i2 = 0; i2 < olength; i2++) {
output += line[i];
i++;
}
}
}
input.close();
return output;
}
Related
I'm creating a custom language parser in C++, I'm struggling with a runtime error, where I have a std::vector<std::string> member of a class with a constructor.
The full error is:
The procedure entry point
_ZSt28__throw_bad_array_new_lengthv could no be located
in the dynamic link library
"path_to_executable"
This error is throw whenever I try to use std::vector::push_back in my code, but shouldn't std::vector be a dynamically sized data container? Why is this error occurring?
Some of my codes:
//"lib/cursor.h"
#ifndef T_CURSOR
#define T_CURSOR
#include <iostream>
struct Cursor
{
private:
std::string input;
int inputLength;
char getChar(int p);
public:
char character;
int pos;
int line;
int column;
bool eof;
bool lineBreak;
Cursor(std::string i);
void walk(bool back = false);
void walkTimes(int times, bool back = false);
void move(int toPos);
void skipIgnore();
std::string toString();
};
#endif
//"lib/cursor.cpp"
#include <sstream>
#include "cursor.h"
Cursor::Cursor(std::string i)
{
this->input = i;
this->inputLength = i.length();
this->character = i.at(0);
this->pos = 0;
this->line = 0;
this->column = 0;
this->eof = false;
this->lineBreak = false;
}
char Cursor::getChar(int pos)
{
if (pos < 0 || pos >= this->inputLength)
{
return EOF;
}
return this->input.at(pos);
}
void Cursor::walk(bool back)
{
if (back)
{
this->pos--;
this->column--;
if (this->lineBreak)
{
this->line--;
this->column = 0;
for (int i = this->pos - 1; i >= 0; i--)
{
if (this->getChar(i) == '\n')
break;
this->column++;
}
}
}
else
{
this->pos++;
this->column++;
if (this->lineBreak)
{
this->line++;
this->column = 0;
}
}
this->character = this->getChar(this->pos);
this->eof = this->character == EOF;
this->lineBreak = this->character == '\n';
}
void Cursor::walkTimes(int times, bool back)
{
for (int i = 0; i < times; i++)
{
this->walk(back);
}
}
void Cursor::move(int pos)
{
if (pos < 0)
pos = 0;
if (pos > this->inputLength - 1)
pos = this->inputLength - 1;
this->pos = 0;
this->character = this->input.at(0);
this->line = 0;
this->column = 0;
this->eof = false;
this->lineBreak = this->character == '\n';
while (this->pos < pos)
this->walk();
}
void Cursor::skipIgnore()
{
while (this->character == ' ' ||
this->character == '\n' ||
this->character == '\t')
this->walk();
if (this->character == '#')
{
while (!this->eof && this->character != '\n')
this->walk();
}
while (this->character == ' ' ||
this->character == '\n' ||
this->character == '\t')
this->walk();
}
std::string Cursor::toString()
{
std::stringstream ss("");
ss << "(P:" << this->pos;
ss << " L:" << this->line;
ss << " C:" << this->column;
ss << " \"" << this->character << "\")";
return ss.str();
}
//"lib/lexer.h"
#ifndef T_LEXER
#define T_LEXER
#include <iostream>
#include <vector>
#include "cursor.h"
class Lexer
{
private:
std::string input;
protected:
Cursor cursor;
std::vector<std::string> matchStack;
std::vector<std::vector<Cursor>> cursorStack;
public:
Lexer(std::string input);
std::string getStr(int pos);
void setStr(int pos, std::string str);
Cursor getCursorStart(int pos);
Cursor getCursorEnd(int pos);
bool match(std::string str);
};
#endif
//"lib/lexer.cpp"
#include "lexer.h"
Lexer::Lexer(std::string input) : cursor(input)
{
this->input = input;
}
std::string Lexer::getStr(int pos)
{
if (this->matchStack.size() == 0)
return this->input;
while (pos < 0)
pos += this->matchStack.size();
while (pos >= this->matchStack.size())
pos -= this->matchStack.size();
return this->matchStack[pos];
}
void Lexer::setStr(int pos, std::string str)
{
if (this->matchStack.size() == 0)
return;
while (pos < 0)
pos += this->matchStack.size();
while (pos >= this->matchStack.size())
pos -= this->matchStack.size();
this->matchStack[pos] = str;
}
Cursor Lexer::getCursorStart(int pos)
{
if (this->cursorStack.size() == 0)
return Cursor(this->input);
while (pos < 0)
pos += this->cursorStack.size();
while (pos >= this->cursorStack.size())
pos -= this->cursorStack.size();
return this->cursorStack[pos][0];
}
Cursor Lexer::getCursorEnd(int pos)
{
if (this->cursorStack.size() == 0)
return Cursor(this->input);
while (pos < 0)
pos += this->cursorStack.size();
while (pos >= this->cursorStack.size())
pos -= this->cursorStack.size();
return this->cursorStack[pos][1];
}
bool Lexer::match(std::string str)
{
this->cursor.skipIgnore();
const std::string ss = this->input.substr(this->cursor.pos, str.length());
if (ss == str)
{
this->matchStack.push_back(ss); // Getting error if I include this line
const Cursor startCursor = this->cursor;
this->cursor.walkTimes(str.length());
const Cursor endCursor = this->cursor;
this->cursorStack.push_back({startCursor, endCursor});
return true;
}
return false;
}
//"test.cpp"
#include "lib/cursor.h"
#include "lib/lexer.h"
#include <iostream>
using namespace std;
int main()
{
string input = "Something to test";
Lexer lexer = Lexer(input);
cout << "Start" << endl;
cout << lexer.match("Something") << endl;
return 0;
}
I'm compiling my program with g++ on Windows: g++ test.cpp lib/cursor.cpp lib/lexer.cpp -o test.exe
I got the same error when compiling in command line using g++. But it works well in code blocks. To solve this problem try compiling with -static-libstdc++. It should solve the problem.
I am trying previous year's codejam question of round 1A
link to question
i have submitted this code(start reading from main method, for ease)-
#include <bits/stdc++.h>
using namespace std;
#define range(t) for (int i = 0; i < t; i++)
#define rangeG(i, t) for (i = 0; i < t; i++)
#define printVec(vec) \
for (auto c : vec) \
{ \
cout << c << endl; \
}
vector<string> separate(string s)
{
vector<string> result;
range(s.size())
{
if (s[i] == '*')
{
string temp = s.substr(0, i + 1);
if (temp.size() > 1)
{
result.push_back(temp);
}
s = s.substr(i, s.size());
i = 0;
}
else if (i == (s.size() - 1))
{
string temp = s.substr(0, i + 1);
result.push_back(temp);
s = s.substr(i, s.size());
}
}
return result;
}
void removeAsterisk(string &s)
{
s.erase(remove(s.begin(), s.end(), '*'), s.end());
}
bool setStart(string s, string &start)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), start.size()))
{
if (s[i] != start[i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= start.size())
{
start = s;
}
}
return possible;
}
bool setEnd(string s, string &end)
{
bool possible = 1;
removeAsterisk(s);
range(min(s.size(), end.size()))
{
if (s[s.size() - 1 - i] != end[end.size() - 1 - i])
{
possible = 0;
}
}
if (possible)
{
if (s.size() >= end.size())
{
end = s;
}
}
return possible;
}
void solve()
{
int n;
cin >> n;
vector<string> allS;
bool possible = 1;
string start = "";
string end = "";
string middle = "";
string result = "";
while (n--)
{
string str;
cin >> str;
if (count(str.begin(), str.end(), '*') == 0)
{
result = str;
}
vector<string> temp = separate(str);
for (string s : temp)
{
if (s[0] != '*')
{
possible = setStart(s, start);
}
if (s[s.size() - 1] != '*')
{
possible = setEnd(s, end);
}
if (possible && count(s.begin(), s.end(), '*') == 0)
{
result = s;
break;
}
if (s[0] == '*' && s[s.size() - 1] == '*')
{
removeAsterisk(s);
middle += s;
}
}
}
if (possible)
{
if (result.size() == 0)
{
result = start + middle + end;
}
cout << result << "\n";
}
else
{
cout << "*\n";
}
}
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int t = 0;
cin >> t;
range(t)
{
cout << "Case #" << i + 1 << ": ";
solve();
}
return 0;
}
it seems correct to me and i have tested many times for many examples, but it is losing in test set-1(exactly one * (asterisk) character and and always the first character of string). Can anyone tell what's wrong?
you can consider code of first ranked here (it has all solutions,check only for "pattern matching" task) for help. I know that the wrong answer is an edge case and if it passes test set 1 then it will pass others.
I was trying to create a special assembler that will run with a specific machine type. I was trying to compile the program, but got a linker error:
/usr/bin/ld: lexer.o: in function `Lexer::lex(std::__cxx11::basic_string, std::allocator >)':
lexer.cpp:(.text+0x2ee): undefined reference to `Lexer::isSpecial(char)'
collect2: error: ld returned 1 exit status
Screenshot here
I have 3 main files: lexer.h, lexer.cpp, sasm.cpp. Here's the code.
lexer.h:
#ifndef LEXER_H
#define LEXER_H
#include <iostream>
#include <vector>
// type definitions
typedef uint8_t byte;
typedef std::vector<std::string> strings;
enum State : byte {
START,
READCHAR,
READBLOCK,
SKIP,
DUMP,
COMMENT,
END
};
// Instructions definitions
#define ADD 0x40000001
#define SUB 0x40000002
#define TIME 0x40000003
#define DIVIDE 0x40000004
#define HALT 0x40000000
class Lexer {
private:
bool isSpace(char c);
bool isSpecial(char c);
bool isGroup(char c);
char end_char, beg_char;
public:
strings lex(std::string s);
};
#endif
lexer.cpp:
#include "lexer.h"
strings Lexer::lex(std::string s) {
strings strLst;
char lexEme[256];
int i = 0;
int j = 0;
State state = START;
int done = 0;
int len = s.length();
int balance = 0;
while (i < len) {
switch (state) {
case START:
if (isSpace(s[i])) {
state = SKIP;
} else if (isGroup(s[i])) {
if (s[i] == '"') {
lexEme[j] = s[i];
j++;
i++;
}
state = READBLOCK;
} else if (s[i] == '/' && s[i + 1] == '/') {
i += 2;
state = COMMENT;
} else {
state = READCHAR;
}
break;
case READCHAR:
if (isSpace(s[i])) {
state = DUMP;
} else if (s[i] == '\\') {
i += 2;
} else if (isGroup(s[i])) {
if (s[i] == '"') {
lexEme[j] = s[i];
j++;
i++;
}
state = READBLOCK;
} else if (isSpecial(s[i])) {
if (j == 0) {
lexEme[j] = s[i];
j++;
i++;
}
state = DUMP;
} else if (s[i] == '/' && s[i + 1] == '/') {
i += 2;
state = COMMENT;
} else {
lexEme[j] = s[i];
j++;
i++;
}
break;
case READBLOCK:
if (s[i] == beg_char && s[i] != '"') {
balance++;
lexEme[j] = s[i];
j++;
i++;
} else if (s[i] == end_char) {
balance--;
lexEme[j] = s[i];
j++;
i++;
if (balance <= 0) {
state = DUMP;
}
} else if (end_char == '"' && s[i] == '\\') {
// TODO: fix this to actually record the chars
i += 2;
} else {
lexEme[j] = s[i];
j++;
i++;
}
break;
case SKIP:
if (isSpace(s[i])) {
i++;
} else {
state = READCHAR;
}
break;
case DUMP:
if (j < 0) {
lexEme[j] = 0;
strLst.push_back(lexEme);
j = 0;
}
state = START;
break;
case COMMENT:
if (s[i] != '\n') {
i++;
} else {
state = READCHAR;
}
break;
case END:
i = len;
break;
}
}
if (j > 0) {
lexEme[j] = 0;
strLst.push_back(lexEme);
}
return strLst;
}
// This function allows us what a space is
bool Lexer::isSpace(char c) {
switch (c) {
case '\n':
case '\r':
case '\t':
case '\v':
case ' ':
case '\f':
return true;
default:
return false;
}
}
bool Lexer::isGroup(char c) {
beg_char = c;
switch (c) {
case '"':
end_char = '"';
return true;
case '(' :
end_char = ')';
return true;
case ')':
return true;
default:
return false;
}
}
bool isSpecial(char c) {
switch (c) {
case '[':
case ']':
return true;
default:
return false;
}
}
sasm.cpp:
#include <fstream>
#include "lexer.h"
typedef uint32_t i32;
using namespace std;
vector<i32> compile(strings s);
bool isInteger(string s);
bool isPrimitive(string s);
i32 mapToNumber(string s);
int main (int argc, char* argv[]) {
// Check for input errors
if (argc != 2) {
cerr << "Usage: " << argv[0] << " <sasm-file>" << endl;
exit(1);
}
// Read input file
ifstream infile;
infile.open(argv[1]);
if (!infile.is_open()) {
cerr << argv[1] << ": file can't be found" << endl;
exit(1);
}
string line;
string contents;
while (getline(infile, line)) {
contents += line + "\n";
}
infile.close();
// Parse infile
Lexer lexer;
strings lexEmes = lexer.lex(contents);
// Compile binary
vector<i32> instructions = compile(lexEmes);
// Write instructions to file
ofstream ofile;
ofile.open("out.bin", ios::binary);
for (i32 i = 0; i < instructions.size(); i++) {
ofile.write(reinterpret_cast<char*>(&instructions[i]), sizeof(i32));
}
ofile.close();
return 0;
}
vector<i32> compile(strings s) {
vector<i32> instructions;
for (i32 i = 0; i < s.size(); i++) {
if (isInteger(s[i])) {
instructions.push_back(stoi(s[i]));
} else {
i32 instruction = mapToNumber(s[i]);
if (instruction != -1) {
instructions.push_back(instruction);
} else {
cerr << "\033[1;31m" << s[i] << "\033[0m Invalid instruction" << std::endl;
}
}
}
return instructions;
}
bool isInteger(string s) {
for (i32 i = 0; i < s.length(); i++) {
if (!isdigit(s[i])) {
return false;
}
}
return true;
}
i32 mapToNumber(string s) {
if (s == "+") {
return ADD;
} else if (s == "-") {
return SUB;
} else if (s == "*") {
return TIME;
} else if (s == "/") {
return DIVIDE;
}
return -1; // Invalid instruction
}
Thanks for your answers.
You are missing the class reference in the function definition.
bool Lexer::isSpecial(char c)
^^^^^^^
So now looking at line 2, Cow- DNA Sequence; this continues on line 13 and 24 and ... I want to get this long sequence for each sequences ignoring the white space and new line in between.
This is the format of the file: 1
This is the code, which reads the first 10 sequences only
ifstream file ("txt");
string line;
vector <string> vec;
stringstream s;
string name;
string strip(string & s)
{
size_t b = s.find_first_not_of(' ');
size_t e = s.find_last_not_of(' ');
if (b == string::npos) {
return "";
} else {
return s.substr(b, e - b + 1);
}
}
void getSequence(){
int i;
int row;
int col;
if (file.is_open())
{
file >> row >> col;
for (i = 0; i < row; i++) {
vec.push_back("");
}
i = 0;
while (getline(file, line))
{
file >> name;
if (line == " ")
{
continue;
}
vec[i % row] += strip(line);
i++;
}
}
else {
cerr << "Error: file did not open!" << endl;
}
for (const string & v : vec) {
cout << v << endl;
}
}
Thank you in advance for your help.
Perhaps this will help a bit. The idea is to read the row & col then read the header line for the number of rows. After that repeatedly read the next chunk of lines and append each to the correct item assuming the lines are interleaved.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
struct Sequence
{
std::string name;
std::string data;
};
using SeqVec = std::vector<Sequence>;
bool readHeader(std::ifstream& f, SeqVec& v)
{
for (size_t i = 0; i < v.size(); ++i)
{
if (!(f >> v[i].name >> v[i].data))
{
return false;
}
}
return true;
}
int readChunk(std::ifstream& f, SeqVec& v)
{
int linesRead = 0;
std::string chunk;
for (size_t i = 0; i < v.size(); ++i)
{
if(!(f >> chunk))
{
break;
}
v[i].data += chunk;
++linesRead;
}
return linesRead;
}
int main()
{
std::vector<Sequence> v;
const std::string filename = "test.txt";
std::ifstream f(filename);
if (!f)
{
return -1;
}
int row;
int col;
if (f >> row >> col)
{
v.resize(row);
if (!readHeader(f, v))
{
return -1;
}
for (;;)
{
int linesRead = readChunk(f, v);
if (linesRead == 0 && v[0].data.size() == col)
{
//If we read nothing and the lines are the correct length we're done.
break;
}
else if (linesRead < v.size())
{
//partial read is an error.
return -1;
}
}
}
for (auto& seq : v)
{
std::cout << seq.name << " : " << seq.data << "\n";
}
return 0;
}
I'm trying to show how many times a word appears in a file. I'm not allowed to use third party libraries (c++ stl, boost etc.) Thats why im having a trouble. This is what i got so far;
I created an array list to store the words in the file. I got rid of the punctuations and numbers. Now i need to print all the words with their frequency and sort with respect to frequency like this;
Words: Frequency:
their 13
how 10
apple 9
is 5
arrayList.h
#include <iostream>
#include <string>
using namespace std;
class arrayList
{
public:
bool isEmpty() const;
bool isFull() const;
int listSize() const;
void print() const;
void insertAt(int location, const string& insertItem);
void removeAt(int location);
string retrieveAt(int location) const;
bool seqSearch(const string& item) const;
void insert(const string& insertItem);
void remove(const string& removeItem);
arrayList(int);
~arrayList();
private:
string *list;
int length;
int maxSize;
};
arrayList.cpp
#include "arrayList.h"
bool arrayList::isEmpty() const
{
return (length == 0);
}
bool arrayList::isFull() const
{
return (length == maxSize);
}
int arrayList::listSize() const
{
return length;
}
void arrayList::print() const
{
for (int i = 0; i < length; i++)
cout << list[i];
}
void arrayList::insertAt(int location, const string& insertItem)
{
list[location] = insertItem;
length++;
}
void arrayList::removeAt(int location)
{
for (int i = location; i < length - 1; i++)
list[i] = list[i+1];
length--;
}
string arrayList::retrieveAt(int location) const
{
return list[location];
}
bool arrayList::seqSearch(const string& item) const
{
int loc;
bool found = false;
for (loc = 0; loc < length; loc++)
if (list[loc] == item)
{
found = true;
break;
}
if (found)
return 1;
else
return 0;
}
void arrayList::insert(const string& insertItem)
{
list[length++] = insertItem;
}
void arrayList::remove(const string& removeItem)
{
int loc;
loc = seqSearch(removeItem);
removeAt(loc);
}
arrayList::arrayList(int size)
{
maxSize = size;
length = 0;
list = new string[maxSize];
}
arrayList::~arrayList(void)
{
delete [] list;
}
Source.cpp
#include <iostream>
#include <fstream>
#include <string>
#include "arrayList.h"
#include <cctype>
using namespace std;
int wordCount(ifstream &file)
{
string word;;
int count=0;
while (file >> word)
{
count++;
}
file.clear();
file.seekg(0, ios::beg);
return count;
}
string removePunct(string word)
{
for (unsigned int i = 0; i < word.length(); i++)
{
if( word[i] == '.')
word[i] = ' ';
else if(word[i] == ',')
word[i] = ' ';
else if(word[i] == ';')
word[i] = ' ';
else if(word[i] == ':')
word[i] = ' ';
else if(word[i] == '?')
word[i] = ' ';
else if(word[i] == '-')
word[i] = ' ';
else if(word[i] == '[')
word[i] = ' ';
else if(word[i] == ']')
word[i] = ' ';
else if(word[i] == '(')
word[i] = ' ';
else if(word[i] == ')')
word[i] = ' ';
else if(word[i] == '!')
word[i] = ' ';
else if(word[i] == '\"')
word[i] = ' ';
else if(word[i] == '\'')
word[i] = ' ';
else if(word[i] == '_')
word[i] = ' ';
}
return word;
}
string makelower (string word)
{
for (unsigned int i = 0; i < word.length(); i++)
{
if ( isupper(word[i]) )
word[i] = tolower(word[i]);
}
return word;
}
int main ()
{
string fileName;
ifstream file;
cout << "Please enter the file name: ";
getline(cin,fileName);
file.open(fileName);
int listSize = wordCount(file);
arrayList list1(listSize*2);
string word, newWord;
int i = 0;
while (file >> word)
{
if (word[i] >= '1' && word[i]<= '9')
{
list1.insert(" ");
i++;
}
else
{
newWord = makelower(word);
list1.insert(removePunct(newWord));
list1.insert(" ");
}
}
/*int *counter = new int [listSize*2]; //I tried this but don't think its working
string item;
for (int i = 0; i < list1.listSize(); i++)
{
if( list1.retrieveAt(i) != " " )
{
string item = list1.retrieveAt(i);
while ( list1.seqSearch(item) )
counter[i]++;
}
}*/
system("pause");
return 0;
}
Any help is appreciated.
You have strange things going on in your code. But i think it doesn't effect your real problem.
The solution would be something like this:
class freqList
{
freqList(int size)
{
words = new string[size];
freqList = new int[size];
memset(freqList, 0, sizeof(int)*size); //set freqs to 0
length = 0;
}
int seqSearch(const string& item) const
{
...
return index_of_item; //-1 if you can't find it
}
void insertWord(string word)
{
int idx = searchSeq(word);
if(idx >= 0)
{//it already exists in the words list
freqs[idx]++;
}
else
{// new word, add to the end of the list
words[length] = word;
freqs[length]++;
length++;
}
}
...
string *words;
int *freqs; //same size of words
...
};
int wordCount(ifstream &file)
{
string word;;
int count=0;
while (file >> word)
{
word = removePunct(word);
word = wordToLower(word);
if(isWord(word))
count++;
}
file.clear();
file.seekg(0, ios::beg);
return count;
}
bool isWord(word)
{
//write a function which fills your constraints
}
Now, the main function should be like this:
int listSize = wordCount(file);
freqList freqs(listSize);
string word;
int i = 0;
while (file >> word)
{
word = removePunct(word);
word = wordToLower(word);
... // maybe you have other constraints
if (isWord(word))
{
freqs.insert(word);
}
}
After the while loop, you have freq list with words and freqs corresponding to each word.