I'm reading a function from a file in the format f(x,y,f(x),g) once I read the input it is stored as a vector and I am trying to get each value between the commas so in this case i want to get x, y f(x) and g as separate chars/strings. I'm stuck, any ideas?
Here is the solution I came up with:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
//Split string into vector of strings
vector<string> split(string str, char delimiter)
{
vector<string> internal;
stringstream ss(str); // Turn the string into a stream.
string tok;
while(getline(ss, tok, delimiter))
{
internal.push_back(tok);
}
return internal;
}
int main()
{
string myInput = "f(x,y,f(x),g)";
//Extract the string between outer brackets
size_t startIndex = myInput.find_first_of("(") + 1;
size_t endIndex = myInput.find_last_of(")");
string innerStr = myInput.substr(startIndex, endIndex-startIndex);
//Split the result by comma
vector<string> sep = split(innerStr, ',');
for(unsigned int i = 0; i < sep.size(); ++i)
{
cout << sep[i] << endl;
}
}
Hope it helps
Related
#include <string>
#include <iostream>
#include <vector>
#include <sstream>
#include <fstream>
using namespace std;
vector <string> tokenizeString(string filename, string delimiter);
int main() {
vector<string> tokens = tokenizeString("cityLocation.txt", "-");
for (int i = 0; i < tokens.size(); i++) {
cout << tokens[i];
}
return 0;
}
vector <string> tokenizeString (string filename, string delimiter) {
size_t pos = 0;
vector<string>tokens;
string token;
ifstream cityText(filename);
string line;
while (getline(cityText, line)) {
while ((pos = line.find(delimiter)) != string::npos) {
token = line.substr(0,pos);
tokens.push_back (token);
line.erase(0, pos + delimiter.length());
}
}
return (tokens);
}
So this is my code, and my text file data are
[1,1]-3-Big_City
[1,2]-3-Big_City
[1,3]-3-Big_City
[2,1]-3-Big_City
[2,2]-3-Big_City
[2,3]-3-Big_City
[2,7]-2-Mid_City
[2,8]-2-Mid_City
[3,1]-3-Big_City
My code is skipping all the Big_city and Mid_city.
It prints out only the first and second column data.
My delimiter is suppose to be '-'.
I haven't tried saving the data into vectors but would like some recommendation on how to do that
That is because you need another run for the last field after the last delimiter. You can accomplish this by using a post-test loop that will excecute one more time when pos==string::npos, therefore adding line.substr(pos,string::npos); as a token which is defined to be the substring from position pos to the end of the string.
vector <string> tokenizeString (string filename, string delimiter) {
vector<string>tokens;
string token;
ifstream cityText(filename);
string line;
while (cityText >> line) {
size_t pos = 0, lastpos=0;
do {
pos = line.find(delimiter, lastpos);
token = line.substr(lastpos,pos-lastpos);
tokens.push_back (token);
lastpos=pos+1;
} while (pos != string::npos);
}
return (tokens);
}
I want to do a read word by word and compare what word with what I have in my struct array. If I don't have one, I want to add in the first empty spot.
#include <iostream>
#include <fstream>
#include <string>
#include<string.h>
using namespace std;
struct cuvinte{
char *cuvant;
int numar;
};
int main()
{
cuvinte multime[100];
ifstream f;
f.open("input.txt");
string str;
while(getline(f,str))
{
char * cuvant = new char[str.size() + 1];
char * abc = new char[str.size() + 1];
copy(str.begin(), str.end(), abc);
cuvant = strtok (abc," ,/_");
while(cuvant!=NULL)
{
for(int i=0;i<10;i++)
{
cout<<cuvant;
if(strcmp(cuvant,multime[i].cuvant)==0)
multime[i].numar++;
else
{
for(int j=0;j<10;j++)
if(multime[j].numar==0)
{
multime[j].cuvant=cuvant;
multime[j].numar=1;
}
}
}
cuvant = strtok ( NULL , " ");
}
}
return 0;
}
Strcmp works infinitely and only takes the first word; I don't know why.
In C++ it should only take a handful of lines:
#include <string>
#include <fstream>
#include <unordered_map>
using WordFrequency = std::unordered_map<std::string, unsigned>;
WordFrequency read_words(std::istream& s) {
WordFrequency wf;
for(std::string word; s >> word;)
++wf[word];
return wf;
}
int main() {
std::fstream f("input.txt");
auto wf = read_words(f);
}
Before using word you may like to lower-case it and remove all punctuation, so that your dictionary doesn't contain separate entries for the same word, e.g. Or, or, or,.
I have written a program to store a text file in vector of characters .
#include<iostream>
#include<fstream>
#include <algorithm>
#include<vector>
using namespace std;
int main()
{
vector<char> vec;
ifstream file("text.txt");
if(!file.eof() && !file.fail())
{
file.seekg(0, std::ios_base::end);
std::streampos fileSize = file.tellg();
vec.resize(fileSize);
file.seekg(0, std::ios_base::beg);
file.read(&vec[0], fileSize);
}
int c = count(vec.begin(), vec.end(), 'U');
cout << c;
return 0;
}
I want to count occurrence of "USER" in the text file , but using count i can only count number of characters . How can i count number of occurrences of "USER" in the vector of character?
For example
text.txt
USERABRUSER#$$* 34 USER ABC RR IERUSER
Then the count of "USER" is 4. Words can only be in uppercase.
std::string has a find member function that will find an occurrence of one string inside another. You can use that to count occurrences something like this:
size_t count(std::string const &haystack, std::string const &needle) {
auto occurrences = 0;
auto len = needle.size();
auto pos = 0;
while (std::string::npos != (pos = haystack.find(needle, pos))) {
++occurrences;
pos += len;
}
return occurrences;
}
For example:
int main() {
std::string input{ "USERABRUSER#$$* 34 USER ABC RR IERUSER" };
std::cout << count(input, "USER");
}
...produces an output of 4.
This is how I would do it:
#include <fstream>
#include <sstream>
#include <iostream>
#include <unordered_map>
#include <string>
using namespace std;
int main() {
unordered_map<string, size_t> data;
string line;
ifstream file("text.txt");
while (getline(file, line)) {
istringstream is(line);
string word;
while (is >> word) {
++data[word];
}
}
cout << data["USER"] << endl;
return 0;
}
Let's try again. Once again, a vector isn't necessary. This is what I would consider to be the most C++ idiomatic way. It uses std::string's find() method to repeatedly find the substring in order until the end of the string is reached.
#include <fstream>
#include <iostream>
#include <string>
int main() {
// Read entire file into a single string.
std::ifstream file_stream("text.txt");
std::string file_contents(std::istreambuf_iterator<char>(file_stream),
std::istreambuf_iterator<char>());
unsigned count = 0;
std::string substr = "USER";
for (size_t i = file_contents.find(substr); i != std::string::npos;
i = str.find(substr, i + substr.length())) {
++count;
}
}
I need to split string by line.
I used to do in the following way:
int doSegment(char *sentence, int segNum)
{
assert(pSegmenter != NULL);
Logger &log = Logger::getLogger();
char delims[] = "\n";
char *line = NULL;
if (sentence != NULL)
{
line = strtok(sentence, delims);
while(line != NULL)
{
cout << line << endl;
line = strtok(NULL, delims);
}
}
else
{
log.error("....");
}
return 0;
}
I input "we are one.\nyes we are." and invoke the doSegment method. But when i debugging, i found the sentence parameter is "we are one.\\nyes we are", and the split failed. Can somebody tell me why this happened and what should i do. Is there anyway else i can use to split string in C++. thanks !
I'd like to use std::getline or std::string::find to go through the string.
below code demonstrates getline function
int doSegment(char *sentence)
{
std::stringstream ss(sentence);
std::string to;
if (sentence != NULL)
{
while(std::getline(ss,to,'\n')){
cout << to <<endl;
}
}
return 0;
}
You can call std::string::find in a loop and the use std::string::substr.
std::vector<std::string> split_string(const std::string& str,
const std::string& delimiter)
{
std::vector<std::string> strings;
std::string::size_type pos = 0;
std::string::size_type prev = 0;
while ((pos = str.find(delimiter, prev)) != std::string::npos)
{
strings.push_back(str.substr(prev, pos - prev));
prev = pos + delimiter.size();
}
// To get the last substring (or only, if delimiter is not found)
strings.push_back(str.substr(prev));
return strings;
}
See example here.
#include <sstream>
#include <string>
#include <vector>
std::vector<std::string> split_string_by_newline(const std::string& str)
{
auto result = std::vector<std::string>{};
auto ss = std::stringstream{str};
for (std::string line; std::getline(ss, line, '\n');)
result.push_back(line);
return result;
}
#include <iostream>
#include <string>
#include <regex>
#include <algorithm>
#include <iterator>
using namespace std;
vector<string> splitter(string in_pattern, string& content){
vector<string> split_content;
regex pattern(in_pattern);
copy( sregex_token_iterator(content.begin(), content.end(), pattern, -1),
sregex_token_iterator(),back_inserter(split_content));
return split_content;
}
int main()
{
string sentence = "This is the first line\n";
sentence += "This is the second line\n";
sentence += "This is the third line\n";
vector<string> lines = splitter(R"(\n)", sentence);
for (string line: lines){cout << line << endl;}
}
We have a string with multiple lines
we split those into an array (vector)
We print out those elements in a for loop
Using the library range-v3:
#include <range/v3/all.hpp>
#include <string>
#include <string_view>
#include <vector>
std::vector<std::string> split_string_by_newline(const std::string_view str) {
return str | ranges::views::split('\n')
| ranges::to<std::vector<std::string>>();
}
Using C++23 ranges:
#include <ranges>
#include <string>
#include <string_view>
#include <vector>
std::vector<std::string> split_string_by_newline(const std::string_view str) {
return str | std::ranges::views::split('\n')
| std::ranges::to<std::vector<std::string>>();
}
This fairly inefficient way just loops through the string until it encounters an \n newline escape character. It then creates a substring and adds it to a vector.
std::vector<std::string> Loader::StringToLines(std::string string)
{
std::vector<std::string> result;
std::string temp;
int markbegin = 0;
int markend = 0;
for (int i = 0; i < string.length(); ++i) {
if (string[i] == '\n') {
markend = i;
result.push_back(string.substr(markbegin, markend - markbegin));
markbegin = (i + 1);
}
}
return result;
}
I have a string currentLine="12 23 45"
I need to extract 12, 23, 45 from this string without using Boost libraries. Since i am using string, strtok fails for me. I have tried a number of things still no success.
Here is my last attempt
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
int countVar=0;
int inputArray[10];
char* tokStr;
tokStr=(char*)strtok(currentLine.c_str()," ");
while(tokstr!=NULL)
{
inputArray[countVar]=(int)tokstr;
countVar++;
tokstr=strtok(NULL," ");
}
}
}
the one without strtok
string currentLine;
while(!inputFile.eof())
while(getline(inputFile,currentLine))
{
cout<<atoi(currentLine.c_str())<<" "<<endl;
int b=0,c=0;
for(int i=1;i<currentLine.length();i++)
{
bool lockOpen=false;
if((currentLine[i]==' ') && (lockOpen==false))
{
b=i;
lockOpen=true;
continue;
}
if((currentLine[i]==' ') && (lockOpen==true))
{
c=i;
break;
}
}
cout<<b<<"b is"<<" "<<c;
}
Try this:
#include <sstream>
std::string str = "12 34 56";
int a,b,c;
std::istringstream stream(str);
stream >> a >> b >> c;
Read a lot about c++ streams here: http://www.cplusplus.com/reference/iostream/
std::istringstream istr(your_string);
std::vector<int> numbers;
int number;
while (istr >> number)
numbers.push_back(number);
Or, simpler (though not really shorter):
std::vector<int> numbers;
std::copy(
std::istream_iterator<int>(istr),
std::istream_iterator<int>(),
std::back_inserter(numbers));
(Requires the standard headers <sstream>, <algorithm> and <iterator>.)
You can also opt for Boost tokenizer ......
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
using namespace std;
using namespace boost;
int main(int argc, char** argv)
{
string str= "India, gold was dear";
char_separator<char> sep(", ");
tokenizer< char_separator<char> > tokens(str, sep);
BOOST_FOREACH(string t, tokens)
{
cout << t << "." << endl;
}
}
stringstream and boost::tokenizer are two possibilities. Here is a more explicit solution using string::find and string::substr.
std::list<std::string>
tokenize(
std::string const& str,
char const token[])
{
std::list<std::string> results;
std::string::size_type j = 0;
while (j < str.length())
{
std::string::size_type k = str.find(token, j);
if (k == std::string::npos)
k = str.length();
results.push_back(str.substr(j, k-j));
j = k + 1;
}
return results;
}
Hope this helps. You can easily turn this into an algorithm that writes the tokens to arbitrary containers or takes a function handle that processes the tokens.