Make 2D Array by Splitting a text with a delimiter C++ - c++

Well I have that code:
#include <iostream>
#include <string>
using namespace std;
int main()
{
std::string s = "0,0,0,1,1,1,0,0,1";
std::string delimiter = ",";
int x = 0;
std::string mapa[9];
size_t pos = 0;
std::string token;
while ((pos = s.find(delimiter)) != std::string::npos) {
token = s.substr(0, pos);
std::cout << token << std::endl;
s.erase(0, pos + delimiter.length());
mapa[x] = token;
x++;
}
std::cout << s << std::endl;
cin.get();
}
Parse (split) a string in C++ using string delimiter (standard C++)
I have x array, but I need a second dimension the Y... I get the content from a text file called map.txt:
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
And I need to split it by commas (for the x) and later by newlines (for y)...
But Idk how to do the Y array... What Can I do?
Thanks!

You may read the lines from the file as
fstream fstr;
fstr.open("file.txt",ios::in);
string str;
int yDimension = 0;
while(getline(fstr,str)
{
yDimension++; //do appropriate thing with the y dimension
std::string token;
while ((pos = str.find(delimiter)) != std::string::npos) {
token = str.substr(0, pos);
std::cout << token << std::endl;
str.erase(0, pos + delimiter.length());
mapa[x] = token;
x++;
}
}

You can read the entire file of any number of rows with any number of comma-delimited columns (memory-permitting) with this:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <string>
#include <sstream>
#include <vector>
struct int_reader : std::ctype<char>
{
int_reader() : std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table()
{
static std::vector<std::ctype_base::mask> rc(table_size, std::ctype_base::mask());
rc[','] = std::ctype_base::space;
rc['\n'] = std::ctype_base::space;
return &rc[0];
}
};
int main()
{
std::vector<std::vector<int> > myFileData;
std::ifstream fin("MyDataFile.txt", std::ifstream::in);
std::string buffer;
while (std::getline(fin, buffer))
{
std::stringstream ss(buffer);
std::vector<int> t;
int_reader reader;
ss.imbue(std::locale(std::locale(), &reader));
std::copy(std::istream_iterator<int>(ss), std::istream_iterator<int>(), std::back_inserter(t));
myFileData.push_back(t);
}
// do whatever you need to with the loaded arrays ...
return 0;
}

You can use ifstream::getline(), with a delimiter ','
ifstream file ( "map.txt" );
string value;
while ( file.good() )
{
getline ( file, value, ',' );
}
Or you can read all the text and use regular expression to take each text out between delimiter.

The sortest way to do that without vectors:
#include <iostream>
#include <string>
#include <fstream>
using namespace std;
int main()
{
fstream fstr;
fstr.open("mapa.txt");
char mapa[31][9];
int x = 0, y = 0;
char c;
while(fstr.good())
{
c = fstr.get();
if (c!= ',') {
mapa[x][y] = c;
x++;
}
if (c=='\n')
{
x = 0;
y++;
}
}
fstr.close();
cin.get();
}
Only 32 lines!! :D

Related

How can I split a string of Numbers and multiply the separate numbers?

I have two separate numbers in a string. I figured out how to split the string with a delimiter (output being 136) but am stuck with how I can multiply the two numbers and store the result in a variable. Any tips?
#include <iostream>
#include <string>
int main()
{
std::string b = "13,6";
std::string delimiter = ",";
size_t pos = 0;
std::string token;
while ((pos = b.find(delimiter)) != std::string::npos) {
token = b.substr(0, pos);
std::cout << token;
b.erase(0, pos + delimiter.length());
}
std::cout << b;
}
Got it thanks to you:
#include <iostream>
#include <string>
int main()
{
std::string b = "13,6";
std::string delimiter = ",";
size_t pos = 0;
std::string token;
int number1;
int number2;
while ((pos = b.find(delimiter)) != std::string::npos) {
token = b.substr(0, pos);
number1 = std::stoi(token);
b.erase(0, pos + delimiter.length());
}
number2 = std::stoi(b);
std::cout << number1*number2;
}

Concatenate unique value separated by comma in two string in C++

CString s;
int res = 0;
char *existing;
char *current;
existing = strtok(urls, ",");
current = strtok(storedurls, ",");
while (existing != NULL)
{
while (current != NULL)
{
res = strcmp(existing, current);
if (res == 0) continue;
s.Append(current);
current = strtok(NULL, ",");
if (current != NULL) s.Append(",");
}
existing = strtok(NULL, ",");
}
strcat(urls, s);
We have a string of storedurl L("url1,url2,url3") and urls L("url3,url5") and I want to store the unique urls from both string and get a single output as L("url1,url2,url3,url5")
Stop using C-style string functions in C++ and get acquainted with the C++ Standard Library.
#include <algorithm>
#include <vector>
#include <string>
#include <sstream>
#include <iostream>
std::vector<std::string> split(std::string const& src, char delim = ',')
{
std::vector<std::string> dst;
std::stringstream ss{ src };
std::string tmp;
while (std::getline(ss, tmp, delim))
dst.push_back(tmp);
return dst;
}
int main()
{
std::string foo{ "url1,url2,url4" };
std::string bar{ "url2,url3,url5" };
auto foo_urls{ split(foo) };
auto bar_urls{ split(bar) };
std::vector<std::string> unique_urls{ foo_urls.begin(), foo_urls.end() };
unique_urls.reserve(foo_urls.size() + bar_urls.size());
unique_urls.insert(unique_urls.end(), bar_urls.begin(), bar_urls.end());
std::sort(unique_urls.begin(), unique_urls.end());
unique_urls.erase(std::unique(unique_urls.begin(), unique_urls.end()), unique_urls.end());
for (auto const& url : unique_urls)
std::cout << url << '\n';
}
DWORD res = 0;
CString existingUrls = urls;
CString curUrls;
CString curItemInExitingUrl;
CString curItemInCurUrl;
CString urlsToAdd;
while (!existingUrls.IsEmpty()) {
CWinLogFile::GetTok(existingUrls, _T(","), curItemInExitingUrl);
curUrls = src.urls;
while (!curUrls.IsEmpty()) {
CWinLogFile::GetTok(curUrls, _T(","), curItemInCurUrl);
if (curItemInExitingUrl.Compare(curItemInCurUrl)==0)
{
res = 1;
}
}
if (res == 0)
{
urlsToAdd.Append(curItemInExitingUrl);
urlsToAdd.AppendChar(',');
}
else
res = 0;
}
urlsToAdd.Append(src.urls);
Found the solution for my posted question. Where urls & src.urls are two comma separated values of urls. Thanks.

How to take a function using stringstream to parse the numbers, and put them into an array?

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

converting strings to integers by using "stringstream "

I am trying to convert strings of data to integers, (to use it for some calculations ) by using stringstream , but it fails when there is a space.
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
if(stream >> ch) {
values.push_back(n);
}
else {
values.push_back(n);
}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
input : 1,182,08 51 15 --> output : 1 182 8 1 5
there are some digits lost after spaces.
so, what can I do to avoid it?
Complete working code based on seccpur's answer. Visual Studio 2017 Community:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
#define BUFSZ 100 // Set max size of the numbers as a single string
int convertToIntegers(char *s, vector<int> &values);
int main()
{
int count;
int i;
char data[BUFSZ];
vector<int> values;
strcpy_s(data, "1,182,08 51 15");
count = convertToIntegers(data, values);
// for (auto val : values) // Show the result
// cout << val << '\n';
// *** OR ***
for (i = 0; i < count; i++)
cout << values[i] << '\n';
}
//////////////////////////////////////
// Convert a C string to integers
//
int convertToIntegers(char *s, vector<int> &values)
{
vector<string> numbers;
char *next_token;
char* ptr = strtok_s(s, " -.,;", &next_token);
while (ptr)
{
string str(ptr);
numbers.push_back(str);
ptr = strtok_s(NULL, " -.,;", &next_token); // Next number
}
//
// Convert the resulting strings to integers
//
for (auto str : numbers)
values.push_back(stoi(str));
return (int)values.size();
}
If you know you have exactly one character as a separator, either a space, either a comma, the following code will work:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
string line;
vector <string>data;
for (int i = 0; i < 10;i++) {
getline(cin,line);
data.push_back(line);
}
///converting digits to int
vector<int> values;
int n;
char ch=',';
for (int i = 0; i < data.size();i++) {
stringstream stream(data[i]);
while( stream >>n ) {
char c = stream.get();
//if(stream >> ch) {
// values.push_back(n);
//}
//else {
values.push_back(n);
//}
cout<<n<<" ";
}
cout<<endl;
}
return 0;
}
You are using multiple delimiters in the input ( like whitespace : , ; -) which complicates the matter. Here's a possible snippet using std::strtok:
//Enter a line
string line;
getline(cin, line);
// Convert string to char* so that std::strtok could be used later
char *cstr = new char[line.length() + 1];
std::strcpy(cstr, line.c_str());
vector<string> words;
// split line into multiple strings using multiple delimiters
char* ptr = std::strtok(cstr, " -.,;");
while (ptr)
{
string str(ptr);
words.push_back(str);
ptr = strtok(NULL, " -.,;");
}
delete[] cstr;
// Convert string to int
vector<int> values;
for (auto str : words){
values.push_back(std::stoi(str));
}
// Print the values
for (auto val : values){
cout << val << '\n';
}

