C++ function equivalent to Python set() function - c++

I was wondering if there's a library function in C that can do the same job as set() in Python.
My purpose of using it is to check the total number of unique character in a string.
Code in Python example:
aString = "abbc"
print(len(set(aString)))
This code will output 3. Since the set of aString is {a,b,c}. Is there something similar I can use in C++?

My purpose of using it is to check the total number of unique character in a string
Yes you can create a std::set from the std::string and then get the sets' size using std::set::size() member function as shown below:
#include <iostream>
#include <string>
#include <set>
int main()
{
std::string aString = "abbc";
//create set from std::string
std::set<char> mySet( aString.begin() , aString.end() );
std::cout<< mySet.size();
return 0;
}
The output of the program can be seen here.
Note in C++ there is also option for std::unordered_set so that you would write:
//create unordered_set from std::string
std::unordered_set<char> mySet( aString.begin() , aString.end() ); //note the unordered_set used here instead of set

Related

Using C++'s reverse(string.begin(), string.end()) Why won't it let me hold it in a new variable?

Hello I am very new to programming and C++. I'm trying to make a program that checks if a string is a palindrome (a word that is the same backwards as it is forwards).
In order to do that I searched online about how to reverse a string and came across the reverse(string.begin(), string.end()) function from <bits/stdc++.h>.
I've made a function that can reverse the string written in the parameters and it works fine:
#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
std::string reverseStr(std::string str) {
reverse(str.begin(), str.end());
return str;
}
int main() {
std::cout << reverseStr("word");
}
But when I want to assign the reversed string into a new variable "reversedStr":
#include <iostream>
#include <vector>
#include <string>
#include <bits/stdc++.h>
std::string reverseStr(std::string str) {
std::string reversedStr;
reversedStr = reverse(str.begin(), str.end());
return reversedStr;
}
int main() {
std::cout << reverseStr("word");
}
Then when I try and compile it, it gives me this error.
C:/Program Files/mingw-w64/x86_64-8.1.0-posix-seh-rt_v6-rev0/mingw64/lib/gcc/x86_64-w64-mingw32/8.1.0/include/c++/bits/basic_string.h:776:7: note: no known conversion for argument 1 from 'void' to 'std::initializer_list<char>'
The terminal process "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command g++ -g main.cpp" terminated with exit code: 1.
If you wouldn't mind explaining what is happening that would be great! Thank you!
reverse reverses a collection in place and doesn't return it. If you want to do it to a new variable, then first copy the string to the variable then reverse that:
// pass the str argument by reference to avoid unnecessary copies
std::string reverseStr(const std::string& str) {
std::string reversedStr = str;
std::reverse(reversedStr.begin(), reversedStr.end());
return reversedStr;
}
As stated in documentation std::reverse() does not return anything so you cannot assign it's return value to a variable. Simplest solution would be:
std::string reverseStr(const std::string &str)
{
return std::string( str.rbegin(), str.rend() );
}
using reverse iterators to initialize and return temporary std::string
std::reverse() is used to reverse the elements within the range given by the two parameters, str.begin() and str.end() in your case. This does not return a new reversed string, instead it reverses the collection itself.
If you want the reversed content in a new variable, you must first copy the original string into a new string and then reverse the new string. Alternatively you could use std::reverse_copy() which copies the reverse contents to a new string without affecting the original. It takes in a third parameter that tells where the reversed content must be copied. Do note the reversed string variable must first be resized to the original string's size.
std::string reverseStr(std::string& str) {
std::string reversedStr;
reversedStr.resize(str.size());
std::reverse_copy(str.begin(), str.end(), reversedStr.begin());
return reversedStr;
}
Some additional info: std::reverse() and std::reverse_copy() are present in the <algorithm> header file. <bits/stdc++.h> is non-standard and compiler specific and hence should be avoided. Check this answer for more details: Why should I not #include <bits/stdc++.h>?

How do I concatenate a vector of strings in c++ with boost?

I have a vector of strings, like this:
{"abc"}{"def"}{"ghi"}
I want to concatenate them into a single string, with a separator like "-".
Is there a concise (pretty) way of doing this without using a typical for loop? I have c++03 and boost available to me.
Sure, boost provides a convenient algorithm for achieving what you are trying to do. In higher level languages you may have spotted a join function. Boost provides an equivalent algorithm in the join function.
#include <boost/algorithm/string/join.hpp>
using namespace std;
string data[] = {"abc","def","ghi"};
const size_t data_size = sizeof(data) / sizeof(data[0]);
vector<string> stringVector(data, data + data_size);
string joinedString = boost::algorithm::join(stringVector, "-");
Just for reference, there is currently a proposal for std::join, which you can check out here.
But since you have boost available, you can use boost::algorithm::join, which takes a sequence of strings and a separator, like so:
#include <iostream>
#include <string>
#include <vector>
#include <boost/algorithm/string/join.hpp>
int main() {
std::vector<std::string> words;
words.push_back("abc");
words.push_back("def");
words.push_back("ghi");
std::string result = boost::algorithm::join(words, "-");
std::cout << result << std::endl;
}
Prints:
abc-def-ghi
Another option using only the STL is:
std::ostringstream result;
if (my_vector.size()) {
std::copy(my_vector.begin(), my_vector.end()-1,
std::ostream_iterator<string>(result, "-"));
result << my_vector.back();
}
return result.str()

How to convert string into char *agv[]

I am building a command line tool and at the beginning whole line is a string. How could I convert:
string text = "-f input.gmn -output.jpg";
into
const char *argv[] = { "ProgramNameHere", "-f", "input.gmn", "-output.jpg" };
If I had to use getopt, and I knew I was starting with a white-space separated std::string, I'd do this:
#include <iostream>
#include <string>
#include <sstream>
#include <algorithm>
#include <iterator>
#include <vector>
#include <cassert>
#include <cstring>
int main() {
https://stackoverflow.com/questions/236129/how-to-split-a-string-in-c
// My input
std::string sentence = "-f input.gmn -output.jpg";
// My input as a stream
std::istringstream iss(sentence);
// Create first entry
std::vector<std::string> tokens;
tokens.push_back("ProgramNameHere");
// Split my input and put the result in the rest of the vector
std::copy(std::istream_iterator<std::string>(iss),
std::istream_iterator<std::string>(),
std::back_inserter(tokens));
// Now we have vector<string>, but we need array of char*. Convert to char*
std::vector<char *> ptokens;
for(auto& s : tokens)
ptokens.push_back(&s[0]);
// Now we have vector<char*>, but we need array of char*. Grab array
char **argv = &ptokens[0];
int argc = ptokens.size();
// Use argc and argv as desired. Note that they will become invalid when
// *either* of the previous vectors goes out of scope.
assert(strcmp(argv[2], "input.gmn") == 0);
assert(argc == 4);
}
See also: Split a string in C++?
Postscript: In the solution I provided, I used two language features introduced in C++2011: range-based for loops and type inference.
This code fragment will only compile if your compiler supports thew new features:
for(auto& s : tokens)
ptokens.push_back(&s[0]);
If you have an older C++ compiler, you might need to rewrite it using C++2003 features:
for(std::vector<string>::iterator it = tokens.begin(); it != tokens.end(); ++it)
ptokens.push_back(it->c_str());
or
for(std::vector<string>::size_type i = 0; i < tokens.size(); ++i)
ptokens.push_back(tokens[i].c_str());
I would recommend using boost::program_options to parse your program's arguments.
Otherwise if you are using MSVC, you might want to use the built-in __argc and __argv.
There is no portable way to get your program's image name, so you cannot get that information out of nowhere if you dropped it in the first place by discarding your original argv argument.
You could use the C strtok function to split your arguments ... actually scratch that, just use boost::algorithm::split with any_of(' ').

