In the below program i have inputted multiple string inputs like in the example below. Now i want to assign the multiple lines parsed data into different variables of different type.
int main()
{
int line=3, t;
string s, bigString;
for(int i=0 ; i<line ; i++)
{
getline(cin,s);
bigString += s + "\n";
}
cout <<bigString <<endl;
return 0;
}
Sample Input:
1 toy at 10.65
2 box of books at 12.11
1 pot plant at 6.45
I would like to parse and assign my variables like below,
//For storing array of variables,
int quantity;
Map<string,double>itemAndPrice;
ex1:
quantity = 1
itemAndPrice.first() = toy;
itemAndPrice.second() = 10.65;
ex2:
quantity = 2
itemAndPrice.first() = box of
books;
itemAndPrice.second() = 12.11;
ex3:
quantity = 1
itemAndPrice.first() = pot plant;
itemAndPrice.second() = 6.45;
As every input is different, how to parse and assign in respective variables in a generic way.
Why are you concatenating all of the inputs into a single string? And why are you using a Map for holding single items? I would suggest defining a struct to hold the different fields you need, and then have your reading loop parse the individual lines into a vector holding that struct type, eg:
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
struct itemInfo
{
int quantity;
std::string name;
double price;
};
int main()
{
std::string line;
std::vector<itemInfo> items;
while (std::getline(std::cin, line))
{
try
{
itemInfo item;
auto start = line.find_first_not_of(" \t");
auto stop = line.find_first_of(" \t", start + 1);
item.quantity = std::stoi(line.substr(start, stop - start));
start = line.find_first_not_of(" \t", stop + 1);
stop = line.find(" at ", start);
item.name = line.substr(start, stop - start);
start = line.find_first_not_of(" \t", stop + 4);
item.price = std::stod(line.substr(start));
items.push_back(item);
}
catch (const std::logic_error &) { }
}
// use items as needed...
return 0;
}
Online Demo
You could then take this a step further by moving the parsing logic into an overloaded operator>> for the struct, eg:
#include <iostream>
#include <string>
#include <vector>
#include <stdexcept>
struct itemInfo
{
int quantity;
std::string name;
double price;
};
std::istream& operator>>(std::istream &in, itemInfo &item)
{
try
{
std::string line;
if (std::getline(in, line))
{
auto start = line.find_first_not_of(" \t");
auto stop = line.find_first_of(" \t", start + 1);
item.quantity = std::stoi(line.substr(start, stop - start));
start = line.find_first_not_of(" \t", stop + 1);
stop = line.find(" at ", start);
item.name = line.substr(start, stop - start);
start = line.find_first_not_of(" \t", stop + 4);
item.price = std::stod(line.substr(start));
}
}
catch (const std::logic_error &)
{
in.setstate(std::ios_base::failbit);
}
return in;
}
int main()
{
itemInfo item;
std::vector<itemInfo> items;
while (std::cin >> item)
{
items.push_back(item);
}
// use items as needed...
return 0;
}
Online Demo
Related
I am reading File that contains
Boss, level, Specials,
"FireMen", 3, "Flame,Thrower", Fire,Breath
"Medusa", 6, "Snake,Poison"
"Hype", 10, "One,punch,Knock", Fly,Kick, "Dragon,Breath"
I am trying to read it into class with objects boss, level and specials
I am having problem reading from file since I split each by words by comma but it read specials like Flame,Thrower as separate due to comma in between them. How can I combine specials rather then splitting by commas so that it read Flame Thrower rather then Flame and thrower separately.
Also some specials are in quotation others are not.
I have been stuck at reading this rather complicated file. If anyone has time to read through my code and fix 10s of errors that I am getting would greatly be appreciated, Thank You
(What I did doesn't make much sense since this is my one month into C++ so still newbie and progressing)
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <iomanip>
#include "Boss.h"
using namespace std;
vector <Boss*> Info;
Boss* parseLine(string str)
{
vector<string> store;
string smt = " ";
Boss* values = nullptr;
if (smt != "")
{
(store.push_back(smt));
}
for (int i = 0; i < (int)str.size(); i++)
{
char ch = str[i];
if (ch != ',')
{
smt = smt + ch;
}
else
{
store.push_back(smt);
smt = "";
}
}
values = new Boss(store[0], stoi(store[1]), store[2]);
Name = store[0];
Level = store[1];
Specials = store[2];
return values;
}
bool readFile()
{
std::ifstream myFile("Bosses.txt");
if (!myFile.is_open())
{
cout << "fAILED" << "\n";
return false;
}
string str;
int i = 0;
while (std::getline(myFile, str))
{
cout << str << endl;
if (str[0] != '/')
{
Boss* Boss = parseLine(str);
result.push_back(Boss);
}
}
return true;
}
int main()
{
std::cout << "Read file\n;";
bool data = readFile();
for (Boss* t : result)
{
delete t;
}
And Class
#include <string>
#include <vector>
class Boss {
std::string Name;
int Level;
std::vector<std::string> Specials;
Boss(std::string Name, int Level, std::vector<std::string> Specials);
~Boss();
Boss(Boss& b);
void setName(std::string Name);
void setLevel(int Level);
};
Boss::Boss(std::string Name, int Level, std::vector<std::string> Specials)
{
this->Name= Name;
this->Level = Level;
this->Specials = Specials;
}
Boss::~Boss() {}
Boss::Boss(Boss& b)
{
Name = b.Name;
Level = b.Level;
Specials = b.Specials;
}
void Boss::setName(std::string Name) {
this->Name = Name;
}
void Boss::setLevel(int Level)
{
this->Level = Level;
}
This code reads your file and stores the data in the std::vector Info using stringstreams and other things to parse.
#include <iostream>
#include <string>
#include <vector>
#include <fstream>
#include <iomanip>
#include <sstream>
using namespace std;
class Boss {
std::string Name;
int Level;
std::vector<std::string> Specials;
public:
Boss(std::string n, int l, std::vector<std::string> s)
{
this->Name = n;
this->Level = l;
this->Specials = s;
};
~Boss() {};
Boss(const Boss& b) {
this->Name = b.Name;
this->Level = b.Level;
this->Specials = b.Specials;
};
Boss() {};
Boss operator= (Boss b) {
this->Name = b.Name;
this->Level = b.Level;
this->Specials = b.Specials;
return b;
}
void setName(std::string n) { Name = n; };
void setLevel(int l) { Level = l; };
void setSpecials(std::vector<std::string> s) {Specials = s;}
std::string getName() const { return Name; }
int getLevel() const { return Level; }
std::vector<std::string> getSpecials() const { return Specials; }
};
vector <Boss> Info;
Boss parseLine(string str)
{
vector<string> store;
string smt;
stringstream evaluator;
Boss value;
evaluator << str; //put our string into evaluator
{
char double_quote_remover;
evaluator >> double_quote_remover; //remove the first double quote
getline(evaluator, smt, '"'); //get the name until the next double quote
char comma_remover;
evaluator >> comma_remover; //remove the comma
}
value.setName(smt); //put smt into the Boss's name
{
int Level;
evaluator >> Level; //get an int from our string
value.setLevel(Level); //put our int into our Boss
}
char curr;
while (evaluator >> curr && curr != ','); //get the comma after the int
smt = ""; //reset
curr = ' '; //reset
while (evaluator >> curr) { //while we read chars into curr
if (isalpha(curr)) { evaluator.putback(curr); curr = ','; } //if the char is a letter, put it back
if (curr == '\"') getline(evaluator,smt,'\"'); //if the char is a double quote, read until we reach another
else if (curr == ',') getline(evaluator,smt,','); //if the char is a comma, read until we get another
if (smt != "") //if the string is not null, put it in store
store.push_back(smt);
smt = ""; //reset
}
value.setSpecials(store); //put store into our Boss
return value; //return our boss
}
bool readFile()
{
std::ifstream myFile("Bosses.txt");
if (!myFile.is_open())
{
cout << "FAILED" << "\n";
return false;
}
string str;
getline(myFile, str); //for the first line, which we don't need
int i = 0;
while (std::getline(myFile, str))
{
Boss Boss = parseLine(str);
Info.push_back(Boss);
}
return true;
}
int main()
{
bool data = readFile();
}
This should work. I have tested it thouroughly. Inform me of any errors.
Note: There was no need for pointers that were in your original code.
So I am using stringstream in a function in c++ to take the numbers from a string, and then return the numbers to an array in main, but for some reason, they always return as 0 instead of the actual numbers. Code is below, does anyone know how to fix this?
int main()
{
for(int i = 0; i < userInput.length(); i++)
{
...
else
{
chemNumbers[i] = extractIntegerWords(userInput);
cout << chemNumbers[i] << endl;
}
}
int extractIntegerWords(string str)
{
stringstream ss;
int num = 0;
ss << str;
/* Running loop till the end of the stream */
string temp;
int found;
if(!ss.eof())
{
ss >> temp;
if (stringstream(temp) >> found)
{
num = found;
}
temp = "";
}
return found;
}
The original if statement doesn't pertain to the function only what is seen in the else statement, which is in main
This is off the top of my head and I don't have much time to test it, but this should put you in the right direction:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
using std::cout;
using std::endl;
using std::istringstream;
using std::string;
using std::vector;
inline bool tryGetInt(const string& str, string& out) { istringstream sStream(str); return !(sStream >> out).fail(); } /*!< Tries to parse a string to int. */
void splitString(const string &str, const string &delimiters, vector<string> &tokens) {
// Skip delimiters at beginning.
string::size_type lastPos = str.find_first_not_of(delimiters, 0);
// Find first "non-delimiter".
string::size_type pos = str.find_first_of(delimiters, lastPos);
while (string::npos != pos || string::npos != lastPos) {
// Found a token, add it to the vector.
tokens.push_back(str.substr(lastPos, pos - lastPos));
// Skip delimiters. Note the "not_of"
lastPos = str.find_first_not_of(delimiters, pos);
// Find next "non-delimiter"
pos = str.find_first_of(delimiters, lastPos);
}
}
int32_t main(int argCount, char* argValues[]) {
for (int32_t i = 0; i < argCount; i++) {
cout << "Found argument " << argValues[i] << endl;
auto foundIntegers = getIntegerFromString(string(argValues[i]));
// Do whatever
}
return 0;
}
vector<int64_t> getIntegerFromString(string formula) {
vector<int64_t> foundInts;
string temp;
if (tryGetInt(formula, temp)) {
vector<string> intsAsStrings;
splitString(temp, " ", intsAsStrings);
for (auto item : intsAsStrings) {
foundInts.push_back(stol(item));
}
}
return foundInts;
}
Regular expression might help:
std::vector<std::pair<std::string, std::size_t>> Extract(const std::string& s)
{
std::vector<std::pair<std::string, std::size_t>> res;
const std::regex reg{R"(([a-zA-Z]+)(\d*))"};
for (auto it = std::sregex_iterator(s.begin(), s.end(), reg);
it != std::sregex_iterator();
++it)
{
auto m = *it;
res.push_back({m[1], m[2].length() == 0 ? 1 : std::stoi(m[2])});
}
return res;
}
int main()
{
for (auto p : Extract("C6H12O6")) {
std::cout << p.first << ": " << p.second << std::endl;
}
}
Demo
I add option for array instead vector for #I'mbadatCS
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
using namespace std;
vector<int> extractIntegerWords(const string& _str)
//for array option: void extractIntegerWords(const string& _str, int* numArr)
{
stringstream ss;
ss << _str;
vector<int> vec;
string temp;
int found;
//for array option: int idx = 0;
while(!ss.eof())
{
ss >> temp;
if (stringstream(temp) >> found)
{
vec.push_back(found);
//for array option:numArr[idx++] = found;
}
temp = "";
}
return vec;
//for array option: return;
}
int main()
{
string s = "bla 66 bla 9999 !"
vector<int> res = extractIntegerWords(s);
for (int i = 0; i < res.size(); ++i)
{
cout << res[i] << ", " << endl;
}
}
a few comments:
const string& in input argument, not string. you don't want harm your source data
you need a loop not "if" (like ths the operation will run just one time)
where your array??
in C++ prefer use vector and not array
This is a code for reading in .txt file and spliting it by : and printing out the result. But I got stuck on the while-loop. This is my code.
#include <iostream>
#include <fstream>
#include <string>
#include <cstring>
using namespace std;
string* split(const string& str, const string& delim) {
string* string_list = new string[10];
int idx = 0;
char *token = strtok(const_cast<char*>(str.c_str()), delim.c_str());
while (token != NULL) {
string_list[idx] = token;
token = strtok(NULL, delim.c_str());
++idx;
}
return string_list;
}
struct Item {
string name;
string age;
string id;
string subject[10];
};
struct Item* create_item() {
struct Item* pitem = new Item;
return pitem;
};
void insert_item(struct Item *prev_item, struct Item *item) {
item = (prev_item + 5);
}
int main() {
string student, student2;
string *string_list, *subject, *string_list2, *subject2;
struct Item* pstudent, *pstudent2;
ifstream fin;
fin.open("input.txt");
fin >> student;
while (student != "\n") {
string_list = split(student, ":");
pstudent = create_item();
pstudent->name = *string_list;
pstudent->age = *(string_list + 1);
pstudent->id = *(string_list + 2);
subject = split(*(string_list + 3), ",");
for (int i = 0; i < 10; i++) {
if (*(subject + i) != "") {
pstudent->subject[i] = *(subject + i);
}
}
cout << *(string_list+1) << endl;
fin >> student2;
string_list = split(student2, ":");
pstudent2 = create_item();
insert_item(pstudent, pstudent2);
pstudent2->name = *(string_list);
pstudent2->age = *(string_list + 1);
pstudent2->id = *(string_list + 2);
subject2 = split(*(string_list + 3), ",");
for (int i = 0; i < 10; i++) {
if (*(subject2 + i) != "") {
pstudent2->subject[i] = *(subject2 + i);
}
}
}
cout << pstudent2->name << endl;
fin.close();
return 0;
}
I am still working on this code, but the while-loop in the main() will not stop. I wanted it to stop when the input.txt file input is a new line.
input.txt is
Mary:20:287:Math,Algorithm\n
Tom:21:202:Math,English\n
Hee:20:256:Math
thanks in advance!
Don't try to process more than one student in the body of the loop.
Rather than trying to write a linked-list type, use an existing collection type.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
using strings_view = std::vector<std::string_view>;
strings_view split(std::string_view str, char delim) {
strings_view view;
while (str.size())
{
auto pos = str.find(delim);
view.push_back(str.substr(0, pos - 1));
str = str.substr(pos + 1);
}
return view;
}
struct Item {
std::string name;
std::string age;
std::string id;
std::vector<std::string> subject;
};
int main() {
std::vector<Item> students;
std::ifstream fin("input.txt");
for (std::string line; get_line(fin, line);) {
strings_view view = split(line, ':');
Item student;
student.name = view[0];
student.age = view[1];
student.id = view[2];
string_view subject = split(view[3], ',')
student.subject.assign(subject.begin(), subject.end());
students.push_back(student);
}
std::cout << students[1].name << std::endl;
return 0;
}
I'm writing a program which makes calculations based on commands, but i'm having a little trouble with the vector's range.
Basically i am entering integers into a vector, a sequence of integers each on a new line, and for example if i enter the command "sum" it gets the last two elements of the vector (the sequence of integers) sums them, deletes them from the sequence and adds to the sequence the new number.
Example:
1
2
4
5
sum
end (this command ends my program)
Output:
1
2
9
Here is the code:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
#define CONSOLE_LOG(x) std::cout << x
#define COMMAND_END command[0]
#define COMMAND_SUM command[1]
#define COMMAND_SUBTRACT command[2]
#define COMMAND_CONCAT command[3]
#define COMMAND_DISCARD command[4]
#define COMMAND_DISPSEQ command[5]
std::string sum(std::string& x, std::string& y, std::vector<std::string>& vec)
{
int xInt = atoi(x.c_str());
int yInt = atoi(y.c_str());
int result = xInt + yInt;
std::ostringstream os;
std::string strResult;
os << result;
strResult = os.str();
vec.erase(vec.end() - 1);
vec.erase(vec.end() - 1);
return strResult;
}
/*
std::string subtract(std::string& x, std::string& y)
{
}
std::string concat(std::string& x, std::string& y)
{
}
std::string discard(std::string& x, std::string& y)
{
}
*/
void dispseq(std::vector<std::string>& vec)
{
std::vector<std::string>::const_iterator iter;
for (iter = vec.begin(); iter != vec.end(); iter++)
{
std::cout << *iter << std::endl;
}
}
void enterSequence()
{
std::vector<std::string> command =
{
"end",
"sum",
"subtract",
"concat",
"discard",
"dispseq"
};
std::vector<std::string> sequence;
std::string input;
std::string a = sequence[sequence.size() - 1];
std::string b = sequence[sequence.size() - 2];
do
{
std::cin >> input;
sequence.emplace_back(input);
if (input == COMMAND_END)
{
sequence.erase(sequence.end() - 1);
}
if (input == COMMAND_SUM)
{
sequence.emplace_back(sum(a, b, sequence));
}
dispseq(sequence);
} while (input != COMMAND_END);
}
int main()
{
enterSequence();
std::cin.get(); std::cin.get();
return 0;
}
And here is my problem. Of course i need to define the last two elements of the vector, and i do it with
std::string a = sequence[sequence.size() - 1];
std::string b = sequence[sequence.size() - 2];
But it gives me an exception, and tells me i'm out of range. I guess im not supposed to pass a size of a vector, which still doesn't have one.
How can i write it then?
a and b are being initialized to a negative index of your vector. You can fix that by modifying your do-while loop.
std::string a;
std::string b;
do
{
if(sequence.size() >= 2)
{
b = sequence[sequence.size() - 2];
a = sequence[sequence.size() - 1];
}
else if(sequence.size() >= 1)
{
a = sequence[sequence.size() - 1]
}
std::cin >> input;
sequence.emplace_back(input);
if (input == COMMAND_END)
{
sequence.erase(sequence.end() - 1);
}
if (input == COMMAND_SUM)
{
sequence.emplace_back(sum(a, b, sequence));
}
dispseq(sequence);
} while (input != COMMAND_END);
So i need to check if a specific sub-string exists in a Token and if it exists add 1 to the variable int a.
String input = "aaabbb#abbb#"
tokenize input
tokens =
abbba
abbbb
a exists in both tokens so output should be
a:2
However my code outputs
a:1
a:1
If there is only one token with a then it prints
a:1
If there are no tokens with a such as :
bbb#bbb#
it correctly outputs nothing.
How can i get my code to output
a:2
and not
a:1
a:1
---This is my code
main.cpp
#include "Tokenizer.h"
#include <string>
#include <iostream>
#include <algorithm>
using std::string;
using std::cout;
using std::endl;
int countSubstring(const std::string& str, const std::string& sub)
{
if (sub.length() == 0) return 0;
int count = 0;
for (size_t offset = str.find(sub); offset != std::string::npos;
offset = str.find(sub, offset + sub.length()))
{
++count;
}
return count;
}
int main(int argc, char* argv[])
{
// instanciate Tokenizer class
Tokenizer str;
string token;
string input;
getline(std::cin , input);
// set source string with delimiter "#"
str.set(input, "#");
// Tokenizer::next() returns a next available token from source string
// If it reaches EOS, it returns zero-length string, "".
while((token = str.next()) != "")
{
int a = 0;
if(countSubstring(token,"a") >= 1)
{
a++;
}
cout << "a: " << a << endl;
}
cout << endl;
return 0;
}
Tokenizer.h
#ifndef TOKENIZER_H
#define TOKENIZER_H
#include <string>
#include <vector>
// default delimiter string (space, tab, newline, carriage return, form feed)
const std::string DEFAULT_DELIMITER = "";
class Tokenizer
{
public:
// ctor/dtor
Tokenizer();
Tokenizer(const std::string& str, const std::string& delimiter=DEFAULT_DELIMITER);
~Tokenizer();
// set string and delimiter
void set(const std::string& str, const std::string& delimiter=DEFAULT_DELIMITER);
void setString(const std::string& str); // set source string only
void setDelimiter(const std::string& delimiter); // set delimiter string only
std::string next(); // return the next token, return "" if it ends
std::vector<std::string> split(); // return array of tokens from current cursor
protected:
private:
void skipDelimiter(); // ignore leading delimiters
bool isDelimiter(char c); // check if the current char is delimiter
std::string buffer; // input string
std::string token; // output string
std::string delimiter; // delimiter string
std::string::const_iterator currPos; // string iterator pointing the current position
};
#endif // TOKENIZER_H
Tokenizer.cpp
#include "Tokenizer.h"
///////////////////////////////////////////////////////////////////////////////
// constructor
///////////////////////////////////////////////////////////////////////////////
Tokenizer::Tokenizer() : buffer(""), token(""), delimiter(DEFAULT_DELIMITER)
{
currPos = buffer.begin();
}
Tokenizer::Tokenizer(const std::string& str, const std::string& delimiter) : buffer(str), token(""), delimiter(delimiter)
{
currPos = buffer.begin();
}
///////////////////////////////////////////////////////////////////////////////
// destructor
///////////////////////////////////////////////////////////////////////////////
Tokenizer::~Tokenizer()
{
}
///////////////////////////////////////////////////////////////////////////////
// reset string buffer, delimiter and the currsor position
///////////////////////////////////////////////////////////////////////////////
void Tokenizer::set(const std::string& str, const std::string& delimiter)
{
this->buffer = str;
this->delimiter = delimiter;
this->currPos = buffer.begin();
}
void Tokenizer::setString(const std::string& str)
{
this->buffer = str;
this->currPos = buffer.begin();
}
void Tokenizer::setDelimiter(const std::string& delimiter)
{
this->delimiter = delimiter;
this->currPos = buffer.begin();
}
///////////////////////////////////////////////////////////////////////////////
// return the next token
// If cannot find a token anymore, return "".
///////////////////////////////////////////////////////////////////////////////
std::string Tokenizer::next()
{
if(buffer.size() <= 0) return ""; // skip if buffer is empty
token.clear(); // reset token string
this->skipDelimiter(); // skip leading delimiters
// append each char to token string until it meets delimiter
while(currPos != buffer.end() && !isDelimiter(*currPos))
{
token += *currPos;
++currPos;
}
return token;
}
///////////////////////////////////////////////////////////////////////////////
// skip ang leading delimiters
///////////////////////////////////////////////////////////////////////////////
void Tokenizer::skipDelimiter()
{
while(currPos != buffer.end() && isDelimiter(*currPos))
++currPos;
}
///////////////////////////////////////////////////////////////////////////////
// return true if the current character is delimiter
///////////////////////////////////////////////////////////////////////////////
bool Tokenizer::isDelimiter(char c)
{
return (delimiter.find(c) != std::string::npos);
}
///////////////////////////////////////////////////////////////////////////////
// split the input string into multiple tokens
// This function scans tokens from the current cursor position.
///////////////////////////////////////////////////////////////////////////////
std::vector<std::string> Tokenizer::split()
{
std::vector<std::string> tokens;
std::string token;
while((token = this->next()) != "")
{
tokens.push_back(token);
}
return tokens;
}
Also, a is not allowed to be printed if it does not appear in a token.
A while would work better I think. This is my solution:
#include <iostream>
#include <string>
using namespace std;
size_t countSubString(const string& str, const string& sub) {
size_t ret = 0;
size_t loc = str.find(sub);
while (loc != string::npos) {
++ret;
loc = str.find(sub, loc+1);
}
return ret;
}
int main() {
static const char* tokens[] = {"aaa", "aba" };
for (int i=0; i<2; ++i) {
cout << tokens[i] << " " << countSubString(tokens[i], "a") << endl;
}
return 0;
}
#include <string>
#include <iostream>
int countOccurances( const std::string &token, const std::string &substring )
{
const size_t token_len = token.length();
const size_t substring_len = substring.length();
if ( substring_len > token_len ) { return 0; }
if ( substring_len == token_len )
return ((token.compare(substring) == 0) ? 1 : 0);
const size_t range = token_len-substring_len;
size_t counter = 0;
for (size_t i=0; i <= range; i++) {
if ( token.compare(i,substring_len,substring) == 0 )
++counter;
}
return counter;
}
int main () {
std::string token = "abbb";
std::string substring = "a";
std::cout << "Token " << token << " has " << countOccurances(token,substring) <<
" occurances of " << substring << std::endl;
token = "abba";
substring = "a";
std::cout << "Token " << token << " has " << countOccurances(token,substring) <<
" occurances of " << substring << std::endl;
return 0;
}
The heart of your code is this
int a = 0;
if(countSubstring(token,"a") >= 1)
{
a++;
}
cout << "a: " << a << endl;
This code creates a variable called a and assigns it the value 0. Then it calls countSubstring and tests if the return value for being >= 1. The return value is then discarded.
If the condition above matched, we increase a by 1.
Then we print a.
All of the above happens for each iteration of the while loop in which this code sits.
So this code can only ever print a: 0 or a: 1.
This is a shame, because the value you were looking for was returned to you by countSubstring yet you chose to discard it.
Your code can be fixed this simply:
int count = countSubstring(token, "a");
std::cout << "a: " << count << '\n';
As in:
while((token = str.next()) != "")
{
int count = countSubstring(token, "a");
std::cout << "a: " << count << '\n';
}