function returns an empty vector - c++

I am trying to return a vector of strings from a function, but every time I do so I get an empty vector.However when I try to print the vector in the function itself it's not empty but when I try to print the returned vector I am getting nothing printed.
#include <iostream>
#include <vector>
using namespace std;
vector<string> permute(string S, string chosen){
vector<string> permutated_strings;
if(S.empty())
permutated_strings.push_back(chosen);
else{
for(int i=0;i<S.length();i++){
char c = S[i];
chosen += c;
S.erase(i,1);
permute(S,chosen);
//backtrack
chosen.erase(chosen.length()-1,1);
S.insert(i,1,c);
}
}
return permutated_strings;
}
int main() {
//code
int test;
cin >> test;
while(test)
{
string S;
cin >> S;
vector<string> vec;
vector<string> ::iterator i;
vec = permute(S,"");
for(i=vec.begin();i!=vec.end();i++)
cout<<*i<<" ";
cout << "\n";
test--;
}
return 0;
}
When I am printing the vector in the permute function I am getting the right result but when I am printing the vector in main function it is empty. Can somebody please point me out the mistake I am doing.

You need to save result of recursive call of permute method.
auto result = permute(S,chosen);
permutated_strings.insert(permutated_strings.end(), result.begin(), result.end());

I got the mistake that I was doing. I really hate answering my own questions but it may help someone like me in the future.
I have changed -
vector<string> permutated_strings;
to
static vector<string> permutated_strings;
in the permute function so that previous returns from the recursive calls are not lost. By doing so I am getting the desired result.
Thanks everyone for pointing me to the mistake that I was doing.
EDIT
As suggested by #M.M that this solution may cause problem in future. And I have realized that if I give "test" value as 2 the final value in the permutated_strings will be from test=1 + test =2 which is not which I wanted. So this solution is not the perfect one. Instead I am accepting solution from #BartekPL.

Related

Why does my control function do the opposite of what it's supposed to do?

int control(int n, data a[], string cod){
for(int i = 0 ; i<n ; i++){
if(cod == a[i].code)
return i;
}
return -1;
}
Hello, everyone! this is my control function. it's used to check if a code that has been input by a user already exists in the struct. This is what happens in the "input" function:
void input(int &n, data a[]){
string code;
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else
cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code)) == -1);
n++;
}
There are two problems:
everytime i input a code it tells me that it already exists, even though it's my first time.
it doesn't make me try again, even though the code already exists.
Let's start by indenting your code so we can more easily understand what it does:
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return i;
}
return -1;
}
Ah, so it scans through an array, and returns a value greater than or equal to 0 if a string is present, or -1 if it's absent. Then let's consider the code that uses it:
void input(int &n, data a[])
{
string code;
do
{
cout << "\nInput the code: ";
cin >> code;
if ((control(n, a, code)) > 0)
a[n].code = code;
else
cout << "\nThe code you've input already exists. Please try again.";
} while ((control(n, a, code)) == -1);
n++;
}
So this accepts the code if the return value was greater than 0, and otherwise rejects the code as already existing. This is mostly backwards, but not exactly even that.
My suggestion would be to start by defining an enumeration to give meaningful names to the values you're returning. This makes it much easier to keep track of what's going on:
enum { DUPLICATE, UNIQUE };
int control(int n, data a[], string cod) {
for (int i = 0; i < n; i++)
{
if (cod == a[i].code)
return DUPLICATE;
}
return UNIQUE;
}
Now it's much easier to get our condition correct, and much more obvious if we react to it incorrectly:
if (control(n, a, code) == UNIQUE)
a[n].code = code;
else
cout << "\nThe code is a duplicate";
Or, if you prefer to reverse the condition, it's still easy to get correct:
if (control(n, a, code) == DUPLICATE)
cout << "\nThe code is a duplicate";
else
a[n].code = code;
But in particular, if you accidentally get things backwards, it'll be pretty obvious:
if (contro(n, a, code) == UNIQUE)
cout << "\nThe code is a duplicate";
At least to me, the contrast between "UNIQUE" on one line, and "duplicate" immediately below it seems fairly obvious.
Other Points to Consider
I'd advise against having:
using namespace std;
...in your code, as you apparently do right now. This is a bad habit that saves a little typing now, but can lead to considerable grief in the long term.
I'd also look up std::set and std::unordered_set, which can already do (more efficiently) what you're using your data array to do.
If/when you do need something array-like in C++, you probably want to use an std::array or std::vector rather than the built-in array type. They're much more convenient and help prevent quite a few errors.
I'd try to come up with a better name than control for a function that tries to show whether a code is already in use. control is such a generic name, it's almost impossible to guess what it's supposed to accomplish without looking at its content. A good name for a function does a great deal to clarify the code that uses it, and show what you intend that piece of code to accomplish:
std::cin >> new_code;
if (isDuplicate(new_code))
std::cerr << "The code you entered is a duplicate. Please try again\n";
else
codes.add(new_code);
do{
cout<<"\nInput the code: ";
cin>> code;
if((control(n,a,code))>0)
a[n].code=code;
else cout<<"\nThe code you've input already exists. Please try again.";
}while((control(n,a,code))==-1);
I see at least two problems here:
control returns 0 when the element is found at the first position, you check for >0 in the condition
if the loop body sucessfully inserts the element then while((control(n,a,code))==-1); results in an endless loop.
I suggest you to use std::find_if to check if an element is already present. With a std::vector thats:
#include <string>
#include <vector>
#include <algorithm>
struct data {
std::string code;
};
int main() {
std::vector<data> v;
std::string foo = "test";
auto it = std::find_if(v.begin(),v.end(),[foo](auto x){ return x.code == foo;});
bool found = (it == v.end());
}
Also consider to use a std::set if you want a container with unique entries.

