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; }