Parsing String to Array of Integers

I'm looking for a way to convert a string with specified dividers (such as slashes or spaces) into an array of the integers those dividers separate.
For example, if the user inputs 12/3/875/256, I need to retrieve the array {12, 3, 875, 256}. Ideally, it would be able to handle an arbitrary length.
I tried sweeping through the string character-by-character and storing everything that's not a divider in a temporary variable, which is added to the array the next time I encounter a divider character. Unfortunately, the type conversions are being a pain in the butt. Is there an easier way to do this?
You can set '/' to a delimiter and read using getline? then you'd have to put each one into a variable, and you'd need to know the size--maybe you can pass over the array and count the slashes? then you'd know that and can set up the array first. You might need to parse each string segment into an int, which may or may not be difficult. (haven't used c++ for a while, I don't remember a convenient way.)
See here for a small example of how this is done (3 posts down).
Try using the boost::tokenizer and boost::lexical_cast
strtok and strtol? (this is somewhat tongue in cheek. Strtok is usually not a good idea)
The splitting is covered in this Parsing String to Array of Integers
COnverting strings to int in C++ has quite a number of relevant questions https://stackoverflow.com/search?q=convert+string+to+int+c%2B%2B
What is the issue with the type conversions? It doesn't seem to be a block as far as I can see.
Can you show your code?
Take a look at this other answer. It even has an example of a tokenizer code using boost::tokenizer.
EDIT:
I copied the code there with the neccessary modifications:
#include <iostream>
#include <string>
#include <boost/foreach.hpp>
#include <boost/tokenizer.hpp>
#include <vector>
#include <boost/lexical_cast.hpp>
#include <iterator>
#include <algorithm>
using namespace std;
using namespace boost;
int main(int argc, char** argv)
{
string text = "125/55/66";
vector<int> vi;
char_separator<char> sep("/");
tokenizer<char_separator<char> > tokens(text, sep);
BOOST_FOREACH(string t, tokens)
{
vi.push_back(lexical_cast<int>(t));
}
copy(vi.begin(), vi.end(), ostream_iterator<int>(cout, "\n"));
}
Will print:
125
55
66
You could use a combination of Boost.split and Boost.lexical_cast to break up the string by whatever delimiters you want, and then you could lexical cast it all.
#include <boost/foreach.hpp>
#include <boost/lexical_cast.hpp>
#include <boost/algorithm/string.hpp>
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::string s = "11/23/2010";
std::vector<std::string> svec;
std::vector<int> ivec;
// split the string 's' on '/' delimiter, and the resulting tokens
// will be in svec.
boost::split(svec, s, boost::is_any_of("/"));
// Simple conversion - iterate through the token vector svec
// and attempt a lexical cast on each string to int
BOOST_FOREACH(std::string item, svec)
{
try
{
int i = boost::lexical_cast<int>(item);
ivec.push_back(i);
}
catch (boost::bad_lexical_cast &ex)
{
std::cout << ex.what();
}
}
return 0;
}
Untested...don't have boost on this machine.
Other ways you could use to convert std::string/char * to int types involve stringstream use directly, or C constructs like atoi.

How to declare an array of strings in C++?