String permutation recursion issue

(--This question was answered down below--)
Hey guys so I know this question has been answered in various ways so far on this site but I wanted to see if I could get a hint to my question without getting the blunt answer... sorry if this is redundant!
so... so far my code is this (as the function says, this is supposed to print out every permutation of the string "ABCD" and MUST be done recursively and without the use of STL algorithms):
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
prefix += remainder[i];
remainder = (remainder.substr(0, i) + remainder.substr(i+1)); //Gets rid of selected char
printPermutations(prefix, remainder); //recursion w/updated values. Problem here?
}
}
}
Where remainder = "ABCD" as a test string. I'm assuming my problem is with the recursive call itself?
So far, the function only prints out the first 3 permutations: ABCD, ABDC, ACBD. I also have a hunch that this could have something to do with the for control since it printed out 3 permutations and 3 would be less than the string's length of 4? I don't know. I just started learning recursion and it's really hard for me to figure out how to implement recursive calls properly.
The problem is that you're modifying both strings in the loop, so prefix grows and remainder shrinks.
That is, you want the "top-level" call to iterate through A/BCD, B/ACD, C/ABD, and D/ABC, but you're iterating through A/BCD, AB/CD, ABC/D, and ABCD/empty.
Don't modify the strings, just pass the values you want to the recursion:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
printPermutations(prefix + remainder[i],
remainder.substr(0, i) + remainder.substr(i+1));
}
}
}
Or use "fresh" variables if you want a more "step-by-step" look:
void printPermutations(string prefix, string remainder)
{
if (remainder.empty())
cout<<prefix<<endl;
else {
for(int i = 0; i<remainder.length(); i++)
{
string thisPrefix = prefix + remainder[i];
string thisRemainder = remainder.substr(0, i) + remainder.substr(i+1);
printPermutations(thisPrefix, thisRemainder);
}
}
}
Please consider using the stl algorithm next_permutation for the job. The code in your case is than:
#include <algorithm>
#include <string>
#include <iostream>
int main()
{
std::string s = "ABCD";
std::sort(s.begin(), s.end());
do {
std::cout << s << '\n';
} while(std::next_permutation(s.begin(), s.end()));
}
If you need to, you can write a wrapper around this snippet.

Segmentation fault during counting of elements in array of strings c++

