This question already has answers here:
How to get the real and total length of char * (char array)?
(15 answers)
Closed 4 years ago.
How do I get the length of const char* arrays indexes?
The vector:
std::vector<const char*> _infoBarText;
The const char* []:
const char* text[4] = {"Current T:", "Target T:", "Time elapsed:", "Time remaining:"};
Assigning the char array to the vector:
_infoBarText.assign(text, text+4);
How can I get the length of the individual strings, like "current T", from the vector?
Raw C strings (bare char*-s) are not a perfect fit for modern C++ code.
If you change it to std::vector<std::string_view> you get your problem solved without (virtually) any overhead (given you are initializing it with literals) and as a bonus you will potentially make it safer and more usable.
See the cppreference article for details.
Example (GodBolt):
#include <string_view>
#include <vector>
#include <iostream>
int main() {
using namespace std::literals;
std::vector<std::string_view> strs = { "hello"sv, "there"sv };
for (auto&& str: strs)
std::cout << str << str.size();
return 0;
}
GodBolt Code Insight Output (note the std::operator""sv("hello", 5ul)):
#include <string_view>
#include <vector>
#include <iostream>
int main()
{
using namespace std::literals;
std::vector<std::string_view> strs = std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > >{std::initializer_list<std::basic_string_view<char, std::char_traits<char> > >{std::operator""sv("hello", 5ul), std::operator""sv("there", 5ul)}, std::allocator<std::basic_string_view<char, std::char_traits<char> > >()};
{
std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > & __range = strs;
__gnu_cxx::__normal_iterator<std::basic_string_view<char, std::char_traits<char> > *, std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > > __begin = __range.begin();
__gnu_cxx::__normal_iterator<std::basic_string_view<char, std::char_traits<char> > *, std::vector<std::basic_string_view<char, std::char_traits<char> >, std::allocator<std::basic_string_view<char, std::char_traits<char> > > > > __end = __range.end();
for( ; __gnu_cxx::operator!=(__begin, __end); __begin.operator++() )
{
std::basic_string_view<char, std::char_traits<char> > & str = __begin.operator*();
std::operator<<(std::cout, std::basic_string_view<char, std::char_traits<char> >(str)).operator<<(str.size());
}
}
return 0;
}
The long way:
#include <vector>
#include <cstring> // for strlen
std::vector<const char*> _infoBarText;
char const *str = _infoBarText[0]; // or any other valid index
auto len = std::strlen(str);
Short:
auto len = std::strlen(_infoBarText[0]);
Related
After compiling my hash_multimap I get this large one paragraph error for my
In member function ‘size_t __gnu_cxx::hashtable<
I have never seen this huge error and I'm actually not sure what to do to fix this error due to it's abnormal size.
Any suggestions why line:
p = map1.equal_range(searchKey);
is causing this abnormaly long error? FYI- I cut the whole error and removed the middle part because once I pasted it here it was like a page long O.o
ERROR
/usr/include/c++/4.3/backward/hashtable.h: In member function ‘size_t
__gnu_cxx::hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey,
_Alloc>::_M_bkt_num_key(const _Key&, size_t) const [with _Val =
std::pair<const std::basic_string<char, std::char_traits<char>,
std::allocator<char> >, Map2*>, _Key = std::basic_string<char
...
std::char_traits<char>, std::allocator<char> > >, _Alloc =
std::allocator<Map2*>]’
hash_map2.cpp:55: instantiated from here
/usr/include/c++/4.3/backward/hashtable.h:595: error: no match for call to
‘(const __gnu_cxx::hash<std::basic_string<char, std::char_traits<char>,
std::allocator<char> > >) (const std::basic_string<char,
std::char_traits<char>, std::allocator<char> >&)’
Map.h file
#ifndef MAP2_H
#define MAP2_H
#include <iostream>
#include <string>
using namespace std;
class Map2 {
public:
Map2(string data1, string data2, string data3, string data4, string data5);
string pop, keyword, user, desc, id;
string get_pop() {return pop;}
string get_key() {return keyword;}
string get_user() {return user;}
string get_desc() {return desc;}
string get_id() {return id;}
void call_Values(int i);
};
Map2:: Map2(string data1, string data2, string data3, string data4, string data5) {
pop = data1;
keyword = data2;
user = data3;
desc = data4;
id = data5;
}
void Map2:: call_Values(int i) {
get_pop();
get_key();
get_user();
get_desc();
get_id();
}
#endif
hash_map2.cpp
#include <fstream>
#include <iostream>
#include "Map2.h"
#include <ext/hash_map>
#include <string>
#include <sstream>
using namespace std;
using __gnu_cxx::hash_multimap;
int nav() {
cout <<"Select from the following options : " << endl <<endl;
cout <<"Search Tweets based on Keyword (Type 1) " <<endl;
cout <<"End Program (Type 2)"<<endl<<endl;
int key =0;
cin >> key;
return key;
}
int main() {
int option = nav();
if (option == 1) {
ifstream readFile("project4.csv");
string tempPop, tempID, tempKey, tempUser, tempDesc;
string tempRead;
hash_multimap<string, Map2 *>map1;
while (readFile != NULL){
// sends to a temp variable
readFile >> tempRead;
for (int i =0; i<400; i++){
//create new object each time
Map2 *mapNode = new Map2(tempPop,tempID,tempKey,tempUser,tempDesc);
//insert each time new object is made
map1.insert(pair<string, Map2 *> (tempKey, mapNode));
} //end for
} //end while
//Navigation through multimap
//first pointer is for first one and second to last hash table value
pair<hash_multimap<string, Map2 *> :: const_iterator,
hash_multimap<string, Map2 *> :: const_iterator> p;
string searchKey = "";
cout << "Please enter the keyword value exactly so we can search the"<<
"available tweets: " <<endl;
cin >> searchKey;
p = map1.equal_range(searchKey);
}
else
return 0;
}
Issue is the fact of calling string to search. Need to convert the string to int before calling the value inside the equal_range function.
The program I want to do is an anagram finder
From a dictionary file and a string input, the function "anagrams" should return me a vector (one for each size from 1 to max) of vector of words found in the dictionary that match all the combination of sub-words possible with input as anagram
When I create the new dictionary with the function createdictionary, I put every anagram in a vector of string
However, when I want to check for these anagrams in my anagrams function, I don't know how to access it (line 74)
In uniqueAnagram, I have every sub-anagram possible, everything is ok, but using
if (dict.words.find(it->second)){
cout << dict.words.find(it->second)->second[0] << endl;
}
in the loop (as a test to see if the expression actually write the right words) leads me to this error and I don't understand why:
In function 'std::vector, std::allocator >, std::allocator, > std::allocator > > >, std::allocator std::char_traits, std::allocator >, std::allocator std::char_traits, std::allocator > > > > > anagrams(const std::string&, const > Dictionary&, int)':|
error: could not convert 'dict->Dictionary::words.std::map<_Key, _Tp,
_Compare, _Alloc>::find [with _Key = std::basic_string, std::allocator >, _Tp =
std::vector,
std::allocator >, std::allocator, std::allocator > > >, _Compare =
std::less,
std::allocator > >, _Alloc = std::allocator
I've been stuck the last 10 hours on this and I can't take it anymore, I really don't know how to solve that issue
Thank for you help, you'd save me life
//anagrams.h
#ifndef ANAGRAMS_H_INCLUDED
#define ANAGRAMS_H_INCLUDED
#include <vector>
#include <string>
#include <map>
using namespace std;
struct Dictionary{
map<string, vector<string> > words;
};
Dictionary createdictionary(const string&);
vector<vector<string> > anagrams(const string&, const Dictionary&, int);
#endif // ANAGRAMS_H_INCLUDED
//anagrams.cpp
#include "anagrams.h"
#include <iostream>
#include <fstream>
#include <map>
#include <vector>
#include <algorithm>
#include <iterator>
using namespace std;
string sortString(string input);
Dictionary createdictionary(const string& filename){
Dictionary dictionary;
ifstream ifs;
ifs.open(filename.c_str());
string word;
while (ifs >> word){
string sortedWord = sortString(word);
(dictionary.words[sortedWord]).push_back(word);
}
return dictionary;
}
string sortString(string input){
vector<char> vectorWord(input.begin(), input.end());
sort(vectorWord.begin(), vectorWord.end());
string sortedInput(vectorWord.begin(), vectorWord.end());
return sortedInput;
}
vector<vector<string> > anagrams(const string& input, const Dictionary& dict, int max){
vector<vector<string> > anagrams;
size_t n = input.length();
for (int r = 0; r < max + 1; r++){
vector<bool> v(n);
fill(v.begin() + r, v.end(), true);
map<string, string> uniqueAnagram;
do {
string word;
for (size_t i = 0; i < n; ++i) {
if (!v[i]) {
word = word + input[i];
}
}
word = sortString(word);
uniqueAnagram[word] = word;
} while (next_permutation(v.begin(), v.end()));
vector<string> tempAnagram;
for(map<string, string>::iterator it = uniqueAnagram.begin(); it != uniqueAnagram.end(); it++){
if (dict.words.find(it->second)){
cout << dict.words.find(it->second)->second[0] << endl;
}
}
sort(tempAnagram.begin(), tempAnagram.end());
anagrams.push_back(tempAnagram);
}
vector<char> vectorWord(input.begin(), input.end());
sort(vectorWord.begin(), vectorWord.end());
string sortedWord(vectorWord.begin(), vectorWord.end());
// cout << (dict.words.find(sortedWord)->second)[0] << endl;
return anagrams;
}
//main.cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include "anagrams.h"
using namespace std;
int main()
{
string filename = "C:/dictionary.txt";
Dictionary dictionary = createdictionary(filename);
vector<vector<string> > anagram = anagrams("llohe", dictionary, 5);
return 0;
}
map::find returns an iterator, not a boolean. If the key wasn't found, it returns the map's past-the-end iterator. So instead of
if (dict.words.find(it->second))
you want
if (dict.words.find(it->second) != dict.words.end())
or
if (dict.words.count(it->second) != 0)
It would be more efficient to store the iterator so you don't need to find the key twice:
auto found = dict.words.find(it->second);
if (found != dict.words.end()) {
cout << found->second[0] << endl;
}
I'm trying to compile some c++ code on os x using g++ in the terminal. However, I keep getting an error and I'm unsure of what it means. I have 3 files, main.cpp; comp_fns.cpp and comp_fns.h. Window and Gene are two different classes. Here is the error:
g++ -Wall main.cpp comp_fns.cpp
duplicate symbol Window::setValues(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)in:
/var/folders/jf/3y93rsfd1n55q2qd75y0w0r00000gn/T//cc51aFZg.o
/var/folders/jf/3y93rsfd1n55q2qd75y0w0r00000gn/T//cc2KNfcB.o
duplicate symbol Gene::setValues(std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::basic_string<char, std::char_traits<char>, std::allocator<char> >)in:
/var/folders/jf/3y93rsfd1n55q2qd75y0w0r00000gn/T//cc51aFZg.o
/var/folders/jf/3y93rsfd1n55q2qd75y0w0r00000gn/T//cc2KNfcB.o
ld: 2 duplicate symbols for architecture x86_64
collect2: ld returned 1 exit status
Any help would be much appreciated, and I can post the code if needed.
EDIT: I did not #include one cpp file into another. Here is my header file, where I think the issue may be at. This is my first cpp program so there might be some obvious mistakes. I originally wrote it in C and am changing it over to c++ so I can learn how to do both.
#ifndef __Compare_Data_C____comp_fns__
#define __Compare_Data_C____comp_fns__
#include <iostream>
#include <cstdlib>
#include <string>
#include <sstream>
using namespace std;
class Window {
public:
int start, stop, length;
double average;
string strandID, locations;
void setValues(string locs, string strand, string length, string avg);
};
class Gene {
public:
int start, stop;
string strandID, genes;
void setValues(string locs, string strand, string spcGene);
};
void Window::setValues(string locs, string strand, string a_length, string avg) {
locations = locs;
vector<string> token(3);
istringstream iss(locs);
for (int i=0; i<3; i++) {
getline(iss, token[i], '.');
}
start = atoi(token[0].c_str());
stop = atoi(token[2].c_str());
strandID = strand;
length = atoi(a_length.c_str());
average = atof(avg.c_str());
}
void Gene::setValues(string locs, string strand, string givenGene) {
vector<string> token(3);
istringstream iss(locs);
for (int i=0; i<3; i++) {
getline(iss, token[i], '.');
}
start = atoi(token[0].c_str());
stop = atoi(token[2].c_str());
strandID = strand;
genes = givenGene;
}
int getSize(string inputID, string strandID, const int header);
void getWindows(vector<Window> &win, string inputID, const int header);
void getGenes(vector<Gene> &posGene, vector<Gene> &negGene, string inputID, const int header);
void getSpecialWindows(vector<Window> &w, vector<Gene> &g, int wSize, int gSize, ofstream &output);
#endif /* defined(__Compare_Data_C____comp_fns__) */
Duplicate symbols means the linker faces the same function in both of your compilation units (main.cpp and comp_fns.cpp). Maybe you implemented the functions in the header without inline?
I get: C:\Documents and Settings\ppp\Pulpit\Zadanie3Infix\main.cpp|72|error: conversion from 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >*' to non-scalar type 'std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >' requested|
and i don't know why. The function suppose to return vector of strings and it does, i used all of these * & and it does not work. Please correct me so it will return this vector.
it works like that s = "(2+23)" it will return it will return vector with tokens.
vector<string> split(string s){
vector<string>* v = new vector<string>();
int i = 0; bool b;string el = "";
while(i < s.size()){
if(isNotNumber(s.at(i))){
el = s.at(i);
v->push_back(el);
cout<<el<<" to operator"<<endl;
el = "";
i++;
}else{
while( i <s.size() && !isNotNumber(s.at(i))){//LENIWE WYLICZANIE !!!
el = el + s.at(i);
cout<<s.at(i)<<" to liczba"<<endl;
i++;
}
v->push_back(el);
el = "";
}
}
cout<<"PO while"<<endl;
for(int i = 0; i < v->size();i++){
cout<<v->at(i)<<endl;
}
return v;
}
and what about that
stack<string>* stack = new stack<string>();
type specifier before stack ;////////////////
Your function split() claims to return vector<string>, however your return value is v. What is v? It's
vector<string>* v
You are attempting to return a pointer but your function declaration states that it is not returning a pointer. Actually, there's no need for a pointer at all in your function; just use a regular vector<string> or pass in a vector by reference:
void split(string s, vector<string>& v){
The question about whether to return a pointer or a value, or pass in a reference to an existing vector was settled a long time ago: don't do any of the above. Instead, create a generic algorithm that works with iterators:
template <class InIt, class OutIt>
void tokenize(InIt b, InIt e, OutIt o) {
while (b != e) {
std::string token;
while (isdigit(*b))
token.push_back(*b++);
if (!token.empty())
*o++ = token;
while (!isdigit(*b) && b != e)
*o++ = std::string(1, *b++);
}
}
To put the result in a vector of strings, you'd do something like:
std::string i("(2+23)");
std::vector<std::string> tokens;
tokenize(i.begin(), i.end(), std::back_inserter(tokens));
Or, if you wanted to display the tokens, one per line for testing:
tokenize(i.begin(), i.end(), std::ostream_iterator<std::string>(std::cout, "\n"));
...which will produce:
(
2
+
23
)
That fits with what I'd think of as the tokens in this input string. I should add, however, that while it works for that input, it may or may not produce what you expect for other inputs. In particular, it will treat whitespace characters as tokens, which you usually don't want (but does seem to be how the original was intended to work).
Your function signature returns a vector, but your return value is a pointer. Change the return value type to pointer to vector or return a vector by value in your function body.
This is really Blastfurnace's answer, ...
but convert the line:
vector<string>* v = new vector<string>();
into
vector<string> v;
and change all the v-> into v.
This way you fix the memory leak too. (The memory allocated by new vector<string>() is never deleted). However, vector<string> v; puts the memory on the stack and is automatically deleted when it goes out of scope.
For my computer science class, we need to write a program (in C++) that takes an input of characters and outputs the possible permutations of it according to the dial pad on a phone, leaving non-digit characters in place.
For example, inputing 2 outputs 2, A, B, C. Inputing 23 outputs 23, A3, B3, C3, 2D, 2E, 2F, AD, AE, AF, BD, BE, BF, etc...
The application provided for this program is finding permutations of "vanity" phone numbers for a given phone number.
Currently, the program I have written doesn't even compile, and I'm afraid the algorithm I'm using is incorrect:
#include <iostream>
#include <multimap.h>
#include <vector>
using namespace std;
// Prototypes
void initLetterMap(multimap<char,char> &lmap);
void showPermutations(const vector<string> &perms);
vector<string> getPermutations(const string &phoneNumber,const multimap<char,char> &lmap);
vector<char> getLetters(char digit, const multimap<char,char> &lmap);
// Declarations
void initLetterMap(multimap<char,char> &lmap) {
lmap.insert(pair<char,char>('1','1'));
lmap.insert(pair<char,char>('2','2'));
lmap.insert(pair<char,char>('2','A'));
lmap.insert(pair<char,char>('2','B'));
lmap.insert(pair<char,char>('2','C'));
lmap.insert(pair<char,char>('3','3'));
lmap.insert(pair<char,char>('3','D'));
lmap.insert(pair<char,char>('3','E'));
lmap.insert(pair<char,char>('3','F'));
// ...
}
vector<char> getLetters(char digit, const multimap<char,char> &lmap) {
multimap<char,char>::iterator it;
pair<multimap<char,char>::iterator,multimap<char,char>::iterator> range;
vector<char> result;
if (isdigit(digit)) {
range = lmap.equal_range(digit);
for (it=range.first;it!=range.second;++it) {
result.push_back((*it).second);
}
} else {
result.insert(result.end(),digit);
}
return result;
}
void showPermutations(vector<string> &perms) {
vector<string>::iterator it;
for (it = perms.begin(); it != perms.end(); it++) {
cout << *it << endl;
}
}
vector<string> getPermutations(const string &phoneNumber,const multimap<char,char> &lmap) {
vector<string> results;
string number = phoneNumber;
vector<char>::iterator vcit;
vector<char> letters;
unsigned int i;
for (i=0;i<phoneNumber.length();i++) {
letters = getLetters(number[i],lmap);
for (vcit=letters.begin();vcit!=letters.end();vcit++) {
number[i] = *vcit;
results.push_back(number);
}
}
return results;
}
int main() {
multimap<char,char> lmap;
initLetterMap(lmap);
string input;
cout << "Enter a phone number to get all possible vanity numbers" << endl;
cout << "> "; getline(cin,input);
showPermutations(getPermutations(input,lmap));
return 0;
}
I get a whole slew of build issues when I try to build this, and am not sure how to resolve most of them:
In file included from /usr/include/c++/4.0.0/backward/multimap.h:59,
from phone02.cpp:18:
/usr/include/c++/4.0.0/backward/backward_warning.h:32:2: warning: #warning This file includes at least one deprecated or antiquated header. Please consider using one of the 32 headers found in section 17.4.1.2 of the C++ standard. Examples include substituting the <X> header for the <X.h> header for C++ includes, or <iostream> instead of the deprecated header <iostream.h>. To disable this warning use -Wno-deprecated.
/usr/include/c++/4.0.0/bits/stl_pair.h: In constructor 'std::pair<_T1, _T2>::pair(const std::pair<_U1, _U2>&) [with _U1 = std::_Rb_tree_const_iterator<std::pair<const char, char> >, _U2 = std::_Rb_tree_const_iterator<std::pair<const char, char> >, _T1 = std::_Rb_tree_iterator<std::pair<const char, char> >, _T2 = std::_Rb_tree_iterator<std::pair<const char, char> >]':
phone02.cpp:75: instantiated from here
/usr/include/c++/4.0.0/bits/stl_pair.h:90: error: no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
/usr/include/c++/4.0.0/bits/stl_tree.h:167: note: candidates are: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator(std::_Rb_tree_node<_Tp>*) [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:164: note: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator() [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:152: note: std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_iterator<std::pair<const char, char> >&)
/usr/include/c++/4.0.0/bits/stl_pair.h:90: error: no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
/usr/include/c++/4.0.0/bits/stl_tree.h:167: note: candidates are: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator(std::_Rb_tree_node<_Tp>*) [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:164: note: std::_Rb_tree_iterator<_Tp>::_Rb_tree_iterator() [with _Tp = std::pair<const char, char>]
/usr/include/c++/4.0.0/bits/stl_tree.h:152: note: std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_iterator<std::pair<const char, char> >&)
make: *** [phone02.o] Error 1
The line numbers are a bit off, but the important ones that I can see are the two about no matching function for call to 'std::_Rb_tree_iterator<std::pair<const char, char> >::_Rb_tree_iterator(const std::_Rb_tree_const_iterator<std::pair<const char, char> >&)'
Besides the errors, I also believe I am heading in the wrong direction with my algorithm.
So I have 2 questions here:
Why am I getting these build errors, and how do I fix them?
How would you suggest going about solving this problem? Am I on the right track or no?
For question #2, I would prefer to not get solutions, just advice or pointers in the right direction.
Thanks!
PS: I am building this on Mac OS X 10.5.8 with gcc, using QtCreator 1.2.1
UPDATE:
I have successfully compiled a solution program. I will post the source code to those who are curious.
#include <iostream>
#include <map>
#include <vector>
#include <string>
using namespace std;
void initLetterMap(map<char,string> &lmap);
vector<string> getMapped(const string &phoneNumber, map<char,string> &lmap);
vector<string> getPermutations(vector<string> number);
unsigned long int countPermutations(vector<string> number);
void initLetterMap(map<char,string> &lmap) {
lmap['0'] = "0";
lmap['1'] = "1";
lmap['2'] = "2ABC";
lmap['3'] = "3DEF";
lmap['4'] = "4GHI";
lmap['5'] = "5JKL";
lmap['6'] = "6MNO";
lmap['7'] = "7PQRS";
lmap['8'] = "8TUV";
lmap['9'] = "9WXYZ";
}
unsigned long int countPermutations(vector<string> number) {
long int fold = 1;
int vals = 0;
vector<string>::iterator it;
for (it=number.begin();it!=number.end();it++) {
vals = (*it).length();
fold *= vals;
}
return fold;
}
vector<string> getMapped(const string &phoneNumber, map<char,string> &lmap) {
unsigned int i;
vector<string> out;
char digit;
string temp;
for (i=0;i<phoneNumber.length();i++) {
digit = phoneNumber.at(i);
if (isdigit(digit)) {
out.push_back(lmap[digit]);
} else {
temp = string(1,digit);
out.push_back(temp);
}
}
return out;
}
vector<string> getPermutations(vector<string> number) {
vector<string> results;
unsigned long int i,j,k;
unsigned long int perms = countPermutations(number);
vector<string>::reverse_iterator numit;
string temp,temp2;
vector<int> state = vector<int>(number.size(), 0);
vector<int>::reverse_iterator stateit;
for (i=0;i<perms;i++) {
j=i;
temp = "";
for (stateit=state.rbegin(), numit=number.rbegin();stateit!=state.rend();stateit++, numit++) {
*stateit = j % (*numit).length();
j /= (*numit).length();
temp.insert(temp.begin(),(*numit)[*stateit]);
}
results.push_back(temp);
}
return results;
}
int main() {
map<char,string> lettermap;
initLetterMap(lettermap);
string input;
cout << "> "; getline(cin,input);
vector<string> perms = getPermutations(getMapped(input,lettermap));
vector<string>::iterator it;
for (it=perms.begin();it!=perms.end();it++) {
cout << *it << endl;
}
}
The code is probably more complicated than it has to be, but my goal was to just get it to work. It seems to run fairly quickly for 10 digit phone numbers, so I guess it's not too bad.
Thanks to Jacob and ShreevatsaR for getting me pointed in the right direction!
How about the following:
#include <cstddef>
#include <iostream>
#include <iterator>
#include <string>
#include <algorithm>
template <typename Iterator>
bool next_combination(const Iterator first, Iterator k, const Iterator last);
int main()
{
std::string phone_number = "23";
std::string number[] = {
"0", "1", "2abc", "3def", "4ghi",
"5jkl","6mno", "7pqrs", "8tuv","9wxyz"
};
std::string tmp_set;
std::string set;
for(std::size_t i = 0; i < phone_number.size(); ++i)
{
tmp_set += number[static_cast<std::size_t>(phone_number[i] - '0')];
}
std::sort(tmp_set.begin(),tmp_set.end());
std::unique_copy(tmp_set.begin(),
tmp_set.end(),
std::back_inserter(set));
std::string current_set;
current_set.reserve(phone_number.size());
do
{
std::copy(set.begin(),
set.begin() + phone_number.size(),
std::back_inserter(current_set));
do
{
std::cout << current_set << std::endl;
}
while (std::next_permutation(current_set.begin(),current_set.end()));
current_set.clear();
}
while(next_combination(set.begin(),
set.begin() + phone_number.size(),
set.end()));
return 0;
}
template <typename Iterator>
inline bool next_combination(const Iterator first, Iterator k, const Iterator last)
{
/* Credits: Thomas Draper */
if ((first == last) || (first == k) || (last == k))
return false;
Iterator itr1 = first;
Iterator itr2 = last;
++itr1;
if (last == itr1)
return false;
itr1 = last;
--itr1;
itr1 = k;
--itr2;
while (first != itr1)
{
if (*--itr1 < *itr2)
{
Iterator j = k;
while (!(*itr1 < *j)) ++j;
std::iter_swap(itr1,j);
++itr1;
++j;
itr2 = k;
std::rotate(itr1,j,last);
while (last != j)
{
++j;
++itr2;
}
std::rotate(k,itr2,last);
return true;
}
}
std::rotate(first,k,last);
return false;
}
Well if you don't want a solution, I would implement it like this:
Use a vector V with each element drawn from a string. E.g. if it's 23, then your vector V, would have two vectors each containing 2ABC and 3DEF.
Iterate each digit like a counter through the associated string. Move right-to-left and when each digit overflows increment the one to the left, and reset, etc.
Display the counter at every iteration to obtain your "number".
Hint to compile errors:
there is no file called <multimap.h> in STL. it should be <map>
The problem is with getLetters function. multimap lmap has been passed by const reference. Hence, equal_range API on lmap would return pair of const_iterator not just iterator.
Below code demonstrate how to do it in simple steps(Recursively):
1.) Create vector of strings, and push strings which represents "possible characters resulting from that keypress" (0-key to 9-key).
2.) Since each keypress will serve to add ONLY one char to the resultant string, append only one character at a time and call the function recursively for the next keypress. Do it for each possible char at that keypress.
Demo:
void getCombination(vector<string> &combinations, string current, const string &A, int idx, const vector<string> &keyset){
if(idx >= A.size()) {
combinations.push_back(current);
return;
}
int key = (A[idx] - '0');
int len = keyset[key].length();
for( int i = 0; i < len; i++ ){
current.push_back(keyset[key][i]); //pick at once one char corresp. to that keypress
getCombination(combinations, current, A, idx+1, keyset);
current.pop_back();
}
}
vector<string> letterCombinations(string A) {
vector<string> combinations;
vector<string> keyset{"0", "1", "2abc", "3def", "4ghi", "5jkl", "6mno", "7pqrs", "8tuv", "9wxyz"};
getCombination(combinations, std::string({}), A, 0, keyset);
return combinations;
}
int main() {
vector<string> combinations = letterCombinations("23");
for(string word : combinations){
cout << word << ", ";
}
return 0;
}
Gives Output :
23, 2d, 2e, 2f, a3, ad, ae, af, b3, bd, be, bf, c3, cd, ce, cf,