I am currently trying to separate a string by the number 2 and pushing the sub characters that i get into a 2d vector, the problem is that every time I try, I get a segmentation fault when I try to push the second row of characters in the vector. After trying a few things, I think the problem lies in the vector "some" after I clear the content of the vector. It seems to me that after the clearing, I am no longer able to push values into the vector. I hope that somebody has any suggestions because I am stuck.
std::string str = "11121112111";
std::vector<int> some;
std::vector<std::vector<int> > somemore;
for (unsigned int i = 0; i < str.length(); i++)
{
if (str[i] == '2')
{
somemore.push_back(some);
some.clear();
}
else
{
some.push_back(1);
}
}
for (unsigned int i = 0; i <= 3; i++)
{
for (unsigned int j = 0; j <= 3; j++)
{
std::cout << somemore[i][j] << std::endl;
}
}
With c++11 and Boost you can make a much more elegant solution, without the need for loops with an incrementing index.
#include <vector>
#include <string>
#include <iostream>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/classification.hpp>
int main()
{
std::string str = "11121112111";
std::vector<std::string> string_vector;
boost::split(string_vector, str, boost::is_any_of("2"));
std::vector<std::vector<int>> int_vector;
for (auto& s : string_vector)
int_vector.push_back(std::vector<int>(s.size(), 1));
for (auto& v : int_vector)
for (auto& i : v)
std::cout << i << std::endl;
return 0;
}
I would change the last part:
for(unsigned int i = 0; i <=3; i++)
{
for(unsigned int j = 0; j <=3; j++)
{
std::cout << somemore[i][j] << std::endl;
}
}
Into this:
for(unsigned int i = 0; i < somemore.size(); i++)
{
for(unsigned int j = 0; j < some.size(); j++)
{
std::cout << somemore[i][j] << std::endl;
}
}
It is much safer.
As I already mentioned in comments, you have two problems in your code:
You are not pushing the last some into somemore because there is no 2 at the end of str.
Your last loops are too large - You have a 3x3 matrix but you expect a 4x4 since you go from 0 to 3.
By the way, since you are only counting ones, you don't need some:
std::string str = "11121112111";
std::vector<std::vector<int>> somemore;
size_t count = 0;
for (size_t = 0; i < str.length(); i++) {
if (str[i] == '2') {
somemore.push_back(std::vector<int>(count, 1));
count = 0;
}
else {
++count;
}
}
for (size_t i = 0; i < somemore.size(); ++i) {
for (size_t j = 0; j < somemore[i].size(); ++j) {
std::cout << somemore[i][j] << std::endl;
}
}
You could also replace the last two loops with iterators, or if you have c++11 available:
for (const auto &s: somemore) {
for (const auto &v: s) {
std::cout << v << std::endl;
}
}
In this loop
for(unsigned int i = 0; i < str.length(); i++)
{
if(str[i] == '2')
{
sommore.push_back(som);
som.clear();
}
else
{
som.push_back(1);
}
}
where it is not clear whether som is the vector declared like
std::vector<int> some;
^^^^^
the last part of the string
std::string str = "11121112111";
^^^
is ignored by vector sommore. So the vector contains only two elements that corresponds to two 2(s) in the string.
As result these loops
for(unsigned int i = 0; i <=3; i++)
{
for(unsigned int j = 0; j <=3; j++)
{
std::cout << sommore[i][j] << std::endl;
}
}
that use the magic number 3 have undefined behaviour.
Even if the vector and its sub-vectors contain 3 elements even in this case conditions i <=3 and j <=3 are wrong.
You can adopt the following approach shown in this demonstratrive program
#include <iostream>
#include <string>
#include <vector>
int main()
{
std::vector<std::vector<int>> v;
std::string str = "11121112111";
for ( std::string::size_type pos = 0; ( pos = str.find_first_not_of( "2", pos ) ) != std::string::npos; )
{
auto n = str.find( "2", pos );
if ( n == std::string::npos ) n = str.size();
v.push_back( std::vector<int>( n - pos, 1 ) );
pos = n;
}
for ( const auto &row : v )
{
for ( int x : row ) std::cout << x;
std::cout << std::endl;
}
}
The program output is
111
111
111
Related
I am trying to figure out why my function for dilating an image doesn't produce the correct output.
My goal is to turn something like this:
.........
.........
....x....
.........
.........
into this:
.........
....x....
...xxx...
....x....
.........
for each cycle of dilation.
I haven't thought of it but I also need to to the reverse for the erosion.
This is what I've come up with so far (the program takes in input from the user in the command line using argv) :
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
//look up line by line parsing
using namespace std;
void replacee(vector<vector<char>> &vec, char oldd, char neww)
{
for (vector<char> &v : vec) // reference to innver vector
{
replace(v.begin(), v.end(), oldd, neww); // standard library
algorithm
}
}
void dialationn(vector<vector<char>> & vec, char suspect)
{
for (int i = 0; i < vec.size(); i ++) {
for (int j = 0; j < vec[i].size(); j++) {
if (vec[i][j] == suspect) {
if (i > 0) {
vec[i-1][j] = suspect;
}
if (j > 0) {
vec[i][j-1] = suspect;
}
if (i + 1<vec.size()) {
vec[i+1][j] = suspect;
}
if (j + 1<vec[i].size()) {
vec[i][j+1] = suspect;
}
}
}
}
}
int main(int argc, char* argv[]) {
fstream fin; char ch;
string name (argv[1]); //File Name.
vector<vector<char>> data;
// 2D Vector.
vector<char> temp;
// Temporary vector to be pushed
// into vec, since its a vector of vectors.
fin.open(name.c_str(),ios::in);
// Assume name as an arbitrary file.
string argument2 (argv[2]);
string argument3 (argv[3]);
string argument4 (argv[4]);
while(fin)
{
ch = fin.get();
if(ch!='\n') {
temp.push_back(ch);
}
else
{
data.push_back(temp);
temp.clear();
}
}
if (argument2 == "replace") {
replacee(data, argument3[0], argument4[0]);
for (int i = 0; i < data.size(); i ++) {
for (int j = 0; j < data[i].size(); j++) {
cout << data[i][j];
}
cout << endl;
}
} else if (argument2 == "dialate") {
dialationn(data, argument3[0]);
for (int i = 0; i < data.size(); i ++) {
for (int j = 0; j < data[i].size(); j++) {
cout << data[i][j];
}
cout << endl;
}
}
fin.close();
}
the dialationn function I've implemented so far uses a double for loop to cycle through the 2d array, and when it finds the character that is supposed to be dilated, it checks if a border is near by and sets the coordinate accordingly.
Besides the input parsing issue discussed in the comments to the question, the dilation function proposed by OP doesn't work because it modifies the input image, rather than writing to a new output image. When modifying the input, the result of the dilation for subsequent pixels will be affected.
Correct would be:
void dialationn(vector<vector<char>> & vec, char suspect)
{
vector<vector<char>> out(vec.size(), vector<char>(vec[0].size(), 0))
for (int i = 0; i < vec.size(); i ++) {
for (int j = 0; j < vec[i].size(); j++) {
if (vec[i][j] == suspect) {
if (i > 0) {
out[i-1][j] = suspect;
}
if (j > 0) {
out[i][j-1] = suspect;
}
if (i + 1<vec.size()) {
out[i+1][j] = suspect;
}
if (j + 1<vec[i].size()) {
out[i][j+1] = suspect;
}
}
}
}
swap(out, vec);
}
I need to loop over vector of vector of strings in the same manner as I would do this on this example with integers:
int main()
{
vector<vector<int>> stuff;
//fill the inner vector, then insert it into the outer vector
for (int i = 0; i < 999; i++)
{
vector<int>temp;
for (int j = 0; j < 9; j++)
{
temp.push_back(i);
++i;
}
stuff.push_back(temp);
}
//display all elements ...
for (int i = 0; i < stuff.size(); i++)
{
for (int j = 0; j < stuff[i].size(); j++) {
cout << stuff[i][j] << "\t";
}
cout << endl;
}
}
But strings require different approach as they are more complex,
Here I`m iterating over 1-Dimensional string:
vector<string> first_arr = {};
string line;
ifstream myfile("source.txt");
if (myfile.is_open())
{
while (getline(myfile, line))
{
first_arr.push_back(line); //READ from file
}
myfile.close();
}
else cout << "Unable to open file";
But I have completely stuck on going into the inner circle.
Also, I am expecting strings of very different length
I was not using c++ for a while so, please forgive my question if it seems too obvious to you,
Here's an example with three vectors of strings of sizes 5, 10, and 15. This examples uses C++11's range-based for loop to print the vectors.
Code:
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
int main()
{
using SList = std::vector< std::string >;
using VList = std::vector< SList >;
VList vlist;
for ( int i = 5; i <= 15; i += 5 )
{
SList slist { i };
std::fill( slist.begin(), slist.end(), "Test" );
vlist.push_back( slist );
}
for ( const auto& v : vlist )
{
std::cout << "{ ";
for ( const auto& s : v )
{
std::cout << s << ' ';
}
std::cout << "}\n";
}
return 0;
}
Output:
{ Test Test Test Test Test }
{ Test Test Test Test Test Test Test Test Test Test }
{ Test Test Test Test Test Test Test Test Test Test Test Test Test Test Test }
Here's the live example on Ideone: http://ideone.com/PyYD5p
You can use the same logic.
Unless you want to print every string one letter at a time.
#include <string>
#include <iostream>
#include <vector>
using std::vector;
int main()
{
vector<vector<std::string> > vec;
std::string tmp;
for(int i = 0; i < 2; ++i)
{
vector<std::string> v;
for(int j = 0; j < 9; ++j)
{
std::cin >> tmp;
v.push_back(tmp);
}
vec.push_back(v);
}
for(int i = 0; i < vec.size(); ++i)
{
for(int j = 0; j < vec[i].size(); ++j)
{
std::cout << vec[i][j] << "\t";
}
std::cout << std::endl;
}
return 0;
}
If you want to do the c++11 way, you could replace the last loop for this snippet:
for(const auto &subVec : vec)
{
for(const auto &str : subVec)
{
std::cout << str << "\t";
}
std::cout << std::endl;
}
Hello I am looking for a way to write this C++ Code in a general way, so that if a want 20 columns I will not have to write 20 for loops:
for(int i=1; i<6; i++) {
for(int j=i; j<6; j++) {
for(int k=j; k<6; k++) {
for(int m=k; m<6; m++) {
std::cout << i << j << k << m << std::endl;
}
}
}
}
It is important that my numbers follow a >= Order.
I am very grateful for any help.
This recursive function should work:
#include <iostream>
bool inc( int *indexes, int limit, int n )
{
if( ++indexes[n] < limit )
return true;
if( n == 0 ) return false;
if( inc( indexes, limit, n-1 ) ) {
indexes[n] = indexes[n-1];
return true;
}
return false;
}
int main()
{
const size_t N=3;
int indexes[N];
for( size_t i = 0; i < N; ++i ) indexes[i] = 1;
do {
for( size_t i = 0; i < N; ++i ) std::cout << indexes[i] << ' ';
std::cout << std::endl;
} while( inc( indexes, 6, N-1 ) );
return 0;
}
live example
The design here is simple. We take a std::vector each containing a dimension count and a std::vector containing a current index at each dimension.
advance advances the current bundle of dimension indexes by amt (default 1).
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
return;
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which gives us an advance function for generic n dimensional coordinates.
Next, a filter that tests the restriction you want:
bool vector_ascending( std::vector<size_t> const& v ) {
for (size_t i = 1; (i < v.size()); ++i) {
if (v[i-1] < v[i]) {
return false;
}
}
return true;
}
then a for loop that uses the above:
void print_a_lot( std::vector<size_t> counts ) {
for( std::vector<size_t> v(counts.size()); v < counts; advance(v,counts)) {
// check validity
if (!vector_ascending(v))
continue;
for (size_t x : v)
std::cout << (x+1);
std::cout << std::endl;
}
}
live example.
No recursion needed.
The downside to the above is that it generates 6^20 elements, and then filters. We don't want to make that many elements.
void advance( std::vector<size_t>& indexes, std::vector<size_t> const& counts, size_t amt=1 ) {
if (indexes.size() < counts.size())
indexes.resize(counts.size());
for (size_t i = 0; i < counts.size(); ++i ) {
indexes[i]+=amt;
if (indexes[i] < counts[i])
{
size_t min = indexes[i];
// enforce <= ordering:
for (size_t j = i+i; j < counts.size(); ++j) {
if (indexes[j]<min)
indexes[j]=min;
else
break; // other elements already follow <= transitively
}
assert(vector_ascending(indexes));
return;
}
assert(counts[i]!=0);
amt = indexes[i]/counts[i];
indexes[i] = indexes[i]%counts[i];
}
// past the end, don't advance:
indexes = counts;
}
which should do it without the vector_ascending check in the previous version. (I left the assert in to do testing).
This function works for me, but do not call it with 20 if you want it to finish.
#include <list>
#include <iostream>
std::list<std::list<int>> fun (std::list<std::list<int>> inputlist, int counter)
{
if(counter == 0)
{
return inputlist;
}
else
{
std::list<std::list<int>> outputlist;
for(std::list<int> oldlist : inputlist)
{
for(int i = 1; i<6; i++)
{
std::list<int> newlist = oldlist;
newlist.push_back(i);
outputlist.push_back(newlist);
}
}
return fun(outputlist, counter - 1);
}
}
int main()
{
std::list<int> somelist;
std::list<std::list<int>> listlist;
listlist.push_back(somelist);
std::list<std::list<int>> manynumbers = fun (listlist,5);
for (std::list<int> somenumbers : manynumbers)
{
for(int k : somenumbers)
{
std::cout<<k;
}
std::cout<<std::endl;
}
return 0;
}
Same with Processing (java) here :
void loopFunction(int targetLevel, int actualLevel, int min, int max, String prefix){
/*
targetLevel is the wanted level (20 in your case)
actualLevel starts from 1
min starts from 1
max is the max number displayed (6 in your case)
prefix starts from blank
see usage bellow (in setup function)
*/
for(int m=min; m<max; m++) {
if(targetLevel==actualLevel)
{
println(prefix+ " " + m);
}
else
{
loopFunction(targetLevel, actualLevel+1,m,max,prefix+ " " + m);
}
}
}
void setup(){
loopFunction(10,1,1,6,"");
}
Well, I am not the fastest in writing answer... when I started there was no other answer. Anyhow, here is my version:
#include <iostream>
#include <vector>
using namespace std;
class Multiindex {
public:
typedef std::vector<int> Index;
Multiindex(int dims,int size) :
dims(dims),size(size),index(Index(dims,0)){}
void next(){
int j=dims-1;
while (nextAt(j) && j >= 0){j--;}
}
Index index;
bool hasNext(){return !(index[0]==size-1);}
private:
bool nextAt(int j){
index[j] = index[j]+1;
bool overflow = (index[j]==size);
if (!overflow && j < dims-1){std::fill(index.begin() + j + 1,index.end(),index[j]);}
return overflow;
}
int dims;
int size;
};
int main() {
Multiindex m(4,6);
while (m.hasNext()){
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
m.next();
}
cout << m.index[0] << m.index[1] << m.index[2] << m.index[3] << endl;
return 0;
}
If I want to get the Cartesian Product of these two vector<string>s:
vector<string> final{"a","b","c"};
vector<string> temp{"1","2"};
But I want to put the result in final, such that final would contain:
a1
a2
b1
b2
c1
c2
I'd like to do this without creating a temporary array. Is it possible to do this? If it matters, the order of final is not important.
You may try the following approach
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> final{ "a", "b", "c" };
std::vector<std::string> temp{ "1", "2" };
auto n = final.size();
final.resize( final.size() * temp.size() );
for ( auto i = n, j = final.size(); i != 0; --i )
{
for ( auto it = temp.rbegin(); it != temp.rend(); ++it )
{
final[--j] = final[i-1] + *it;
}
}
for ( const auto &s : final ) std::cout << s << ' ';
std::cout << std::endl;
return 0;
}
The program output is
a1 a2 b1 b2 c1 c2
Try the function cartesian:
#include <vector>
#include <string>
using namespace std;
void cartesian(vector<string>& f, vector<string> &o) {
int oldfsize = f.size();
f.resize(oldfsize * o.size());
for (int i = o.size() - 1; i>=0; i--) {
for (int j = 0; j < oldfsize; j++) {
f[i*oldfsize + j] = f[j] + o[i];
}
}
}
int main()
{
vector<string> f{"a","b","c"};
vector<string> temp{"1","2"};
cartesian(f, temp);
for (auto &s: f) {
printf("%s\n", s.c_str());
}
}
This works for me:
void testCartesianString(vector<string>& final,
vector<string>const& temp)
{
size_t size1 = final.size();
size_t size2 = temp.size();
// Step 1.
// Transform final to : {"a","a","b","b","c","c"}
final.resize(size1*size2);
for ( size_t i = size1; i > 0; --i )
{
for ( size_t j = (i-1)*size2; j < i*size2; ++j )
{
final[j] = final[i-1];
}
}
// Step 2.
// Now fix the values and
// change final to : {"a1","a2","b1","b2","c1","c2"}
for ( size_t i = 0; i < size1; ++i )
{
for ( size_t j = 0; j < size2; ++j )
{
final[i*size2+j] = final[i*size2+j] + temp[j];
cout << final[i*size2+j] << " ";
}
cout << endl;
}
}
This is just a personal preference option to Vald from Moscow's solution. I think it may be faster for dynamic arrays because there would be less branching. But I haven't gotten around to writing a timing test bench.
Given the inputs vector<string> final and vector<string> temp:
const auto size = testValues1.first.size();
testValues1.first.resize(size * testValues1.second.size());
for (int i = testValues1.first.size() - 1; i >= 0; --i){
testValues1.first[i] = testValues1.first[i % size] + testValues1.second[i / size];
}
EDIT:
Nope, this solution is slower not faster: http://ideone.com/e.js/kVIttT
And usually significantly faster, though I don't know why...
In any case, prefer Vlad from Moscow's answer
For starters, total C++ and coding noob here, apologies in advance. I've been working on a program that creates a concordance of a text file with the number of times a word occurs and on what lines the word occurs on. Brief example of the intended output:
A occurs 9 time(s) on lines 1 3 5
AND occurs 3 time(s) on lines 2 4
I first wrote the program using only arrays, which I've got running successfully. I'm now trying to rewrite it using vectors instead of arrays, and basically I have no idea what I'm doing past declaring the vectors. I've got my vector version to compile and link without errors, but when I run it I get a "segmentation fault 11" error. From what I understand, the reason this error is occurring because I'm trying to access memory that hasn't been allocated yet. I'm pasting my entire code that I've written so far below. If someone can help me out, or point me in the right director of what I need to do to make this happen, that'd be so awesome. I know I'll need to push the push_back method, but I just have no idea where. I realize this probably rudimentary to most of you, but I'm just trying to wrap my head around all of this. Again, thanks so much -
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
using namespace std;
void copy(vector<int> fromarr, vector< vector<int> > toarr, int index)
{
for (int i = 0; i <= fromarr[0]; i++)
{
toarr[index][i] = fromarr[i];
}
}
void copy(vector< vector<int> > fromarr, vector<int> toarr, int index)
{
for (int i = 0; i <= fromarr[index][0]; i++)
{
toarr[i] = fromarr[index][i];
}
}
int search(vector<string> array, int len, string target)
{
for(int i = 0; i < len; i++)
{
if(array[i] == target) return i;
}
return -1;
}
void sort(vector<string> wordarray, vector<int> linecount, vector< vector<int> > linenumbersarray, int length)
{
int minpos = 0;
for(int i = 0; i < length; i++)
{
minpos = i;
for (int j = 0; j < length; j++)
{
if(wordarray[j] > wordarray[minpos]) minpos = j;
string tempword = wordarray[i];
int tempcount = linecount[i];
vector<int> tempnums;
copy(linenumbersarray, tempnums, i);
wordarray[i] = wordarray[minpos];
linecount[i] = linecount[minpos];
copy(linenumbersarray[minpos], linenumbersarray, i);
wordarray[minpos] = tempword;
linecount[minpos] = tempcount;
copy(tempnums, linenumbersarray, minpos);
}
}
}
int main(int argc, char* argv[])
{
vector<string> wordarray;
vector<int> linecount;
vector< vector<int> > linenumbersarray;
int arrayposition = 0;
int linenumber = 1;
int wordlength = 0;
ifstream infile;
infile.open(argv[1]);
string aline;
while (getline(infile, aline))
{
istringstream theline(aline);
string aword;
while (theline >> aword)
{
int isupdated = search(wordarray, wordlength, aword);
if (isupdated == -1)
{
wordarray[wordlength] = aword;
linecount[wordlength] = 1;
linenumbersarray[wordlength][0] = 1;
linenumbersarray[wordlength][1] = linenumber;
wordlength = wordlength + 1;
}
else
{
linecount[isupdated] = linecount[isupdated] + 1;
if (linenumbersarray[isupdated][linenumbersarray[isupdated][0]] != linenumber)
(linenumbersarray[isupdated][++linenumbersarray[isupdated][0]] = linenumber);
}
}
linenumber = linenumber + 1;
}
sort(wordarray, linecount, linenumbersarray, wordlength);
for (int i = 0; i < wordlength; i++)
{
ostringstream out;
for (int j = 1; j <= linenumbersarray[i][0]; j++)
{
out << linenumbersarray[i][j];
j != linenumbersarray[i][0] ? out << " " : out << ".";
}
cout << wordarray[i] << " occurs " << linecount[i] << " time(s) on lines " << out.str() << endl;
out.flush();
}
}
How do you populate your vectors? Use push_back function to fill them in.
vector<int> v; // an empty container
v.push_back(10); // now it has one element - an integer 10
Use size() function to access a vector size, do not pass length parameter as you do in few functions (sort, search).
Another way to iterate through an stl container (vector is a container) is to use iterators.
for (vector<int>::iterator it = v.begin(); it != v.end(); ++it)
{ int a = *it; /*gives you an element of the container*/ }
Using size or iterators will prevent you from accessing unallocated memory - this is your problem.
Do not use operator [] without checking vector boundary.
if (i < v.size()) {v[i]; //an element}
Here are two variants of your search function
int search(vector<string> const &array, string const &target)
{
for(int i = 0; i < array.size(); i++)
{
if(array[i] == target) return i;
}
return -1;
}
vector<string>::const_iterator search(vector<string> const &array, string const &target)
{
for(vector<string>::const_iterator it = array.begin(); it != array.end(); ++it)
{
if(*it == target) return it;
}
return array.end();
}
A better way of searching is to use std::find function, but you may leave that for later when you are more comfortable with STL. std::find does the same as second variant of search above.
vector<string>::iterator it;
it = find (myvector.begin(), myvector.end(), target);
if (it != myvector.end())
std::cout << "Element found in myvector: " << *it << '\n';
else
std::cout << "Element not found in myvector\n";