I am trying to solve an old problem found on topcoder. I am immediately stuck in trying to find the number of elements in an array of strings. Here is my code
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string>
using namespace std;
class MiniPaint {
private:
size_t numLines;
public:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
numLines++;
}
cout << numLines << '\n';
return 0;
}
};
int main() {
MiniPaint instance;
string picture[] = {"BBBBBBBBBBBBBBB", "WWWWWWWWWWWWWWW", "WWWWWWWWWWWWWWW", "WWWWWBBBBBWWWWW"};
instance.leastBad(picture, 10);
return 0;
}
This code gives me a segmentation fault. Something is going wrong, the code is a little bit excessive for just the functionality of counting the number of elements but of course I want to extend the class to include more functionality. If anyone can explain what is going wrong here I would be grateful! Thanks in advance.
EDIT: when I expand the code by
cout << picture[numlines] << '\n';
in the while loop, to show the actual elements in the array, first the four proper strings are shown and then somehow it endlessly prints spaces to the terminal. So the problem lies somewhere in the fact that
picture[4].empty()
does not return true, even though picture has only four elements.
Your while loop condition assumes that the last string in the array is empty:
int leastBad(string picture[], int maxStrokes) {
numLines = 0;
while (!picture[numLines].empty()) {
But your input string array defined in main() is not terminated with an empty "" string.
So you may want to add this empty string terminator:
// inside main()
string picture[] = {..., "" /* Empty string terminator */ };
In addition, in modern C++ I'd encourage you to use array container classes instead of raw C-style arrays, typically std::vector<std::string>.
In this case, you can use the size() method to get the array size (i.e. element count), or just a range-for loop for iterating through the whole array.
You access the array out of bounds.
When you call picture[4] you want to access a string object which is not there end the call to the function empty() is on uninitialized memory.
You either need to store how big the array is and iterate until numLines<=3 or you can use a vector
std::vector<std::string> picture = ...
for(std::string line : picture)
{
//do stuff
}
You are out of array bounds at picture[numLines]. You should pass array length or calculate it and check the index numLines. Code will look like:
size_t length = sizeof(picture) / sizeof(*picture); // For VS use _countof macro
while (numLines < length && !picture[numLines].empty())
{
++numLines;
}

Write a short C++ program that outputs all possible strings formed by using each of the characters ’a’, ’b’, ’c’, ’d’, ’e’, and ’f’ exactly once

I came across this question and I am not able to solve it. All I could code was for small strings like ab,ac,ad,ae,af and such. But not for the longer strings like abc,abcd,etc. It would be really nice if someone could direct me towards some kind of solution. I would prefer without recursion but if not then recursion is also fine.
Here is my code:
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
vector<string> make_string(vector<char>vec, char ch)
{
int i=0;
vec.erase(remove(vec.begin(), vec.end(), ch), vec.end());
int size = vec.size();
vector<string>all_strings;
string answer="";
for(i=0;i<size;i++) //here is the "meat". I could add a few more for loops for longer strings
// But I think that would just get messy.
{
answer= answer+ch+vec[i];
all_strings.push_back(answer);
answer="";
}
return all_strings;
}
void print_vector(vector<string>vec)
{
int i=0;
int size = vec.size();
for(i=0;i<size;i++)
{
cout<<vec[i]<<endl;
}
cout<<"--------------------------";
cout<<endl;
}
int main()
{
vector<char>vec;
vec.push_back('a');
vec.push_back('b');
vec.push_back('c');
vec.push_back('d');
vec.push_back('e');
vec.push_back('f');
int i=0;
vector<string>my_strings;
int size=vec.size();
for(i=0;i<size;i++)
{
my_strings=make_string(vec,vec[i]);
print_vector(my_strings);
my_strings.clear();
}
return 0;
}
You are looking for a permutation algorithm. Please take a look at this post on wordaligned.org, which describes an iterative solution to the problem:
Next permutation
The author's code is very simple and makes use of the standard library:
#include <algorithm>
#include <cstdio>
int main()
{
char xs[] = "abcdef"; // <-- modified to fit the question.
do
{
std::puts(xs);
}
while (std::next_permutation(xs, xs + sizeof(xs) - 1));
return 0;
}
If you read further, there is a discussion on the implementation of next_permutation and a breakdown of how it works.

C++ program has stopped working

I am making a quite simple program, just a little chat bot AI kind of thing, and I have some code, c++ of course, for the program. I don't get any errors but when I run it a window comes up saying program.exe has stopped working, like it stopped responding. My code is:
#include<iostream>
#include<string.h>
#include<cmath>
#include<vector>
#include<ctime>
#include<conio.h>
#include<algorithm>
#include<cstdlib>
using namespace std;
struct strarray{
char* array[];
};
struct keyword{
string keywords;
string responses[];
};
keyword * dictionary = new keyword[2];
keyword defaultr;
keyword getMatch(string key);
string sconvert(string con);
void init();
string getResp(keyword key);
bool cont=true;
int main(int argc, char* argv[]){
string input;
while(cont){
getline(cin,input);
cout << getResp(getMatch(input));
getch();
getch();
}
}
string sconvert(string con){
con.erase(remove_if(con.begin(), con.end(), ::isspace), con.end());
con.erase(remove_if(con.begin(), con.end(), ::ispunct), con.end());
return con;
}
void init(){
srand(time(NULL));
dictionary[0].keywords="hello";
dictionary[0].responses[0]="Hello, how have you been?";
dictionary[0].responses[1]="Hello, have you missed me?";
dictionary[0].responses[2]="Hey, how's it going?";
defaultr.responses[0]="That's interesting, tell me more.";
defaultr.responses[1]="Please, tell me more.";
}
keyword getMatch(string key){
for(int i=0; i<sizeof(dictionary); i++){
if(key==dictionary[i].keywords){return dictionary[i];}
}
return defaultr;
}
string getResp(keyword key){
return key.responses[rand() % sizeof(key)];
}
When I run it, it opens up normally, but after I input something when it comes up it "stops working". Could somebody please tell me what I need to change, and why would be appreciated.
Is there some pointer problem? Or something with the rand? I'm really confused and would appreciate some advice on how to better this program so it actually works.
sizeof(dictionary) will give sizeof(keyword*), probably 4 or 8, so you will iterate over the end of the dictionary array and terminate.
Easiest fix: Define a constant to store the array length.
const dictionarySize = 2;
and use that throughout.
You also need to change struct keyword to:
struct keyword{
string keywords;
string responses[3];
};
first of all u have an infinite loop so the program should work for ever .. I took a glance at the code and using rand() % sizeof(key) is wrong, the responses is not predetermined so either you set it to a specific value for example
struct keyword {
string keywords;
string responses[2];
};
rand() % sizeof(key.responses)
or you make your structure like this
struct keyword {
string keywords;
vector<string> responses;
};
rand() % key.responses.size()
//After setting the responses by push_back for example
there are other ways but this is safer and no memory management needed ...