0

I was reading about string and function pointer in C++. There I found a problem sort array of string based on first character value. And here is my code solution.

#include<bits/stdc++.h>
using namespace std;

bool compare1(const void *a, const void  *b)
{
    string c = *(string *)a;
    string d = *(string *)b;
    return c[0]<d[0];
}

int main()
{

    string str[3];
    int i;
    
    for(i=0;i<3;i++)
    {
        cout<<"Enter "<<i+1<<" string";
        cin>>str[i];
    }
    
    cout<<"Before sort"<<endl;
    for(i=0;i<3;i++)                               
    {
        cout<<str[i]<<" ";
    }
    
    cout<<endl;
    
    sort(str.begin(),str.end(),compare1);
    
    cout<<"After sort"<<endl;
    for(i=0;i<3;i++)
    {
        cout<<str[i]<<" ";
    }
    return 0;
}

But I am getting compile time error: [Error] request for member 'begin' in 'str', which is of non-class type 'std::string [3] {aka std::basic_string [3]}'

How to fix this issue?

8
  • It looks like you're confusing the C library's qsort with the C++ library's std::sort. Commented Sep 1, 2021 at 8:35
  • Unrelated to your problem but you can use a lambda to simplify your code: std::sort(std::begin(str), std::end(str), [](const std::string& s1, const std::string& s2) { return s1[0] < s2[0]; }); Commented Sep 1, 2021 at 8:35
  • 1
    It looks almost like you're learning programming and C++ from a so-called "competition" or "online judge" site. Don't do that, that's not what they're for. Get some good books to read, and take some classes. You need to do that because you have multiple basic errors in your code. Commented Sep 1, 2021 at 8:36
  • 1
    you shouldn't use void*, especially when the method can only work correctly when string*s are passed (though you dont need pointers in the first place) Commented Sep 1, 2021 at 8:39
  • Aside from the actual answers, you should make sure that your comparison function also checks whether the strings actually have a first element, if you don't want to have a segmentation fault in wait. Commented Sep 1, 2021 at 9:05

3 Answers 3

2

Two issues:

  1. str is a raw array and doesn't have member function named begin and end. You can use std::begin and std::end instead.

  2. std::sort passes the elements for comparing; compare1 should accept std::strings instead of pointers.

E.g.

bool compare1(const string& c, const string& d)
{
    // for empty strings
    if (c.length() == 0 || d.length() == 0)
        return c.length() < d.length();

    return c[0] < d[0];
}

then

sort(std::begin(str), std::end(str), compare1);

LIVE

Sign up to request clarification or add additional context in comments.

5 Comments

I propose that you add something that catches whether the strings are of length zero in the comparator. Wouldn't want there to be a segmentation fault in wait.
@Aziuth Nice idea.
@Hashinclude It's just how std::sort works, you have to follow its rules. The types Type1 and Type2 must be such that an object of type RandomIt can be dereferenced and then implicitly converted to both of them.​
Okay thanks I got confused it with qsort() in C language where we can use const void* inside comparator and then typecast it to desired data type.
@Hashinclude C and C++ are quite different. In most cases you won't use raw pointers (and arrays) in C++.
1

Standard C++ arrays don't have a begin member.

Either use the function-style overloads:

sort(std::begin(str), std::end(str), compare1);

or use a std::vector<std::string> str instead.

or use std::array<std::string, 3>, which is a fixed size but does support the begin member.

1 Comment

Or since the size of the array is known at compile-time, std::array<std::string, 3>
1

I suppose that string is the name of the standard class std::string.

You declared an array of three objects of the type string

string str[3];

Arrays are not classes. So they do not have member functions including begin and end.

Thus this statement

sort(str.begin(),str.end(),compare1);

is incorrect.

There are general functions std::begin and std::end declared in the header that could be used for example like

#include <iterator>

//...

sort( std::begin( str ), std::end( str ), compare1 );

Or without these functions you could write

sort( str, str + 3, compare1 );

On the other hand, the function compare1 is incorrect. The function sort passes to the comparison function two objects of the type std::string or references to such object.

It must be declared and defined at least the following way

bool compare1( const std::string &s1, const std::string &s2 )
{
    return s1[0] < s2[0];
}

4 Comments

Why we can't use void* inside compare function?
@Hashinclude Because the function sort does not passes to the comparison function pointers.
So is there any concept that we can use void* inside compare function only when we are operating on basic data type like (char, array pointer of char type)?
@Hashinclude You can use the type void * for parameters of a comparison function then it gets arguments of pointer types.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.