I am trying to iterate over all the elements of a static array of strings in the best possible way. I want to be able to declare it on one line and easily add/remove elements from it without having to keep track of the number. Sounds really simple, doesn't it?
Possible non-solutions:
vector<string> v;
v.push_back("abc");
b.push_back("xyz");
for(int i = 0; i < v.size(); i++)
cout << v[i] << endl;
Problems - no way to create the vector on one line with a list of strings
Possible non-solution 2:
string list[] = {"abc", "xyz"};
Problems - no way to get the number of strings automatically (that I know of).
There must be an easy way of doing this.
C++ 11 added initialization lists to allow the following syntax:
std::vector<std::string> v = {"Hello", "World"};
Support for this C++ 11 feature was added in at least GCC 4.4 and only in Visual Studio 2013.
You can concisely initialize a vector<string> from a statically-created char* array:
char* strarray[] = {"hey", "sup", "dogg"};
vector<string> strvector(strarray, strarray + 3);
This copies all the strings, by the way, so you use twice the memory. You can use Will Dean's suggestion to replace the magic number 3 here with arraysize(str_array) -- although I remember there being some special case in which that particular version of arraysize might do Something Bad (sorry I can't remember the details immediately). But it very often works correctly.
Also, if you're really gung-ho about the one line thingy, you can define a variadic macro so that a single line such as DEFINE_STR_VEC(strvector, "hi", "there", "everyone"); works.
Problems - no way to get the number of strings automatically (that i know of).
There is a bog-standard way of doing this, which lots of people (including MS) define macros like arraysize for:
#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))
Declare an array of strings in C++ like this : char array_of_strings[][]
For example : char array_of_strings[200][8192];
will hold 200 strings, each string having the size 8kb or 8192 bytes.
use strcpy(line[i],tempBuffer); to put data in the array of strings.
One possiblity is to use a NULL pointer as a flag value:
const char *list[] = {"dog", "cat", NULL};
for (char **iList = list; *iList != NULL; ++iList)
{
cout << *iList;
}
You can use the begin and end functions from the Boost range library to easily find the ends of a primitive array, and unlike the macro solution, this will give a compile error instead of broken behaviour if you accidentally apply it to a pointer.
const char* array[] = { "cat", "dog", "horse" };
vector<string> vec(begin(array), end(array));
You can use Will Dean's suggestion [#define arraysize(ar) (sizeof(ar) / sizeof(ar[0]))] to replace the magic number 3 here with arraysize(str_array) -- although I remember there being some special case in which that particular version of arraysize might do Something Bad (sorry I can't remember the details immediately). But it very often works correctly.
The case where it doesn't work is when the "array" is really just a pointer, not an actual array. Also, because of the way arrays are passed to functions (converted to a pointer to the first element), it doesn't work across function calls even if the signature looks like an array — some_function(string parameter[]) is really some_function(string *parameter).
Here's an example:
#include <iostream>
#include <string>
#include <vector>
#include <iterator>
int main() {
const char* const list[] = {"zip", "zam", "bam"};
const size_t len = sizeof(list) / sizeof(list[0]);
for (size_t i = 0; i < len; ++i)
std::cout << list[i] << "\n";
const std::vector<string> v(list, list + len);
std::copy(v.begin(), v.end(), std::ostream_iterator<string>(std::cout, "\n"));
}
Instead of that macro, might I suggest this one:
template<typename T, int N>
inline size_t array_size(T(&)[N])
{
return N;
}
#define ARRAY_SIZE(X) (sizeof(array_size(X)) ? (sizeof(X) / sizeof((X)[0])) : -1)
1) We want to use a macro to make it a compile-time constant; the function call's result is not a compile-time constant.
2) However, we don't want to use a macro because the macro could be accidentally used on a pointer. The function can only be used on compile-time arrays.
So, we use the defined-ness of the function to make the macro "safe"; if the function exists (i.e. it has non-zero size) then we use the macro as above. If the function does not exist we return a bad value.
#include <boost/foreach.hpp>
const char* list[] = {"abc", "xyz"};
BOOST_FOREACH(const char* str, list)
{
cout << str << endl;
}
#include <iostream>
#include <string>
#include <vector>
#include <boost/assign/list_of.hpp>
int main()
{
const std::vector< std::string > v = boost::assign::list_of( "abc" )( "xyz" );
std::copy(
v.begin(),
v.end(),
std::ostream_iterator< std::string >( std::cout, "\n" ) );
}
You can directly declare an array of strings like string s[100];.
Then if you want to access specific elements, you can get it directly like s[2][90]. For iteration purposes, take the size of string using the
s[i].size() function.