简体   繁体   中英

Trouble in sorting vector strings using std::sort() using custom compare function

I am trying to sort strings according to a rule. The c++ code works in most cases but in some cases gives an error:

  terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid

I have seen this error before, it happens when we try to initialize a string as null pointer or 0 (which is internally converted as a null pointer). I have checked that error is happening during sorting and only when I use the custom function for comparison. Once again, I don't know why it is happening only in certain cases.

The code is:

#include <algorithm>
#include <sstream>
#include <iostream>
#include <vector>
#include <string>

using std::vector;
using std::string;

bool greater(string a, string b) {
  int i = 0;
  a = a + a[0];
  b = b + b[0];
  while(i<a.size() && i<b.size()) {
    if(a[i] != b[i]) {
      if(a[i] - '0' > b[i] - '0')
      return true;
      else return false;
    }
    i++;
  }
  
}

string largest_number(vector<string> a) {
  std::sort(a.begin(), a.end(), greater);
  std::stringstream ret;
  for (size_t i = 0; i < a.size(); i++) {
    ret << a[i];
  }
  string result;
  ret >> result;
  return result;
}

int main() {
  int n;
  std::cin >> n;
  vector<string> a(n);
  for (size_t i = 0; i < a.size(); i++) {
    std::cin >> a[i];
  }
  std::cout << largest_number(a);
  return 0;
}

One of the cases where it gives error is:

100  
2 8 2 3 6 4 1 1 10 6 3 3 6 1 3 8 4 6 1 10 8 4 10 4 1 3 2 3 2 6 1 5 2 9 8 5 10 8 7 9 6 4 2 6 3 8 8 9 8 2 9 10 3 10 7 5 7 1 7 5 1 4 7 6 1 10 5 4 8 4 2 7 8 1 1 7 4 1 1 9 8 6 5 9 9 3 7 6 3 10 8 10 7 2 5 1 1 9 9 5

SOLUTION: Thanks for help. The error was occurring as the compare function was not returning anything once it goes out of the loop. Here is the updated function that works.

bool greater(string a, string b) {
  int i = 0;
  a = a + a[0];
  b = b + b[0];
  while(i<a.size() && i<b.size()) {
      if(a[i] > b[i])
        return true;
    i++;
  }
  return false; 
}

The only problem I can see with the code (actually I tried in an online compiler and it gave me this warning) is that you don't return anything from greater if the two strings are equal:

bool greater(string a, string b) {
  int i = 0;
  a = a;
  b = b;
  while(i<a.size() && i<b.size()) {
    if(a[i] != b[i]) {
      if(a[i] - '0' > b[i] - '0')
      return true;
      else return false;
    }
    i++;
  }
  // <---- what about here?
}

Try inserting a return statement. (Of course, if two things are equal then neither is greater than the other, so specifically it is a return false you want.) Falling off the end of a function without a return statement is undefined behaviour (except for int main() or any function returning void ), so you could expect to see anything at all when this happens, including the type of crash you got.

[Edit: as gst says, you also get to that point if one string is a prefix of the other eg "1" and "10" . So you'll need a bit more code to test which is which, rather than just a return false . But you could see if that one line would fix the crash: it would be logically wrong but at least not undefined behaviour.]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM