I am trying to pass a string and and an empty set into my function. Then I would like to call the function in my main and print all of the elements in the set.
This is my function code:
#include<iostream>
using std::cout; using std::endl;
#include<algorithm>
using std::set_union; using std::copy;
#include<iterator>
using std::inserter; using std::ostream_iterator;
#include<string>
using std::string;
#include<set>
using std::set;
void removing(const string &word, set<string> &result) {
string del_word = word;
char erased_l;
for(int i = 0; i < del_word.length(); i++) {
erased_l = word[i];
del_word.erase(0, 1);
del_word = erased_l + del_word;
}
}
Below is my main code where I call the function:
int main (){
set<string> jump = {};
set<string> del = removing("axiom", jump);
for (string ele:del) {
cout << ele << endl;
}
}
I get the following error:
No viable conversion from 'void' to 'set<std::__1::string>' (aka 'set<basic_string<char, char_traits<char>, allocator<char> > >')
The error is in line 16:
set<string> del = removing("axiom", jump);
My code is trying to accomplish:
If I pass in axiom, then I would like my string set to have {xiom, aiom, axom, axim, axio}. So remove first letter, keep rest of the word. Then remove second letter, keep rest of the word, etc...
Primary issues include:
The return value of a void function can't be assigned to a set, hence your compiler error. Your design is to pass a reference to an empty result set into the removing function and have it populated with the result data, so you can remove the assignment here.
Nothing is added to your result inside your removing function, so it starts empty and ends empty after the function call.
Here's a working version:
void removing(const string &word, set<string> &result) {
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
}
int main () {
set<string> jump = {};
removing("axiom", jump);
for (string ele : jump) {
cout << ele << endl;
}
}
Output:
aiom
axim
axio
axom
xiom
Having said that, it's not clear to me why result should be a parameter to the function. If you're only planning on using it to store this particular result, this design seems much cleaner from the perspective of the caller:
set<string> removing(const string &word) {
set<string> result;
for (int i = 0; i < word.length(); i++) {
result.insert(word.substr(0, i) + word.substr(i + 1, word.length()));
}
return result;
}
int main () {
set<string> jump = removing("axiom");
for (string ele : jump) {
cout << ele << endl;
}
}
Try it!
Related
Trying to learn datastructures, I made this class for a stack. It works just fine with integers but it throws a mysterious error with strings.
The class List is the API for my stack. Its meant to resize automatically when it reaches the limit. The whole code is just for the sake of learning but the error I get doesn't make any sense and it happens somewhere in some assembly code.
#include <iostream>
#include<string>
using namespace std;
class List {
private:
int N = 0;
string* list = new string[1];
void resize(int sz) {
max = sz;
string* oldlist = list;
string* list = new string[max];
for (int i = 0; i < N; i++) {
list[i] = oldlist[i];
}
}
int max = 1;
public:
void push(string str) {
if (N == max) {
resize(2 * N);
}
cout << max << endl;
list[N] = str;
N++;
}
void pop() {
cout << list[--N] << endl;
}
};
int main()
{
string in;
List list;
while (true) {
cin >> in;
if (in == "-") {
list.pop();
}
else {
list.push(in);
}
}
}
string* list = new string[max]; in the resize method defines a new variable named list that "shadows", replaces, the member variable list. The member list goes unchanged and the local variable list goes out of scope at the end of the function, losing all of the work.
To fix: Change
string* list = new string[max];
to
list = new string[max];
so that the function will use the member variable.
Don't forget to delete[] oldlist; when you're done with it to free up the storage it points at.
I've recently read up on STL functions in C++. I understand the basic uses of the functions, but I am struggling getting them to use member variables of a struct.
I have this struct:
struct Apples
{
double weight; // oz
string color; // red or green
void print() const { cout << color << ", " << weight << endl; }
};
Basically, I insert Apples into a vector storing random weights and random color. Now, I want to use a count_if function to determine how many apples are greater than a given weight. I want to convert a function like this:
int cnt = 0;
for(auto it = crate.cbegin(); it != crate.cend(); ++it)
if(it->weight > toFind)
cnt++;
to a count_if() version (this does not work):
int cnt = count_if(crate.begin(), crate,end(), isGreater())
With isGreater() being like this:
void isGreater()
{
if(it->weight > toFind)
return it->weight > toFind;
}
What I don't understand about STL functions and a struct is how to use the member variables inside of the struct with the STL functions. I'm not sure what to pass inside of the STL function, either. Would it be better to use a lambda function in this case? If so, why?
Here is all the current code, if it doesn't make sense:
#include <iostream>
#include <ctime>
#include <cstdlib>
#include <vector>
#include <deque>
#include <string>
using namespace std;
struct Apples
{
double weight; // oz
string color; // red or green
void print() const { cout << color << ", " << weight << endl; }
};
void isGreater()
{
if(it->weight > toFind)
return it->weight > toFind;
}
int main()
{
srand(time(nullptr));
const double minWeight = 8.;
const double maxWeight = 3.;
cout << "Input crate size: ";
int size;
cin >> size;
vector <Apples> crate(size);
for(auto it = crate.begin(); it != crate.end(); ++it)
{
it->weight = minWeight + static_cast<double>(rand())/RAND_MAX*(maxWeight - minWeight);
it->color = rand() % 2 == 1 ? "green" : "red";
}
cout << "Enter weight to find: ";
double toFind;
cin >> toFind;
//this is what I want to convert to count if
int cnt = 0;
for(auto it = crate.cbegin(); it != crate.cend(); ++it)
if(it->weight > toFind)
cnt++;
std::count_if takes unary predicate as the third argument. In this case unary predicate is a function taking one object and returning true if object matches find criterion or false if not.
Since your criterion depends on toFind, it seems more laconic to use lambda capturing toFind:
int cnt = count_if(crate.begin(), crate.end(), [toFind](const Apple& apple) {
return it->weight > toFind;
});
If you want a standalone function, you can use:
bool isGreater(double toFind, const Apple& apple) {
return it->weight > toFind;
}
...
int cnt = count_if(crate.begin(), crate.end(),
std::bind(&isGreater, toFind, std::placeholders::_1));
Note, that you don't need to call function, you need to pass it:
int cnt = count_if(crate.begin(), crate,end(), isGreater())
// ^^ remove parentheses
you are not storing the apples in the vector.
you have to initialize inside a loop each apple and then store them in the vector.
crate.push_back(newApple).
so run a loop from 0 to size.
inside that loop initialize new apples and give them weights and colors
then push_back in vector:
for(int i = 0; i < size ++i)
{
apples newApple;
newApple.weight = ...;
newApple.color = ...;
crate.push_back(newApple);
}
This is usually accomplished by creating a "functor" class, a class whose objects can be called like a function. Each instance call hold the reference weight:
struct IsGreater {
double w;
IsGreater(double weight) : w{weight} {}
bool operator()(const Apples& A) const {
return A.weight > w;
}
};
Then we just need to create an instance of the class holding the reference weight and pass it to count_if:
const int count = std::count_if(crate.begin(), crate.end(), IsGreater(toFind));
You can avoid creating an explicit class using a lambda:
const int count = std::count_if(crate.begin(), crate.end(),
[=](const Apples& A) -> bool {
return A.weight > toFind;
});
Here the reference value toFind is captured by value.
I'm trying to write function that search for char * element in array of char* and the function start check this element, if the element exist in the array I will have "found", if not it should be "inserted" and the element added to the array.
I wrote this code but I cannot know how to try it, the program always gives me exception, what can I do to check the element in my pointer array?
void checkFunction(char*myArray[], char *element,bool flag)
{
for (int i = 0; i < strlen(*myArray) ; ++i)
{
if (myArray[i] == element)
{
flag = true;
}
}
*myArray = element;
flag = false;
if (flag)
{
cout << "Found" << endl;
}
else
{
cout << "Inserted" << endl;
}
}
C++ Way
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
int main(int argc, const char * argv[]) {
vector<string> myStrings { "One", "Two", "Three" };
// std::find() finds the first element that matches a value
auto it = find(begin(myStrings), end(myStrings), "Twooo");
if (it != end(myStrings)) {
cout << "We found this string; do something..." << endl;
}
}
Few remarks regarding your function:
1.Why do you need the third parameter bool flag, instead of having it as local variable?
2.If you want to expand an array you should copy the old to a newly allocated and then add the new element, you can not just do: *myArray = element;
3.If you want to iterate through the array length/ size, instead of:
for (int i = 0; i < strlen(*myArray) ; ++i)
pass an additional parameter to your function, that indicates the number of elements in the array.
With std::string and std::vector you could do something like:
void check_insert (std::vector<std::string>& v, std::string& c) {
for (auto i = 0; i < v.size(); ++i) {
if (v[i] == c) {
std::cout << "Found!\n";
return;
}
}
v.push_back(c);
std::cout << "Inserted!\n";
}
I was trying to sort a vector of struct.The following is my code.I am not able to sort it properly...Can anyone help me..?I need to sort according to the mmNo.Sorry ...i missed some part of the code...
typedef struct MMInfo
{
std :: string strMmNo;
std :: string strMmName;
std :: string strMmsPlace;
std :: string strMmAdd;
std :: string strMmPh;
MMInfo(const std::string& mmNo,
const std::string& mmName,
const std::string& mmPlace,
const std::string& mmAdd,
const std::string& mmPh) : stringValue(mmNo,),stringValue(mmName),
stringValue(mmPlace),stringValue(mmAdd),
stringValue(mmPh) {}
bool operator < (const MMInfo& str) const
{
return (mmNo < str.mmNo);
}
} MMInfo;
std::vector < MMInfo > mmlist;
MMInfo mmInfo = {"", "", "", "", ""};
mmInfo.strMmNo = "3452132"; //actually , i have used a loop to get it from the user
mmInfo.strMmName="Peter";
mmInfo.strMmPlace="TCR";
mmInfo.strMmAdd="Street 453";
mmInfo.strMmPh="8587556587";
mmlist.push_back(mmInfo);
sort(mmlist.begin(),mmlist.end());
for (int i=0; i<mmlist.size(); i++)
{
cout << " first row :" << mmlist[i].strMmNo << " " << mmlist[i].strMmName
<<" " <<mmlist[i].strMmsPlace << " " << mmlist[i].strMmsAdd ;
}
Your code has no problems. I mean, the usage is right but the structure definition seems not correct. It's not compilable at least in Visual C++ 9.0 Please make a proper initialization list. The following code worked fine for me
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
using namespace std;
typedef struct NodeInfo
{
int x;
NodeInfo( int xi ){ x = xi; }
bool operator < (const NodeInfo& str) const
{
return (x < str.x);
}
}MMInfo;
int _tmain(int argc, _TCHAR* argv[])
{
std::vector < MMInfo > mmlist;
mmlist.push_back( 1 );
mmlist.push_back( 31 );
mmlist.push_back( 21 );
mmlist.push_back( 11 );
mmlist.push_back( 41 );
sort(mmlist.begin(),mmlist.end());
for (unsigned int i=0; i<mmlist.size(); i++)
{
cout<< " x row : \n" << mmlist[i].x ;
}
return 0;
}
Does that even compile? (No!)
You're trying to initialize values that don't exist. Maybe initialize your strMm* values instead of stringValue?
You're initializing the same value (that doesn't even exist!) multiple times (Initialize strMm* members with a corresponding mm* value)
Your comparison function compares values that don't exist. (Compare strMmNo < str.strMmNo).
Also, you don't even have values to sort in your list.
I tried to print all the possible combination of members of several vectors. Why
the function below doesn't return the string as I expected?
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
string EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, string
strSoFar)
{
string ResultString;
if (vecIndex >= allVecs.size())
{
//cout << strSoFar << endl;
ResultString = strSoFar;
//return ResultString;
}
for (size_t i=0; i<allVecs[vecIndex].size(); i++) {
strSoFar=EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
}
ResultString = strSoFar; // Updated but still doesn't return the string.
return ResultString;
}
int main ( int arg_count, char *arg_vec[] ) {
vector <string> Vec1;
Vec1.push_back("T");
Vec1.push_back("C");
Vec1.push_back("A");
vector <string> Vec2;
Vec2.push_back("C");
Vec2.push_back("G");
Vec2.push_back("A");
vector <string> Vec3;
Vec3.push_back("C");
Vec3.push_back("G");
Vec3.push_back("T");
vector <vector<string> > allVecs;
allVecs.push_back(Vec1);
allVecs.push_back(Vec2);
allVecs.push_back(Vec3);
string OutputString = EnumAll(allVecs,0,"");
// print the string or process it with other function.
cout << OutputString << endl; // This prints nothing why?
return 0;
}
The expected output is:
TCC
TCG
TCT
TGC
TGG
TGT
TAC
TAG
TAT
CCC
CCG
CCT
CGC
CGG
CGT
CAC
CAG
CAT
ACC
ACG
ACT
AGC
AGG
AGT
AAC
AAG
AAT
You call EnumAll recursively, but you ignore the string that it returns. You have to decide how you are going to aggregate those strings - or what you are going to do with them.
Your function doesn't return anything because your last call doesn't return anything since there's no return and the end of your function.
Edit:
One thing that you can do, is to insert your ResultString to a global vector each time before the return. And at the end, all your results will be available in this vector.
Here is an alternate solution. This does not expect you to pass anything but the initial vectors:
int resultSize( vector< vector<string> > vector ){
int x=1;
for( int i=0;i<vector.size(); i++ )
x *= vector[i].size();
return x;
}
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<resultSize( vector< vector<string> >(allVecs.begin()+1, allVecs.end() ) ); j++){
result.push_back( allVecs[0][i] + enumAll(vector< vector<string> >(allVecs.begin()+1, allVecs.end() ))[j] );//enumAll on each tempVector is called multiple times. Can be optimzed.
}
}
}
Advantage of this method:
This is very readable in terms of the recursion. It has easily identifiable recursion base step and also the recursion itself. It works as follows: Each iteration of the recursion enumerates all possible strings from n-1 vectors and the current step simply enumerates them.
Disadvantages of this method:
1. enumAll() function is called multiple times returning the same result.
2. Heavy on stack usage since this is not tail recursion.
We can fix (1.) by doing the following, but unless we eliminate tail recursion, we cannot get rid of (2.).
vector<string> enumAll(const vector< vector<string> > allVecs )
{
//__ASSERT( allVecs.size() > 0 );
vector<string> result;
if( allVecs.size() == 1 ){
for( int i=0 ; i< allVecs[0].size(); i++){
result.push_back( allVecs[0][i] );
}
return result;
}
const vector< vector<string> > tempVector(allVecs.begin()+1, allVecs.end() );
vector<string> tempResult = enumAll( tempVector );// recurse
int size = resultSize( tempVector );
cout << size << " " << tempResult.size() << endl;
for( int i=0; i<allVecs[0].size(); i++ ){
for( int j=0; j<size; j++){
result.push_back( allVecs[0][i] + tempResult[j] );
}
}
}
Your second return should also accumulate the strSoFar in some way. Something like:
for (size_t i=0; i<allVecs[vecIndex].size(); i++)
{
strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
}
ResultString = strSoFar;
return ResultString;
The code you provided crashes. In the following line, notice that you will be exceeding the limits of vecIndex. There is no check on it in the loop. Also, in the if condition above, you donot reset the vecIndex either. So you will have an access violation.
strSoFar = EnumAll(allVecs, vecIndex+1, strSoFar+allVecs[vecIndex][i]);
To fix it, either rest vecIndex in the if() or use the following for statement:
for (size_t i=0; i<allVecs[vecIndex].size() && vecIndex < allVecs.size(); i++){...}
Edit: However, this does not give the correct output yet.
Your function determines all the correct combinations but they are lost since you do not aggregate them properly.
I see you asked the same question here. I will assume you are now looking for a means to get the output back to the top level so you can handle it from there.
The problem then comes down to how you aggregate the output. You are using a string, but are looking for multiple rows of data. There are infinite answers to this .. here is one using a vector container.
#include <iostream>
#include <vector>
#include <fstream>
#include <sstream>
using namespace std;
void printAll(const vector<string> data);
void EnumAll(const vector<vector<string> > &allVecs, size_t vecIndex, vector<string>&allStr, string strSoFar)
{
if (vecIndex >= allVecs.size())
{
allStr.push_back(strSoFar);
return;
}
for (size_t i=0; i<allVecs[vecIndex].size(); i++)
EnumAll(allVecs, vecIndex+1, allStr, strSoFar+allVecs[vecIndex][i]);
}
int main ( int arg_count, char *arg_vec[] ) {
vector <string> Vec1;
Vec1.push_back("T");
Vec1.push_back("C");
Vec1.push_back("A");
vector <string> Vec2;
Vec2.push_back("C");
Vec2.push_back("G");
Vec2.push_back("A");
vector <string> Vec3;
Vec3.push_back("C");
Vec3.push_back("G");
Vec3.push_back("T");
vector <vector<string> > allVecs;
allVecs.push_back(Vec1);
allVecs.push_back(Vec2);
allVecs.push_back(Vec3);
vector<string> allStr;
EnumAll(allVecs,0,allStr,"");
// print the string or process it with other function.
printAll(allStr);
return 0;
}
void printAll(const vector<string> data)
{
vector<string>::const_iterator c = data.begin();
while(c!=data.end())
{
cout << *c << endl;
++c;
}
}