С ++ сортировка со структурами - PullRequest
14 голосов
/ 17 мая 2009

Мне трудно справиться с этой проблемой, которая требует своего рода имен клиентов, идентификаторов клиентов и, наконец, суммы к оплате. У меня есть вся программа, но я не могу определить последний прототип, необходимый для сортировки. У меня есть структура с именем Customers, и я также предоставлю часть int main (). Мне просто нужна помощь, чтобы начать работу с прототипом SortData ().

struct Customers {
    string Name;
    string Id;
    float OrderAmount;
    float Tax;
    float AmountDue;
};

const int MAX_CUSTOMERS = 1000;
bool MoreCustomers(int);
Customers GetCustomerData();
void OutputResults(Customers [], int);
void SortData(const int, const int, Customers []);

int main() {
    Customers c[MAX_CUSTOMERS]; 
    int Count = 0;      
    do {
      c[Count++] = GetCustomerData();   
    } while (MoreCustomers(Count));     


    for (int i = 0; i < Count; i++) {
        c[i].Tax = 0.05f * c[i].OrderAmount;        
        c[i].AmountDue = c[i].OrderAmount + c[i].Tax;   
    }

    SortData(0, Count, c);     //0:Sorts by customer name       
    OutputResults(c, Count);            
    GeneralSort(1, Count, c);   //1:Sorts by ID     
    OutputResults(c, Count);        
    GeneralSort(2, Count, c);   //2: Sorts by amount due        
    OutputResults(c, Count);        

    return 0;                       
}


void SortData(const int SortItem, const int count, CustomerProfile c[]) {
     //0: Sort by name
    //1: Sort by ID
    //3: Sort by amount due
}

Ответы [ 5 ]

34 голосов
/ 17 мая 2009

Вы должны использовать стандартную функцию сортировки C ++, std::sort, объявленную в заголовке <algorithm>.

Когда вы сортируете, используя пользовательскую функцию сортировки, вы должны предоставить функцию предиката , которая сообщает, является ли левое значение меньше правого значения. Поэтому, если вы хотите сначала отсортировать по имени, затем по идентификатору, а затем по сумме, все в порядке возрастания, вы можете сделать:

bool customer_sorter(Customer const& lhs, Customer const& rhs) {
    if (lhs.Name != rhs.Name)
        return lhs.Name < rhs.Name;
    if (lhs.Id != rhs.Id)
        return lhs.Id < rhs.Id;
    return lhs.AmountDue < rhs.AmountDue;
}

Теперь передайте эту функцию вашему вызову sort:

std::sort(customers.begin(), customers.end(), &customer_sorter);

Предполагается, что у вас есть контейнер STL (а не массив, как в вашем примере кода) с именем customers, содержащий клиентов.

13 голосов
/ 17 мая 2009

Часто упускают из виду, что вы можете использовать функции диапазона STL с массивами на основе Си, как в вашем примере. Так что вам на самом деле не нужно переходить к использованию контейнера на основе STL (я не буду обсуждать преимущества этого здесь: -)).

Итак, основываясь на ответе Криса, вы можете вызвать сортировку следующим образом:

std::sort( customers, customers+Count, &customer_sorter);
2 голосов
/ 17 мая 2009

Вам нужно только написать функцию сравнения, которая сравнивает два типа CustomerProfile. Если у вас есть эта функция, вы можете использовать сортировку STL (см. http://www.sgi.com/tech/stl/sort.html или http://msdn.microsoft.com/en-us/library/ecdecxh1(VS.80).aspx) или старую сортировку C: http://en.wikipedia.org/wiki/Qsort_(C_Standard_Library).. если это не домашнее задание. Ваше сравнение зависит от технологии, которую вы любите использовать, она может выглядеть примерно так:

int CompareCustomerProfile(
   const CustomerProfile* pC1,
   const CustomerProfile* pC2)
{
 int result = strcmp(pC1->name, pC2->name);
 if (0 != result) return result; 

  result = strcmp(pC1->ID, pC2->ID);
  if (0 != result) return result;

  if (pC1->amountDue < pC2->amountDue) return -1;
 if (pC1->amountDue > pC2->amountDue) return 1;

  return 0
}

это предполагает, что тип 'string' в вашем примере это char *. Если вы используете Unicode или многобайтовые типы, то, очевидно, следует использовать соответствующее Unicode или многобайтовое сравнение. Тогда вы просто вызвали бы алгоритм со своей функцией сравнения. Например. используя qsort:

qsort(c, Count, sizeof(CustomerProfile), CompareCustomerProfiler).

Теперь, если это является домашним заданием, вам не следует спрашивать здесь, как это сделать ...

1 голос
/ 17 мая 2009

Вы можете найти множество реализаций сортировки в C ++ с творческим поиском в Google. Разница лишь в том, что вместо сортировки чисел вы сортируете структуры.

Так что, где бы в алгоритме вы не использовали что-то вроде if(a[i]<a[j]), сделайте вызов как `if (isFirstCustomerLowerThanOther (a [i]

Теперь создайте функцию со следующей структурой:

bool isFirstCustuomerLowerThanOther(const Customer& firstCustomer, const Customer& secondCustomer)
{
 // Implement based on your key preferences
}

Еще лучше, если вы используете C ++, вы можете использовать алгоритм сортировки STL (опять же, Google для информации и о том, как передать ему заказ.

0 голосов
/ 17 мая 2009

Я предполагаю, что вы новичок в программировании или в C ++, поэтому вот что вы, вероятно, ищете:

#include <search.h> // for the qsort()

int
CompareByName( const void *elem1, const void *elem2 )
{
  return ((Customers*)elem1)->Name > ((Customers*)elem2)->Name? 1 : -1;
}

int
CompareByOrderAmount( const void *elem1, const void *elem2 )
{
  return ((Customers*)elem1)->OrderAmount > ((Customers*)elem2)->OrderAmount? 1 : -1;
}

void SortData( int SortItem, int count, Customers customers[] )
{
  switch (SortItem) {
  case 0:
    qsort(customers, count, sizeof(Customers), CompareByName);
    break;
  case 1:
    qsort(customers, count, sizeof(Customers), CompareByOrderAmount);
    break;
  // ...
  }
}

void test()
{
  Customers cust[10];

  cust[0].Name = "ten";
  cust[1].Name = "six";
  cust[2].Name = "five";
  SortData( 0, 3, cust );
  cout << cust[0].Name << endl;
  cout << cust[1].Name << endl;
  cout << cust[2].Name << endl;
}
...