I am trying to sort two cstrings, and I'm running into trouble while using qsort to complete this task. I believe my problems are that I'm not sure what to put as the parameters for compare, if my compare function is correct, or if it is even necessary for me to write my own compare function at all.
#include <algorithm>
#include <iterator>
#include <iostream>
#include <cstring>
#include <string>
using namespace std;
bool anagram(const char *s1, const char *s2);
int main() {
string sWord1, sWord2;
char cWord1[10], cWord2[10];
char *cPtr1 = cWord1;
char *cPtr2 = cWord2;
cout << "Enter Word 1: ";
cin.getline(cWord1, 10);
cout <<"\nEnter Word 2: ";
cin.getline(cWord2, 10);
anagram(cPtr1, cPtr2);
return 0;
}
bool anagram(const char *s1, const char *s2) {
char w1[10];
char w2[10];
for (int i = 0; i < 10; i++) {
w1[i] = s1[i];
w2[i] = s2[i];
}
sort(w1.begin(), w1.end()); //DOES NOT WORK
sort(begin(w1), end(w1)); //DOES NOT WORK - Says begin is not in std
}
The correct way to sort an array of chars in C++ is to use std::sort:
#include <algorithm>
#include <iterator>
bool anagram(const char *s1, const char *s2) {
// ...
std::sort(std::begin(w1), std::end(w1));
// If you can't use C++11, then use
// std::sort(w1, w1 + 10);
// ...
}
If you have to use qsort for some weird reason, it expects a function pointer taking two const void * parameters that point to the elements to be compared:
int compare(const void * e1, const void *e2){
char c1 = *static_cast<const char *>(e1), c2 = *static_cast<const char *>(e2);
return c1 - c2; // <0 if c1 < c2, etc.
}
qsort(w1, 10, sizeof(char), compare);
This is slow, error prone, and causes undefined behavior for nontrival types, and is not recommended.
This is your code as you were trying to write it. But as has been pointed out, qsort is not the preferred approach.
#include <cstdlib>
#include <cstring>
#include <iostream>
int compare(const void* c1, const void* c2) {
const char& cc1 = *static_cast<const char*>(c1);
const char& cc2 = *static_cast<const char*>(c2);
return cc1 - cc2; }
bool anagram(const char* s1, const char* s2) {
char w1[10];
char w2[10];
for (int i = 0; i < 10; i++) {
w1[i] = s1[i];
w2[i] = s2[i]; }
qsort(w1, 10, sizeof(char), compare);
qsort(w2, 10, sizeof(char), compare);
return 0 == strncmp(w1, w2, 10); }
int main(int, char* []) {
std::cout << anagram("abcdefghij", "bcdaghefji") << std::endl;
std::cout << anagram("abcdefghij", "xxxxxxxxxx") << std::endl;
return 0; }
Related
I am currently stuck with a slight problem where I want to swap contents in a std::string.
#include <iostream>
#include <string>
void swap(char* t1, char* t2); // function parameter is wrong syntax
int main(){
std::string message = "ABC";
swap(message[0], message[1]); // parameter probably wrong here
return 0;
}
void swap(char * t1, char * t2){
return;
}
GOAL: I wish to do a simple swap of the contents in index 0 and 1 such that after swapping it, the message "ABC" becomes "BAC". As you can see, I tried doing it like I was using a normal array, but it seems this logic doesn't work with strings. I understand that if I switch to
char a[] = "ABC";
it would work, but I wanna try it using the string class.
The type of message[n] is char. So the signature of your swap function should be
swap(char& a, char& b);
But you should use std::swap instead.
#include <iostream>
#include <string>
#include <utility>
int main(){
std::string message = "ABC";
std::swap(message[0], message[1]);
std::cout << message << std::endl;
}
Try the following
#include <iostream>
#include <string>
void swap( char *c1, char *c2 )
{
char tmp = *c1;
*c1 = *c2;
*c2 = tmp;
}
void swap( char &c1, char &c2 )
{
char tmp = c1;
c1 = c2;
c2 = tmp;
}
int main()
{
std::string message = "ABC";
swap( message[0], message[1] );
swap( &message[1], &message[2] );
return 0;
}
If you want to use standard utilities then the program above can look the following way
#include <iostream>
#include <string>
#include <utility>
int main()
{
std::string message = "ABC";
std::swap( message[0], message[1] );
message[1] = std::exchange( message[2], message[1] );
return 0;
}
There is a string like this: M90I4D7
I need to push it in to this kind of struct:
struct CigarOp {
char Type; //!< CIGAR operation type (MIDNSHPX=)
uint32_t Length; //!< CIGAR operation length (number of bases)
//! constructor
CigarOp(const char type = '\0',
const uint32_t& length = 0)
: Type(type)
, Length(length)
{ }
};
which means I need to split it into 3 groups and each of them is a CigarOp( 'M' ,90 'I', 4 'D' ,7 )
Assuming that the string is of the form ([A-Z][0-9]+)*, you could quite simply do something like this:
#include <sstream>
...
std::vector<CigarOp> cigars;
std::istringstream parser("M90I4D7");
char c;
std::uint32_t l;
while(parser >> c >> l) {
cigars.push_back(CigarOp(c, l));
}
Note that this code doesn't do any sort of validation. If validation is necessary, one way to achieve it is to use Boost.Spirit (found on http://boost.org):
#include <boost/spirit/include/qi.hpp>
#include <boost/fusion/adapted/struct.hpp>
#include <cstdint>
#include <iostream>
struct CigarOp {
char Type;
std::uint32_t Length;
};
BOOST_FUSION_ADAPT_STRUCT(CigarOp, (char, Type) (std::uint32_t, Length))
int main() {
using boost::spirit::qi::phrase_parse;
using boost::spirit::qi::char_;
using boost::spirit::qi::uint_;
using boost::spirit::qi::standard::space;
std::vector<CigarOp> cigars;
std::string s = "M90I4D7";
std::string::const_iterator first = s.begin(), last = s.end();
bool r = phrase_parse(first, last, *(char_ >> uint_), space, cigars);
if(r && first == last) {
// string was well-formed
for(auto const &cigar : cigars) {
std::cout << cigar.Type << ", " << cigar.Length << '\n';
}
}
}
how about:
#include <cstdio>
#include <cctype>
#include <vector>
#include <iostream>
#include <cstdlib>
using namespace std;
struct CigarOp {
char op; //!< CIGAR operation type (MIDNSHPX=)
int size; //!< CIGAR operation length (number of bases)
static int parse(const char* s,vector<CigarOp>& v)
{
char* p=(char*)(s);
while(*p!=0)
{
char* endptr;
CigarOp c;
c.op = *p;
if(!isalpha(c.op)) return -1;
++p;
if(!isdigit(*p)) return -1;
c.size =strtol(p,&endptr,10);
if(c.size<=0) return -1;
v.push_back(c);
p=endptr;
}
return 0;
}
};
int main(int argc,char** argv)
{
vector<CigarOp> cigar;
if(CigarOp::parse("M90I4D7",cigar)!=0) return -1;
for(size_t i=0;i< cigar.size();++i)
{
cout << cigar[i].op << ":" << cigar[i].size << endl;
}
return 0;
}
btw , for bioinformatics, you should ask biostars.org.
I have a long list of some good old fashioned c style strings:
const char * p1key = PROPERTY_MAX_THREADS;
const char * p1value = "12";
const char * p2key = PROPERTY_MAX_FRAMES;
const char * p2value = "400";
const char * p3key = PROPERTY_MAX_FRAMEMEMORY;
const char * p3value = "140";
...
Then I do some stuff with them:
// write p1, p2, p3, pn to disk in fancy format
At the end I want to be able to write a loop and compare the written values to the original values.
int numProperties = 20;
for (int i = 0; i < numProperties; ++i) {
// on the first iteration, access p1 key/value
// on the second, access p2 key/value
// ...
}
How can I access p1 on the first iteration, p2 on the second, etc? Would an array of pointers help? I'm struggling to come up with the syntax to make this work. Any help would be very much appreciated.
Edit:
I would consider the best answer to show both the C and C++ way
INTRODUCTION
You'd have to store the pointers in some sort of container to be able to iterate over them in the manner as you propose.
Since you are dealing with pairs, std::pair from <utility> seems like a perfect match. Wrapping these std::pairs in a container such as std::vector will make it very easy to iterate over them in a clean manner.
SAMPLE IMPLEMENTATION
#include <iostream>
#include <utility>
#include <vector>
#define PROPERTY_MAX_THREADS "max_threads"
#define PROPERTY_MAX_FRAMES "max_frames"
#define PROPERTY_MAX_FRAMEMEMORY "max_fmemory"
const char * p1key = PROPERTY_MAX_THREADS;
const char * p1value = "12";
const char * p2key = PROPERTY_MAX_FRAMES;
const char * p2value = "400";
const char * p3key = PROPERTY_MAX_FRAMEMEMORY;
const char * p3value = "140";
int
main (int argc, char *argv[])
{
std::vector<std::pair<char const *, char const *>> properties {
{ p1key, p1value }, { p2key, p2value }, { p3key, p3value }
};
std::cout << "properties:\n";
for (auto& it : properties) {
std::cout << " " << it.first << " = " << it.second << "\n";
}
}
properties:
max_threads = 12
max_frames = 400
max_fmemory = 140
I TRIED THE ABOVE BUT IT DOESN'T COMPILE, WHY?
The previously written snippet makes use of features introduced in C++11, if you are unable to compile such code you will need to resort to functionality that your compiler does provide.
Below is a modified implementation that can be compiled by any compiler that supports C++03:
int const PROPERTIES_LEN = 3;
std::pair<char const *, char const*> properties[PROPERTIES_LEN] = {
std::make_pair (p1key, p1value),
std::make_pair (p2key, p2value),
std::make_pair (p3key, p3value)
};
for (int i = 0; i < PROPERTIES_LEN; ++i) {
std::cout << properties[i].first << " = " << properties[i].second << "\n";
}
You tagged it C++, so I'm going to give the C++ suggestion.
#include <iostream>
#include <vector>
#include <utility>
#define PROPERTY_MAX_THREADS "1"
#define PROPERTY_MAX_FRAMES "2"
#define PROPERTY_MAX_FRAMEMEMORY "3"
const char * p1key = PROPERTY_MAX_THREADS;
const char * p1value = "12";
const char * p2key = PROPERTY_MAX_FRAMES;
const char * p2value = "400";
const char * p3key = PROPERTY_MAX_FRAMEMEMORY;
const char * p3value = "140";
int main() {
using namespace std;
vector<pair<const char*,const char *>> collection =
{{p1key,p1value},{p2key,p2value},{p3key,p3value}};
for(auto &ele : collection){
cout << "key:" << ele.first
<< "value:" << ele.second << endl;
}
return 0;
}
alternatively just declare it as a collection from the beginning
#include <iostream>
#include <string>
#include <vector>
#include <utility>
#define PROPERTY_MAX_THREADS "1"
#define PROPERTY_MAX_FRAMES "2"
#define PROPERTY_MAX_FRAMEMEMORY "3"
int main() {
using namespace std;
vector<pair<const string,const string>> collection =
{
{PROPERTY_MAX_THREADS, "12" },
{PROPERTY_MAX_FRAMES, "400"},
{PROPERTY_MAX_FRAMEMEMORY, "140"}
};
for(auto &ele : collection){
cout << "key:" << ele.first
<< " value:" << ele.second << endl;
}
return 0;
}
In C you can do this way.
#define STRA_END 0
const char* keyArray[] = {
"string1",
"string2",
"string3",
STRA_END
}
const char* valueArray[] = {
"string1",
"string2",
"string3",
STRA_END
}
main(){
int i;
for( i=0; keyArray[i]!=0; ++i )
doSometingToString(keyArray[i], valueArray[i]);
}
I have a vector of strings. Need help figuring out how to convert it into vector of integers in order to be able to work with it arithmetically. Thanks!
#include <iostream>
#include <string>
#include <vector>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
//HELP NEEDED HERE
//CONVERSION CODE from vector<string> to vector<int>
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
There are mulitple ways of converting a string to an int.
Solution 1: Using Legacy C functionality
int main()
{
//char hello[5];
//hello = "12345"; --->This wont compile
char hello[] = "12345";
Printf("My number is: %d", atoi(hello));
return 0;
}
Solution 2: Using lexical_cast(Most Appropriate & simplest)
int x = boost::lexical_cast<int>("12345");
Surround by try-catch to catch exceptions.
Solution 3: Using C++ Streams
std::string hello("123");
std::stringstream str(hello);
int x;
str >> x;
if (!str)
{
// The conversion failed.
}
Use boost::lexical_cast. And surround it with try-catch block.
try
{
for (size_t i=0; i<vectorOfStrings.size(); i++)
{
vectorOfIntegers.push_back(boost::lexical_cast<int>(vectorOfStrings[i]));
}
}
catch(const boost::bad_lexical_cast &)
{
//not an integer
}
Or you can use Boost.Spirit parser (which someone claims is faster than even atoi()) as:
int get_int(const std::string & s)
{
int value = 0;
std::string::const_iterator first = s.begin();
bool r = phrase_parse(first,s.end(),*int_[ref(value)=_1], space);
if ( !r || first != s.end()) throw "error";
return value;
}
//Usage
int value = get_int("17823");
std::cout << value << std::endl; //prints 17823
The full demo using your code : http://ideone.com/DddL7
#include <string>
#include <vector>
#include <iterator>
#include <algorithm>
#include <boost/lexical_cast.hpp>
using namespace std;
int stringToInteger(const std::string& s)
{
return boost::lexical_cast<int>(s);
}
int main(int /*argc*/, char* /*argv*/[])
{
vector<string> vectorOfStrings;
// ..
vector<int> vectorOfIntegers;
std::transform(vectorOfStrings.begin(), vectorOfStrings.end(), std::back_inserter(vectorOfIntegers), stringToInteger);
// ..
}
You can replace the implementation of stringToInteger(..) with your preferred conversion function.
Here is the working version made up using the above comments.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
int x;
for (int i=0; i<vectorOfStrings.size(); i++)
{
stringstream str(vectorOfStrings.at(i));
str >> x;
vectorOfIntegers.push_back(x);
}
int sum = 0;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
What about:
#include <algorithm>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
It can convert vector<string> into vector<int>, and also other container<T1> into container2<T2>, e.g.: list -> list.
Full code:
#include <iostream>
#include <vector>
#include <algorithm>
#include <iterator>
#include <string>
#include <boost/lexical_cast.hpp>
template<typename C1, typename C2>
void castContainer(const C1& source, C2& destination)
{
typedef typename C1::value_type source_type;
typedef typename C2::value_type destination_type;
destination.resize(source.size());
std::transform(source.begin(), source.end(), destination.begin(), boost::lexical_cast<destination_type, source_type>);
}
template<typename T, typename T2>
std::vector<T>& operator<<(std::vector<T>& v, T2 t)
{
v.push_back(T(t));
return v;
}
main(int argc, char *argv[])
{
std::vector<std::string> v1;
v1 << "11" << "22" << "33" << "44";
std::cout << "vector<string>: ";
std::copy(v1.begin(), v1.end(), std::ostream_iterator<std::string>(std::cout, ", "));
std::cout << std::endl;
std::vector<int> v2;
castContainer(v1, v2);
std::cout << "vector<int>: ";
std::copy(v2.begin(), v2.end(), std::ostream_iterator<int>(std::cout, ", "));
std::cout << std::endl;
}
There are two independent tasks.
Convert a single string to an integer
Having something that can convert from A to B, convert std::vector<A> to std::vector<B>
I suggest you try to do them separately, and then combine the results. If one of these tasks proves difficult, you will be able to ask a more focused question.
The most general way to convert strings to integers is with stringstream and a function template. You can optionally set the base for the conversion if you're dealing with hexadecimal. The boost library would also be helpful in your example.
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>
#include <boost/static_assert.hpp>
#include <boost/foreach.hpp>
/******************************************************************************
* Handy string to type conversion
* First parameter is the string to convert
* Second optional parameter is the number base, e.g. std::hex
*
* Because this is a function template, the compiler will instantiate one
* instance of the function per type
*****************************************************************************/
// the std::dec thingy is actually a function, so extra glue required.
typedef std::ios_base& (*ios_base_fn)( std::ios_base& str );
template <class T>
T strtotype( const std::string& s, ios_base_fn base = std::dec )
{
// C++ can't convert 8-bit values, they are *always* treated
// as characters. :( At least warn the user.
// this gives a cryptic error message, but better than nothing.
BOOST_STATIC_ASSERT( sizeof(T) > 1 );
T val;
std::istringstream iss(s);
iss >> base >> val;
if( iss.fail() )
throw std::runtime_error( "Error: strtotype(): Can't convert string '" + s + "' to numeric value" );
return val;
}
using namespace std;
int main(int argc, char* argv[]) {
vector<string> vectorOfStrings;
vectorOfStrings.push_back("1");
vectorOfStrings.push_back("2");
vectorOfStrings.push_back("3");
for (int i=0; i<vectorOfStrings.size(); i++)
{
cout<<vectorOfStrings.at(i)<<endl;
}
vector<int> vectorOfIntegers;
for( size_t i = 0; i < vectorOfStrings.size(); i++ )
vectorOfIntegers.push_back( strtotype<int>( vectorOfStrings[i] ));
// or better yet, use boost_foreach
BOOST_FOREACH( const string& s, vectorOfStrings )
vectorOfIntegers.push_back( strtotype<int>( s ));
int sum;
for (int i=0; i<vectorOfIntegers.size(); i++)
{
sum += vectorOfIntegers.at(i);
}
cout<<sum<<endl;
cin.get();
return 0;
}
If you don't want or can't use boost, you can remove the sizeof() check in strtotype. However, be careful never to try to convert to strings to individual bytes. Doing so will fail silently by only converting the first nibble of the byte.
If you're suing GNU tools, then compile like so:
g++ -Wall -O3 -I /path/to/boost/include main.cpp
or, if you delete the boost related bits:
g++ -Wall -O3 main.cpp
My question is similar to this, but I have two strings (as char *) and the task is to replace strnicmp function (avaible only for MS VC) with something like boost::iequals.
Note strnicmp is not stricmp - it only compares first n characters.
Is there any solution simplier than this:
void foo(const char *s1, const char *s2)
{
...
std::string str1 = s1;
std::string str2 = s2;
int n = 7;
if (boost::iequals(str1.substr(0, n), str2)) {
...
}
}
If it's really necessary, write your own function:
bool mystrnicmp(char const* s1, char const* s2, int n){
for(int i=0; i < n; ++i){
unsigned char c1 = static_cast<unsigned char>(s1[i]);
unsigned char c2 = static_cast<unsigned char>(s2[i]);
if(tolower(c1) != tolower(c2))
return false;
if(c1 == '\0' || c2 == '\0')
break;
}
return true;
}
For case insensitivity, you need a custom comparison function
(or functor):
struct EqIgnoreCase
{
bool operator()( char lhs, char rhs ) const
{
return ::tolower( static_cast<unsigned char>( lhs ) )
== ::tolower( static_cast<unsigned char>( rhs ) );
}
};
If I understand correctly, you're checking for a prefix. The
simplest way to do this is:
bool
isPrefix( std::string const& s1, std::string const& s2 )
{
return s1.size() <= s2.size()
&& std::equals( s1.begin(), s1.end(), s2.begin(), EqIgnoreCase() );
}
(Note the check of the sizes. s1 can't be a prefix of s2 if
it it longer than s2. And of course, std::equals will
encounter undefined behavior if called with s1 longer than
s2.)
For a function defined in terms of C strings (character pointers) going "up" to STL strings seems horribly inefficient, but maybe that's totally premature thinking on my part.
I would consider a straight C solution "simpler", but again that depends on one's perspective.
#include <ctype.h>
void foo(const char *s1, const char *s2)
{
size_t i, n = 7;
for(i = 0; i < n; i++)
{
if(tolower(s1[i]) != tolower(s2[i]))
return;
if(s[i] == '\0' && s2[i] == '\0')
break;
}
/* Strings are equal, do the work. */
...
}
This assumes that if both strings end before the length of the prefix has been exhausted, it's a match.
Of course the above assumes ASCII strings where tolower() makes sense.
I suggest to write the function yourselfs, like this:
bool strnicmp2(const char *s, const char *t, size_t n) {
while (n > 0 && *s && *t && tolower(*s) == tolower(*t)) {
++s;
++t;
--n;
}
return n == 0 || !*s || !*t;
}
something like this ought to work..
#include <iostream>
#include <string>
#include <cctype>
#include <cstring>
#include <algorithm>
struct isequal
{
bool operator()(int l, int r) const
{
return std::tolower(l) == std::tolower(r);
}
};
bool istrncmp(const char* s1, const char* s2, size_t n)
{
size_t ls1 = std::strlen(s1);
size_t ls2 = std::strlen(s2);
// this is strict, but you can change
if (ls1 < n || ls2 < n)
return false;
return std::equal(s1, s1 + n, s2, isequal());
}
int main(void)
{
std::cout << istrncmp("fooB", "fooA", 3) << std::endl;
std::cout << istrncmp("fooB", "fooA", 5) << std::endl;
std::cout << istrncmp("fooB", "f1oA", 3) << std::endl;
return 0;
}
I don't know if this counts as simpler or not, but it has fewer lines and speed should be pretty good.
#include <boost/iterator/transform_iterator.hpp>
#include <algorithm>
#include <cctype>
bool equal_insensitive_n( char const *a, char const *b, size_t n ) {
n = std::min( n, std::min( ::strlen( a ) + 1, ::strlen( b ) + 1 ) );
#define tilc(S) boost::make_transform_iterator( (S), ::tolower )
return std::equals( tilc(a), tilc(a) + n, tilc(b) );
#undef tilc
}