How to use qsort for string in C++ - c++

I want to use qsort function to sort the characters in the strings using C++.
#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
int compare_str(void const *a,void const *b){
char const *aa=(char const *)a;
char const *bb=(char const *)b;
if(*aa==*bb) return 0;
else if(*aa>*bb) return 1;
else return -1;
}
int main(){
string str="cake";
int len=str.length();
qsort(str,len,sizeof(str[0]),compare_str);
cout<<str;
return 0;
}
But it throws :
20 42 [Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'void*' for argument '1' to 'void qsort(void*, size_t, size_t, int (*)(const void*, const void*))'
It would be great if anyone could provide an efficient way to do this.

I strongly recommend the modern method of
#include <algorithm>
#include <iostream>
#include <string>
int main()
{
std::string s("cake");
std::sort(s.begin(), s.end());
std::cout << s << std::endl; // Prints "acek".
return 0;
}
Plus, using std::sort over qsort allows the compiler to optimize better, so it's a win-win...

Your comparator for qsort expects C strings, not C++ std::strings. You should either declare str to be char str[]
char str[] = "cake";
qsort(str, strlen(cake), sizeof(char), compare_str); // Consider renaming to compare_char
or (better) use std::sort:
string str = "cake";
sort(str.begin(), str.end());

If you really want to do this, just pass a pointer to the string's contents:
qsort(str.c_str(),len,sizeof(str[0]),compare_str);
That said, you really should consider using the functions provided in the STL rather than those from the old C library...

You should use the function sort() under the header <algorithm>. This function is very flexible and you can use it in different manner. For sorting as you wish in question you can just write:
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
int main()
{
string s="cake";
sort(s.begin(), s.end());
cout << s << endl;
return 0;
}
//output: acek
again by using sort() we can implement it in a range. If you want to sort first two element , the code will be
sort(s.begin(), s.begin()+2);
for above code the output will be
//output: acke
so if we want to sort first n element then we can write
sort(s.begin,s.begin()+n);
we can also modify the sort function. In that case we have to pass three parameter instead of two. The third parameter will be a functions which returns a bool value.For example , if we want to sort in descending order then our code will be like this
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;
bool desc(char i, char j)
{
return i>j;
}
int main()
{
string s="cake";
sort(s.begin(), s.end(),desc);
cout << s << endl;
return 0;
}
//output: keca

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
int compare_str(void const *a,void const *b){
char const *aa=(char const *)a;
char const *bb=(char const *)b;
if(*aa==*bb) return 0;
else if(*aa>*bb) return 1;
else return -1;
}
int main(){
string str="cake";
int len=str.length();
qsort(const_cast<char*>(str.c_str()),len,sizeof(str[0]),compare_str);
cout<<str<<endl;
return 0;
}

Related

std::string::insert doesn't work with to_string(). CPP

I am writing a code to insert an integer at an index of the string, but after providing the integer to add as string, insert function is not giving the correct output.
It is giving the error that :
no matching member function to call for insert string
This is my code:
#include <iostream>
using namespace std;
int main()
{
string s = "45564528";
int x = 8;
s.insert(s.begin()+5,to_string(x));
cout<<s<<endl;
return 0;
}
The expected output is 455648528.
Looking at the documentation for std::string::insert() shows that it takes a char or an iterator range, not a std::string, which std::to_string() naturally returns. At least, this is the case for the overloads that take an iterator for the first argument.
#include <iostream>
#include <string> // CHANGED: Include what you use
// using namespace std; // CHANGED: Bad practice
int main()
{
std::string s = "45564528";
int x = 8;
// CHANGED: Create string from the int, and use the iterator range overload
// to account for multi-digit numbers
auto tmp = std::to_string(x);
s.insert(s.begin()+5, tmp.begin(), tmp.end());
std::cout << s << '\n'; // CHANGED: std::endl is rarely actually needed
return 0;
}
There is an overload that lets you insert another std::string, but the first argument must be an index and not an iterator. So this would work as well:
#include <iostream>
#include <string>
int main()
{
std::string s = "45564528";
int x = 8;
s.insert(5, std::to_string(x));
std::cout << s << '\n';
return 0;
}

Trying to convert a string into a int using stringstream

I'm trying check if a string representation equals given integer. I'm meant to use stringstream for this in a function. I also have an operator= for this as well.
I'm a little confused on how to execute these together and if I'm missing something. This is the last bit to an assignment I have, this is just a small snippet of my whole program. I can't find many guides on this, and I sense they all direct me to atoi or atod, which I'm not allowed to use.
#ifndef INTEGER
#define INTEGER
using std::string;
class Integer
{
private:
int intOne;
string strOne;
public:
Integer() {
intOne = 0;
}
Integer(int y) {
intOne = y;
}
Integer(string x) {
strOne = x;
}
void equals(string a);
Integer &operator=(const string*);
string toString();
};
#endif
In this header I'm not sure what argument I'm to use for the = operator.
#include <iostream>
#include <sstream>
#include <string>
#include "Integer.h"
using namespace std;
Integer &Integer::operator=(const string*)
{
this->equals(strOne);
return *this;
}
void Integer::equals(string a)
{
strOne = a;
toString(strOne);
}
string Integer::toString()
{
stringstream ss;
ss << intOne;
return ss.str();
}
#include <iostream>
#include <cstdlib>
#include <conio.h>
#include <string>
#include <ostream>
using namespace std;
#include "Menu.h"
#include "Integer.h"
#include "Double.h"
int main()
{
Integer i1;
i1.equals("33");
cout << i1;
}
Sorry if its a bad question I'm not too familiar with this type of assignment and will take any help I can get. Thanks.
you can use std::to_strig() that lets you convert from int to a string that represents the same number.
So if i understand correctly, you want to overload operator =, and that is a bad idea, since operator= is used for assignment not for comparison.
The correct operator signature is:
ReturnType operator==(const TypeOne first, const TypeSecond second) [const] // if outside of class
ReturnType operator==(const TypeSecond second) [const] // if inside class
Since you can't compare string to integer (they are different types), you need to write your comparisment function, since you don't have one i will write one for you:
bool is_int_equal_string(std::string str, int i)
{
std::string tmp;
tmp << i;
return tmp.str() == i;
}
Last but not least, you need to merge both of those, into one convenient operator:
// inside your Integer class
bool operator==(std::string value) const
{
std::stringstream tmp;
tmp << intOne;
return tmp.str() == ref;
}
Now you can use this operator, just like any other:
Integer foo = 31;
if (foo == "31")
cout << "Is equal" << endl;
else
cout << "Is NOT equal" << endl;
I hope this helps.
If you are allowed to use std::to_string then it would be the best.
Otherwise, you could create a function to handle the equality between the string and the integer with the use of std::stringstream:
Example:
bool Integer::equal(const string& str)
{
stringstream ss(str);
int str_to_int = 0;
ss >> str_to_int;
if (intOne == str_to_int)
return true;
else
return false;
}
Combine this with an if statement:
int main()
{
Integer i{100};
if (i.equal("100"))
cout << "true" << endl;
else
cout << "false" << endl;
}

char and char& no matching function for call

In order to compare if two string contain a same char, I was trying to loop through a string a and put the chars into a map.
So this is what I did.
string a = "abc";
unordered_map<char,int> m;
for (auto i:a){
m.insert(i,1);
}
But then there is an error:
no matching function for call to ‘std::unordered_map<char, int>::insert(char&, int)’
I don't quite understand what can I do here. Hope someone can help!
The problem in your code is that you try to insert a which is a std::string into an std::unordered_map<char, int> - you should be inserting i which is a char (each char from std::string a).
Moreover, even if you correctly used
m.insert(a,1);
it wouldn't compile because std::unordered_map::insert accepts a std::pair not 2 arguments from the template type. So you would need:
std::unordered_map<char, int> char_map;
char_map.insert(std::make_pair(c, 1));
Want you want to achieve can be done with std::set (if you don't care about the order of objects - chars - stored inside it)
#include <iostream>
#include <string>
#include <unordered_set>
int main()
{
std::string a = "abc";
std::unordered_set<char> char_set;
for (auto c : a)
char_set.insert(c);
for (auto c : char_set)
std::cout << c << ' ';
}
http://cpp.sh/3zrgr
Unfortunately you need to call std::make_pair first:
#include <iostream>
#include <unordered_map>
int main()
{
std::string a = "abc";
std::unordered_map<char,int> m;
for (int i = 0; i < a.size(); ++i)
m.insert(std::make_pair(a[i],1));
}

usage on c++ function pointer

I'm a newbie to C++, learning pointer of function recently, a little confused by usage of pointer of function;
I practiced the following code:
#include <iostream>
#include <sstream>
using namespace std;
int subtraction(int a,int b){
return a-b;
}
int main(int argc, const char * argv[])
{
int (*minus)(int,int)=subtraction;
cout<<minus(5,4);
return 0;
}
it works well;
so,I try a little variation:
#include <iostream>
#include <sstream>
using namespace std;
int subtraction(int a,int b){
return a-b;
}
int main(int argc, const char * argv[])
{
int *minus(int,int)=subtraction;//only here different!
cout<<minus(5,4);
return 0;
}
I practiced it in Xcode on Mac,it give me Error:
Illegal initializer (only variables can be initialized)
but I think compiler can recognized the two is same,why must have a pair of parenthesizes?
In your original code
int (*minus)(int,int)=subtraction;
declares minus as a function pointer that takes parameter int, int and returns int.
In your second code
int *minus(int,int)=subtraction;
declares minus as a function that takes parameter int, int and returns a pointer int *.
You can use a function name(which is automatically converted to a function pointer) to initialize a function pointer, but you can't initialize a function.
This is a matter of operator precedence. The function call operator () has a higher precedence than the dereference operator *. So you must use parentheses to specify the correct order of evaluation.
int *minus(int, int)
means: First call a function named minus, then dereference the return value (int* in this case).
int (*minus)(int, int)
means: First dereference "minus", which returns a function, and then call that function.
You have tagged your code C++ and using iostream so I can safely assume you are looking for a C++ solution.
In such scenario, its best to use class template std::function instead of the function pointer syntax that is prone to error.
#include <iostream>
#include <sstream>
#include <functional>
int subtraction(int a,int b){
return a-b;
}
int main(int argc, const char * argv[])
{
std::function<int(int,int)> minus = subtraction;
//int (*minus)(int,int)=subtraction;
std::cout<<minus(5,4);
return 0;
}
Alternatively, if you would still want to continue with pointer to function, typedefs are recommended
#include <iostream>
int subtraction(int a,int b){
return a-b;
}
typedef int (*MINUS)(int,int);
int main(int argc, const char * argv[])
{
MINUS minus = subtraction;
//int (*minus)(int,int)=subtraction;
std::cout<<minus(5,4);
return 0;
}
And finally, another widely used option is to use functors.
#include <iostream>
struct MINUS
{
int operator()(int a,int b){
return a-b;
}
};
int main(int argc, const char * argv[])
{
//int (*minus)(int,int)=subtraction;
MINUS minus;
std::cout<<minus(5,4);
return 0;
}

Sorting strings using qSort

According to this site, I have done the following program which sorts strings.
#include <cstdlib>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[])
{
int x;
puts("sortirebamde:");
for (x=0;x>sizeof(list)/sizeof(char);x++)
printf("%s\n",list[x]);
qsort(&list,(sizeof(list)/sizeof(char)),sizeof(list[0]),strcmp);
system("PAUSE");
return EXIT_SUCCESS;
}
Here is the error I get
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp invalid conversion from `int (*)(const char*, const char*)' to `int (*)(const void*, const void*)'
13 C:\Documents and Settings\LIBRARY\Desktop\string_sortireba.cpp initializing argument 4 of `void qsort(void*, size_t, size_t, int (*)(const void*, const void*))'
Please help
Please note: It is unusual to store C strings in two dimensional char arrays. It's more normal to have char *ary[], such as argv. That type cannot be sorted directly using qsort and strcmp, because qsort will pass char ** not char * to the comparison function. This is good for efficiency, the pointers can be swapped instead of the whole strings. The Linux manpage for qsort has some good example code with a correct comparison function.
You can't pass strcmp directly to qsort as its comparison function because qsort expects to pass pointers to void where strcmp expects pointers to const char. Given the required similarity between pointers to void and pointers to char, you could probably do it with a cast (for your code), but the cleaner way would be to write a function that takes the right types:
int cmpstr(void const *a, void const *b) {
char const *aa = (char const *)a;
char const *bb = (char const *)b;
return strcmp(aa, bb);
}
Note, however, that in C++ you'd normally want to use std::sort instead of qsort, and probably use std::string instead of char *, which case the sorting gets a lot simpler (and generally faster as well).
The fourth argument of qsort takes 2 void* pointers as args.So you need to define a compare function for yours.
refer to this link for more details.
You can pass strcmp directly to qsort
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char list[5][4]={"dat","mai","lik","mar","ana"};
int main(int argc, char *argv[]) {
int x;
puts("unsorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
qsort(list,sizeof(list)/sizeof(list[0]),sizeof(list[0]),strcmp);
puts("sorted:");
for (x=0;x<sizeof(list)/sizeof(list[0]);x++)
printf("%s\n",list[x]);
// system("PAUSE");
return EXIT_SUCCESS;
}
use C, not C++
Beyond why qsort fails, don't use it in C++.
#include <algorithm>
#include <iostream>
#include <iterator>
#include <string>
char const* const raw_data[5] = {"dat", "mai", "lik", "mar", "ana"};
std::vector<std::string> data (raw_data, raw_data + 5);
// would rarely be a global
// see below for code that needs to go here
int main() {
using namespace std;
cout << "before: " << data << "\n";
sort(data.begin(), data.end());
cout << "after: " << data << "\n";
return 0;
}
Boost has stream inserter overloads to output a vector directly, but here's one simple version. This goes into a header, rather than being copied and pasted continually:
template<class Stream, class Iter, class Ch>
void write_sequence(Stream& s, Iter begin, Iter end, Ch const* initial, Ch const* sep, Ch const* final) {
if (initial) {
s << initial;
}
if (begin != end) {
s << *begin;
++begin;
for (; begin != end; ++begin) {
if (sep) {
s << sep;
}
s << *begin;
}
}
if (final) {
s << final;
}
}
template<class T, class A>
std::ostream& operator<<(std::ostream& s, std::vector<T,A> const& value) {
write_sequence(s, value.begin(), value.end(), "[", ", ", "]");
return s;
}
More C++-Style - nowadays - with static_cast:
int scmp(const void * s1, const void * s2)
{
const char* _s1 = *static_cast<const char* const*>(s1);
const char* _s2 = *static_cast<const char* const*>(s2);
return strcmp(_s1, _s2);
}
And in main():
char *str_arr[] = { "one", "two", "three" };
qsort(str_arr, sizeof(str_array)/sizeof(char*), sizeof(char*), scmp);
Much easier is it with vector and std::sort.