How to insert an integer with leading zeros into a std::string?

In a C++14 program, I am given a string like
std::string s = "MyFile####.mp4";
and an integer 0 to a few hundred. (It'll never be a thousand or more, but four digits just in case.) I want to replace the "####" with the integer value, with leading zeros as needed to match the number of '#' characters. What is the slick C++11/14 way to modify s or produce a new string like that?
Normally I would use char* strings and snprintf(), strchr() to find the "#", but figure I should get with modern times and use std::string more often, but know only the simplest uses of it.
What is the slick C++11/14 way to modify s or produce a new string like that?
I don't know if it's slick enough but I propose the use of std::transform(), a lambda function and reverse iterators.
Something like
#include <string>
#include <iostream>
#include <algorithm>
int main ()
{
std::string str { "MyFile####.mp4" };
int num { 742 };
std::transform(str.rbegin(), str.rend(), str.rbegin(),
[&](auto ch)
{
if ( '#' == ch )
{
ch = "0123456789"[num % 10]; // or '0' + num % 10;
num /= 10;
}
return ch;
} // end of lambda function passed in as a parameter
); // end of std::transform()
std::cout << str << std::endl; // print MyFile0742.mp4
}
I would use regex since you're using C++14:
#include <iostream>
#include <regex>
#include <string>
#include <iterator>
int main()
{
std::string text = "Myfile####.mp4";
std::regex re("####");
int num = 252;
//convert int to string and add appropriate number of 0's
std::string nu = std::to_string(num);
while(nu.length() < 4) {
nu = "0" + nu;
}
//let regex_replace do it's work
std::regex_replace(std::ostreambuf_iterator<char>(std::cout),
text.begin(), text.end(), re, nu);
std::cout << std::endl;
return 0;
}
WHy not use std::stringstream and than convert it to string.
std::string inputNumber (std::string s, int n) {
std::stringstream sstream;
bool numberIsSet = false;
for (int i = 0; i < s; ++i) {
if (s[i] == '#' && numberIsSet == true)
continue;
else if (s[i] == '#' && numberIsSet == false) {
sstream << setfill('0') << setw(5) << n;
numberIsSet = true;
} else
sstream << s[i];
}
return sstream.str();
}
I would probably use something like this
#include <iostream>
using namespace std;
int main()
{
int SomeNumber = 42;
std:string num = std::to_string(SomeNumber);
string padding = "";
while(padding.length()+num.length()<4){
padding += "0";
}
string result = "MyFile"+padding+num+".mp4";
cout << result << endl;
return 0;
}
Mine got out of control while I was playing with it, heh.
Pass it patterns on its command line, like:
./cpp-string-fill file########.jpg '####' test###this### and#this
#include <string>
#include <iostream>
#include <sstream>
std::string fill_pattern(std::string p, int num) {
size_t start_i, end_i;
for(
start_i = p.find_first_of('#'), end_i = start_i;
end_i < p.length() && p[end_i] == '#';
++end_i
) {
// Nothing special here.
}
if(end_i <= p.length()) {
std::ostringstream os;
os << num;
const std::string &ns = os.str();
size_t n_i = ns.length();
while(end_i > start_i && n_i > 0) {
end_i--;
n_i--;
p[end_i] = ns[n_i];
}
while(end_i > start_i) {
end_i--;
p[end_i] = '0';
}
}
return p;
}
int main(int argc, char *argv[]) {
if(argc<2) {
exit(1);
}
for(int i = 1; i < argc; i++) {
std::cout << fill_pattern(argv[i], 1283) << std::endl;
}
return 0;
}
I would probably do something like this:
using namespace std;
#include <iostream>
#include <string>
int main()
{
int SomeNumber = 42;
string num = std::to_string(SomeNumber);
string guide = "myfile####.mp3";
int start = static_cast<int>(guide.find_first_of("#"));
int end = static_cast<int>(guide.find_last_of("#"));
int used = 1;
int place = end;
char padding = '0';
while(place >= start){
if(used>num.length()){
guide.begin()[place]=padding;
}else{
guide.begin()[place]=num[num.length()-used];
}
place--;
used++;
}
cout << guide << endl;
return 0;
}