This question already has answers here:
Right way to split an std::string into a vector<string>
(12 answers)
Closed 7 years ago.
I'm writing 2 programs, the first program has an array of integers
vector<int> v = {10, 200, 3000, 40000};
Then it converts the vector into string
int i;
stringstream sw;
string stringword;
for (i=0;i<v.size();i++)
{
sw << v[i] << ',';
}
stringword = sw.str();
cout << "Vector in string : "<< stringword << endl;
And then write it in a file
ofstream myfile;
myfile.open ("writtentext");
myfile << stringword;
myfile.close();
The output :
Vector in string : 10,200,3000,40000
The second program will read the file, convert the string back to integer, and then push it back to vector.
The code :
string stringword;
ifstream myfile;
myfile.open ("writtentext");
getline (myfile,stringword);
cout << "Read From File = " << stringword << endl;
cout << "Convert back to vector = " ;
for (int i=0;i<stringword.length();i++)
{
if (stringword.find(','))
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
stringword.erase(0, stringword.find(','));
}
}
for (int j=0;j<v.size();j++)
{
cout << v.at(j) << " " ;
}
The problem is, it can only convert and push back the first element, the rest is erased. Here is the output :
Read From File = 10,200,3000,40000,
Convert back to vector = 10
What did I do wrong? Thanks
There's problem with your for loop
Consider this:
while(1) //Use a while loop, "i" isn't doing anything for you
{
//if comman not found find return string::npos
if (stringword.find(',')!=std::string::npos)
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
//Erase all element including comma
stringword.erase(0, stringword.find(',')+1);
}
else
break; //Come out of loop
}
Instead, just use std::stringstream to read back from file
std::stringstream ss(stringword);
int value;
while (ss >> value)
{
v.push_back(value);
if (ss.peek() == ',')
ss.ignore();
}
for (int j=0;j<v.size();j++) //Fix variables
{
cout << v.at(j) << " " ; // Can use simply v[j]
}
for (int j=0;j<v.size();i++)
{
cout << v.at(i) << " " ;
}
should be
for (int j=0;j<v.size();j++)
{
cout << v.at(j) << " " ;
}
i is not declared in the for loop
You can skip the string conversion. All stream can handle int types.
std::vector<int> to output:
#include <iostream>
#include <iterator>
#include <vector>
int main() {
std::vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
v.push_back(4);
std::ostream_iterator<int> output_iterator(std::cout, ",");
std::copy(v.begin(), v.end(), output_iterator);
}
input to std::vector<int>:
#include <iostream>
#include <vector>
#include <sstream>
using namespace std;
int main() {
std::vector<int> v;
int value;
std::string line;
while(getline(cin, line, ',')) {
std::stringstream ss(line);
ss >> value
v.push_back(value);
}
typedef std::vector<int>::iterator iter;
iter end = v.end();
for(iter it = v.begin(); it != end; ++it) {
std::cout << *it << endl;
}
}
this is only a mistake you did:
for (int j=0;j<v.size();i++)
{
cout << v.at(i) << " " ;
}
but the implement is too inefficient here:
for (int i=0;i<stringword.length();i++)
{
if (stringword.find(','))
{
int value;
istringstream (stringword) >> value;
v.push_back(value);
stringword.erase(0, stringword.find(','));
}
}
you may do like this, just a suggestion:
#include <iostream>
#include <string>
#include <vector>
#include <stdlib.h>
int ConvertStringToInt(const std::string &str, std::vector<int> &ints)
{
int count_int = 0;
std::string string_int;
size_t start = 0;
size_t end = 0;
while ((end = str.find(',', start)) != std::string::npos)
{
string_int.assign(str, start, end - start);
ints.push_back(atoi(string_int.c_str()));
start = end + 1;
++count_int;
}
if (start != str.size())
{
ints.push_back(atoi(str.c_str() + start));
++count_int;
}
return count_int;
}
int main(int argc, char *const argv[])
{
std::vector<int> ints;
std::string str = "123,456,789 ";
std::cout << ConvertStringToInt(str, ints) << std::endl;
for (size_t i = 0; i != ints.size(); ++i)
{
std::cout << ints[i] << std::endl;
}
return 0;
}
You can make your programs simpler:
#include <algorithm>
#include <fstream>
#include <iostream>
#include <iterator>
#include <vector>
// output
int main()
{
// my compiler doesn't support initializer lists yet :(
std::vector<int> v(4);
v[0] = 10;
v[1] = 200;
v[2] = 3000;
v[3] = 40000;
std::ofstream fout("mytestfile.txt");
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(fout, ","));
fout.close();
return 0;
}
// input
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<int> v;
std::ifstream fin("mytestfile.txt", std::ifstream::in);
fin.imbue(std::locale(std::locale(), new int_reader()));
std::copy(std::istream_iterator<int>(fin), std::istream_iterator<int>(), std::back_inserter<std::vector<int>>(v));
fin.close();
std::cout << "You read in: ";
std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, " "));
return 0;
}
Though this is handcrafted instead of using std::stringstream, I find it quite easy to understand.
std::vector<std::string> StringToVector (const std::string s,
const char token)
{
std::vector<std::string> v;
size_t posLast = 0, pos = 0;
while((pos = s.find(token, pos)) != std::string::npos)
{
if(s[pos] != s[posLast])
v.push_back(s.substr(posLast, pos - posLast));
posLast = ++pos;
}
if(s[posLast] != 0) // If there is no terminating token found
v.push_back(s.substr(posLast));
return v;
}
Demo with various test cases.
Related
The code is supposed to be able to count the characters in total then count each time they appear within a text file. I tried building a struct that makes an array which is an integer and char array at the same time so that I can have the counting in the same place as my array. But now I am stuck. I've looked online a lot but cannot find what I need to help me. Anyone got some advice? Also in the code if you see anything that should be changed I appreciate the tips! I am newer at c++ so go easy on me please.
Structs, multiple arrays, searching internet for answers
#include <iostream>
#include <fstream>
#include <string>
#include <algorithm>
struct letters {
int count;
char letter;
};
constexpr int SIZE = 10000;
std::string fileName, word;
int count = 0, charCount = 0;
int Alphabet[26];
letters chars[];
void getFileName(std::string& fileName);
int countWords(int& count, std::string& fileName, std::string word);
int countChar(int& charCount, std::string& fileName, letters chars[]);
void sortChars(letters chars[SIZE], int SIZE);
int main()
{
getFileName(fileName);
countWords(count, fileName, word);
countChar(charCount, fileName, chars);
sortChars(chars, SIZE);
return 0;
}
void getFileName(std::string& fileName)
{
std::cout << "Please enter the name of the file followed by the type (ex: text.txt) : " << std::endl;
std::getline(std::cin, fileName);
}
int countWords(int& count, std::string& fileName, std::string word)
{
count = 0;
std::ifstream infile(fileName);
while (infile >> word) {
count++;
}
std::cout << count << std::endl;
return count;
}
int countChar(int& charCount, std::string& fileName, letters chars[])
{
std::ifstream infile(fileName);
while (infile >> chars->letter) {
count++;
}
std::cout << charCount;
return charCount;
}
void sortChars(letters chars[SIZE], int SIZE)
{
int i = 0;
std::ifstream infile(fileName);
while (infile >> chars[i].letter) {
for (int i = 0; i <= chars->count; i++) {
if (infile == chars[i].letter) {
chars[i].count++;
}
}
}
}
void printCount()
{
std::cout << count << std::endl;
std::cout << charCount << std::endl;
std::ifstream infile(fileName);
}
The struct should count the number of times 'A' or 'a', should be able to convert to one case, but I can do this after it counts one or the other. My tester file is in all lowercase so that would be a good place to start.
Even bigger hint, use a std::unordered_map to count the characters:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
int main()
{
std::string file_name;
if (!std::getline(std::cin, file_name)) {
std::cerr << "Input error. :(\n\n";
return EXIT_FAILURE;
}
std::ifstream is{ file_name };
if (!is.is_open()) {
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return EXIT_FAILURE;
}
std::size_t num_words = 0;
std::unordered_map<char, std::size_t> char_counts;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
for (auto const &count : char_counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
std::cout << "Number of words: " << num_words << "\n\n";
} // when control reaches the end of main() without encountering a return-statement
// it has the same effect as return 0;
If you insist on splitting that few lines of code up into functions:
#include <cstdlib> // EXIT_FAILURE
#include <cctype> // std::isupper(), std::tolower()
#include <string> // std::string<>, std::getline()
#include <unordered_map> // std::unordered_map<>
#include <iostream> // std::ifstream
#include <fstream> // std::cout, std::cerr
std::string get_file_name()
{
std::cout << "Filename: ";
std::string file_name;
if (!std::getline(std::cin, file_name))
std::cerr << "Input error. :(\n\n";
return file_name;
}
std::ifstream open_file(std::string file_name)
{
std::ifstream file{ file_name };
if (!file.is_open())
std::cerr << "Couldn't open \"" << file_name << "\" for reading. :(\n\n";
return file;
}
std::size_t get_file_stats(std::istream &is, std::unordered_map<char, std::size_t> &char_counts)
{
std::size_t num_words = 0;
for (std::string word; is >> word; ++num_words) {
for (auto ch : word) {
if (std::isupper(ch))
ch = std::tolower(ch);
++char_counts[ch];
}
}
return num_words;
}
int main()
{
std::string file_name{ get_file_name() };
if (!file_name.length())
return EXIT_FAILURE;
std::ifstream is{ open_file(file_name) };
if (!is.is_open())
return EXIT_FAILURE;
std::unordered_map<char, std::size_t> counts;
std::cout << "Number of words: " << get_file_stats(is, counts) << "\n\n";
for (auto const &count : counts)
std::cout << "'" << count.first << "': " << count.second << '\n';
}
I've only found some answers to this problem in Python and JS, hopefully you can help me to do the same in c++.
So the challenge is to print out the first recurring character of a given string, here is what i came up with, but I don't know if this code actually looks good. This is my first time posting on StackOverflow, hopefully I'll get some feedback =)
#include <iostream>
#include <vector>
int main() {
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
// vector that stores characters that we will come across in the string
std::vector<char> seen(0);
for (char a : str) {
for (int i = 0; i < seen.size(); i++) {
if (a == seen[i]) {
std::cout << a << std::endl;
return 0;
} else { continue; }
}
seen.push_back(a);
}
std::cout << "none\n";
return 0;
}
For speed, how about:
#include <iostream>
int main() {
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
bool seen [256] = { };
for (char a : str) {
unsigned char u = (unsigned char) a;
if (seen [u]) {
std::cout << a << std::endl;
return 0;
}
seen [u] = true;
}
std::cout << "none\n";
return 0;
}
This is O(N), rather than O(N*N/2)
Live demo
For your task check out std::find:
void printRecurring(const std::string& str) {
std::string::const_iterator it = str.begin(), e = str.end();
for (std::string::const_iterator it2 = str.begin(); it2 != str.end(); ++it2) {
it = std::find(it + 1, e, *it2);
if (it != str.end()) {
std::cout << *it2 << std::endl;
return;
}
}
}
I think you can make it a little simpler by using std::find.
#include <iostream>
#include <vector>
#include <algoritm>
int main()
{
std::cout << "Enter some letters:\n";
std::string str;
std::cin >> str;
// vector that stores characters that we will come across in the string
std::vector<char> seen(0);
for (char a : str) {
auto it = std::find(seen.begin(), seen.end(), a);
if (it != seen.end()) {
std::cout << "Found it: " << *it << std::endl;
return 0;
}
seen.push_back(a);
}
std::cout << "none\n";
return 0;
}
I am creating a C++ program that reading a text file with contents
San Jose, 2, 10 , 1<br/>
Sunnyvale, 2, 5, 4<br/>
Gilroy, 8, 4, 3<br/>
Oakland, 5, 8, 9<br/>
mountain View, 7, 5, 12<br/>
Santa Clara, 6, 4, 6<br/>
Fremont, 1, 2, 0<br/>
Belmont, 4, 9, 5<br/>
My attempt is to store all the numbers in a matrix (8x3). Here is my code
int main () {
vector <vector <string> > data;
ifstream infile( "test.txt" );
int data_row = 0;
while (infile)
{
string s;
if (!getline( infile, s )) break;
data_row++;
istringstream ss( s );
vector <string> record;
while (ss)
{
string s;
if (!getline( ss, s, ',' )) break;
record.push_back( s );
}
data_column = record.size() - 1;
data.push_back( record );
}
if (!infile.eof())
{
cerr << "Fooey!\n";
}
cout << data_row << " " << data_column << "\n";
data_type** m_value;
m_value = new data_type*[data_row];
for(int i=0;i<data_row;i++) {
m_value[i] = new data_type[data_column];
}
vector<string>myvector;
for (int i = 0; i < data.size(); i++) {
for (int j = 0; j < data[i].size(); j++) {
cout << i << "****" << j << " " << data[i][j] << "\n ";
if ( j != 0) {
myvector.push_back(data[i][j]);
}
}
}
for(int i=0;i<data_row;i++) {
for(int j=0;j< data_column;j++) {
for (int k = 0; k < myvector.size(); k++) {
cout << k << " " << myvector[k] << "\n";
m_value[i][j] = myvector[k];
}
}}
The program fails with getline.cpp:57:24: error: cannot convert
'std::basic_string' to 'int' in assignment
m_value[i][j] = myvector[k];
Please help me to resolve the problem
Thank you
std::stoi converts a string to an integer. If you are using decimal numbers use std::stod. That means string to double m_value[i][j] = std::stoi(myvector[k]);
Please go and eat/read a good book on C++
#include <cstddef>
#include <cstdlib>
#include <iostream>
#include <iomanip>
#include <string>
#include <fstream>
#include <vector>
#include <iterator>
template<typename T, std::size_t N>
std::size_t sizeof_array(T(&)[N])
{
return N;
}
struct record
{
std::string name;
int a;
int b;
int c;
};
std::istream& operator>>(std::istream &is, record &r)
{
record tmp;
std::getline(is, tmp.name, ',');
char ch;
int *dst[] = { &tmp.a, &tmp.b, &tmp.c };
for (std::size_t i{}; i < sizeof_array(dst); ++i)
{
if(!( is >> *dst[i] ))
return is;
if (i < sizeof_array(dst) - 1)
is >> ch;
}
while (is.peek() != '\n' && is.peek() != EOF)
is.get();
is.get();
r = tmp;
return is;
}
std::ostream& operator<<(std::ostream &os, record const &r)
{
os << r.name << '\t' << r.a << '\t' << r.b << '\t' << r.c;
return os;
}
int main()
{
constexpr char const *input_file_name{ "input.txt" };
std::ifstream input_file{ input_file_name };
if (!input_file) {
std::cerr << "Failed to open \"" << input_file_name << "\" for reading!\n\n";
return EXIT_FAILURE;
}
std::vector<record> data{ std::istream_iterator<record>{input_file}, std::istream_iterator<record>{} };
for (auto const &d : data)
std::cout << d << '\n';
}
I am trying to implement an algorithm that will take a set of numbers and output the largest possible number (without breaking up the individual numbers). So in an example like this where I give 4 numbers:
4
43 12 3 91
The output would be
91-43-3-12 or 9143312.
My attempt is below.
#include <algorithm>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>
using std::vector;
using std::string;
bool compare (int x, int y) {
std::cout << "in func \n";
string a = std::to_string(x);
string b = std::to_string(y);
std::cout << a << " " << b << "\n";
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
if (std::stoi(a.substr(0, 1)) < std::stoi(b.substr(0, 1))) {
std::cout.flush();
std::cout << "if \n";
return true;
}
else {
std::cout.flush();
std::cout <<"else \n";
return false;
}
}
string largest_number(vector<string> a) {
std::stringstream ret;
while (a.size() > 0) {
int maxNumber =-1;
int index = -1;
std::cout << "going into for " << a.size() << "\n";
for (size_t i = 0; i < a.size(); i++) {
if (! compare (stoi(a[i]), maxNumber ) ) { //stoi(a[i]) >= maxNumber) {
maxNumber = stoi(a[i]);
std::cout << maxNumber << " " << i << "\n";
index = i;
}
std::cout << "here \n";
}
ret << maxNumber;
a.erase(a.begin() + index);
}
string result;
ret >> result;
return result;
}
int main() {
int n;
std::cin >> n;
vector<string> a(n);
for (size_t i = 0; i < a.size(); i++) {
std::cin >> a[i];
}
std::cout << largest_number(a);
}
I do not understand what is wrong with my compare function. When I run it, say with this input:
$ g++ -pipe -O2 -std=c++14 largest_number.cpp -lm -o largest1
$ ./largest1.exe
4
4 23 1 45
going into for 4
in func
4 -1
It doesnt print the cout statements in the conditional if or else. How could this be possible? I even tried flushing. However, if I take the entire conditional out, put a cout statement and the return true or something, then it runs the program in entirety (although this is not the expected output).
I do not mind harsh criticism. What am I doing wrong here? Any advice will be appreciated.
Thanks in advance.
In this statement
std::cout << std::stoi(a.substr(0, 1)) << " " << std::stoi(b.substr(0, 1)) << "\n" ;
when b is equal to -1 the expression b.substr(0, 1) is equal to an object of type std::string that contains one character '-' that is the minus sign.
If to apply the standard function std::stoi to such a string then an exception will be thrown.
Consider the following code snippet
std::string s("-");
try
{
std::stoi(s);
}
catch (const std::exception &e)
{
std::cout << e.what() << std::endl;
}
Its output will be
invalid stoi argument
It seems what you need is just to sort the strings. For example
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
std::vector<std::string> v { "4", "23", "1", "45" };
auto cmp = [](const std::string &a, const std::string &b)
{
std::string::size_type i = 0, m = a.size();
std::string::size_type j = 0, n = b.size();
int result;
do
{
if (m < n)
{
result = a.compare(i, m, b, j, m);
j += m;
n -= m;
}
else
{
result = a.compare(i, n, b, j, n);
i += n;
m -= n;
}
} while (result == 0 && m && n);
return 0 < result;
};
std::sort(v.begin(), v.end(), cmp);
for (const auto &s : v) std::cout << s;
std::cout << std::endl;
return 0;
}
The output of the program will be
454231
Or for this set of numbers
std::vector<std::string> v{ "43", "12", "3", "91" };
the output will be
9143312
or for one more set of numbers
std::vector<std::string> v{ "93", "938" };
the output will be
93938
I made a program that takes data from file, puts it into vector and then checks for most frequent element in the vector. (using map)
The problem is when I have same number of elements in the data (two Element1, two Element2, one Element3). It returns Element1 and I need it to pass the information that there is "no most frequent element".
My code looks like:
using namespace std;
bool comp(const pair<string, unsigned long> &pair1,
const pair<string, unsigned long> &pair2) {
return pair1.second < pair2.second;
}
string Odczyt::tokenizer() {
inFile.open("baza.txt");
while (!inFile.eof()) {
for (int i = 0; i < 4; i++) {
inFile >> row1[i] >> row2[i] >> row3[i] >> row4[i];
}
}
sVector1.assign(row1, row1 + 3);
string w1 = most_occurred(sVector1);
return w1;
}
string Odczyt::most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
for (vector<string>::const_iterator it = vec.begin(); it != vec.end();
++it) {
++str_map1[*it];
}
return max_element(str_map1.begin(), str_map1.end(), comp)->first;
}
Create a variable which stores the number of times you have found an element which occurs m times (where m is the current maximum number of times any element has occurred). If at the termination point of the algorithm you have more than one element appearing m times, then you know there is no single most-frequently-occurring element.
#include <iostream>
#include <string>
#include <vector>
#include <map>
using namespace std;
string most_occurred(vector<string> &vec) {
map<string, unsigned long> str_map1;
std::string max_element = "";
int max_count = 0;
typedef vector<string>::const_iterator iter;
iter end = vec.end();
for (iter it = vec.begin(); it != end; ++it) {
int count = ++str_map1[*it];
if(count == max_count) max_element = "no max found";
if(count > max_count) {
max_count = count;
max_element = *it;
}
}
return max_element;
}
int main() {
std::string arr1[5] = {"aa" , "bb", "cc", "dd", "ee"}; // no max found
std::string arr2[5] = {"aa" , "aa", "cc", "dd", "ee"};// aa
std::string arr3[5] = {"aa" , "aa", "cc", "cc", "ee"}; // no max found
std::vector<std::string> input1(arr1, arr1+5);
std::vector<std::string> input2(arr2, arr2+5);
std::vector<std::string> input3(arr3, arr3+5);
std::cout << most_occurred(input1) << std::endl;
std::cout << most_occurred(input2) << std::endl;
std::cout << most_occurred(input3) << std::endl;
}
the result is:
no max found
aa
no max found
The following test resulted in no max found.
int main() {
std::string arr1[24] = {"Element1", "Element2", "Element33", "1",
"Element1", "Element2", "Element33", "2", "Element11", "Element2",
"Element33", "2", "Element11" "Element21" "Element31", "2", "Element11",
"Element21", "Element31", "1", "Element12", "Element21", "Element31",
"1"}; // no max found
std::vector<std::string> input1(arr1, arr1+24);
std::cout << most_occurred(input1) << std::endl;
}
If the above code returns std::string("") then there was no max element, else it will return the max.
This is a frequent operation here is my sample code:
#include <iostream>
#include <algorithm>
#include <vector>
#include <map>
#include <iterator>
using namespace std;
int main(int argc, char* argv[]) {
// number -> frequency
map<int, int> idfreq = {{1, 3}, {2, 10}, {3,8}, {9, 15}, {7,30}};
vector<pair<int, int> > v;
copy(idfreq.begin(), idfreq.end(), back_inserter(v));
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
make_heap(v.begin(), v.end(), [](const pair<int,int> &a, const pair<int,int> &b){ return a.second < b.second; });
// with -std=c++14
//make_heap(v.begin(), v.end(), [](auto& a, auto& b){ return a.second < b.second; });
cout << v.front().first << " " << v.front().second << " most frequent element\n";
cout << "after make heap call\n";
for (auto& el : v) {
cout << el.first << " " << el.second << endl;
}
cout << endl;
return 0;
}