I am writing a very simple interpreter with these two commands: "print:value", to print and "printnl:value", to print in a new line and i use vectors to store the command and the value. the problem is that when i input something it returns ma an error "vector subscript out of range" and some random exit code. Here is the code:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> brk_token(string text, char breakon) {
vector<string> tokens;
string token = "";
for (int i = 0;i < text.size(); i++) {
if (text.at(i) != breakon) {
token += text.at(i);
}
else {
tokens.push_back(token);
token = "";
}
}
return tokens;
}
int main() {
string program;
while (true) {
getline(cin, program);
if (brk_token(program.c_str(), ':')[0] == "print") {
cout << brk_token(program.c_str(), ':')[1];
}
else if (brk_token(program.c_str(), ':')[0] == "printnl") {
cout << brk_token(program.c_str(), ':')[1] << "\n";
}
if (program == "break") {
break;
}
}
return 0;
}
I wrote: "print:hello" and "printnl:hello" and every time it returned that error, i wrote some random characters and the result is the same, can someone help?
Inside of brk_token()
, when the loop reaches the end of the string, you are not pushing the final token
into the vector
. As such, inside of main()
, you have undefined behavior when you try to access the vector[1]
element that doesn't exist.
Also, some other issues with your code:
the string::at()
method performs bounds checking at runtime, but you are doing your own bounds checking in the for
loop that iterates through a string
, so using at()
is useless overhead. You can safely use string::operator[]
instead.
your while
loop in main()
is not checking whether getline()
is successful or not before processing the string
.
when calling brk_token()
, you are converting the string
into a const char*
just to convert it back to a string
again. You don't need to use string::c_str()
in this code at all.
calling brk_token()
repeatedly is overkill. Call it one time per string
and save the result into a local variable that you can then validate before using.
With all of that said, try this instead:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
vector<string> brk_token(const string &text, char breakon) {
vector<string> tokens;
string token;
for (size_t i = 0; i < text.size(); ++i) {
if (text[i] != breakon) {
token += text[i];
}
else {
tokens.push_back(token);
token = "";
}
}
if (!token.empty())
tokens.push_back(token);
return tokens;
}
int main() {
string program;
vector<string> tokens;
while (getline(cin, program) && (program != "break")) {
tokens = brk_token(program, ':');
if (tokens.size() != 2) {
cerr << "Bad input\n";
}
else if (tokens[0] == "print") {
cout << tokens[1];
}
else if (tokens[0] == "printnl") {
cout << tokens[1] << '\n';
}
else {
cerr << "Unknown input\n";
}
}
return 0;
}