Проблемы алфавитного массива структур. Работает от Z до A, но не от A до Z

0

В настоящее время я работаю над небольшим проектом над зимним перерывом и столкнулся с некоторыми проблемами.

Вот структура, с которой я работаю:

struct student{
string last_name;
string first_name;
double exams[NUM_EXAMS];
double average;
char letter_grade;
bool passed;};

Я пытаюсь в алфавитном порядке по имени от A до Z. Вот функция алфавита, а также функция обмена, которую она вызывает:

void alphabetize(student class_list[], int count)
{
    for (int pass = 0; pass < count; pass++)
        for (int x = 0; x < count - pass; x++)
            if (class_list[x].last_name < class_list[x + 1].last_name)
                swap(class_list, x);
}

void swap(student class_list[], int x)
{
    student temp[MAX_STUDENTS];

    temp[x] = class_list[x];
    class_list[x] = class_list[x + 1];
    class_list[x + 1] = temp[x];
}

Это отлично работает и упорядочивает по алфавиту массив структур в обратном порядке от Z до A.

Здесь исходный выходной файл несортирован:

   Jones        John  87  66  92  88 83.25  B  Pass
   Smith       Peter  55  66  63  58  60.5  D  Pass
   Quest      Nicole  79  89  99  98 91.25  A  Pass
      Wu          Li  98  99 100  91    97  A  Pass
    West     Vincent  80  80  88  89 84.25  B  Pass
McCartin       Susan  80  90 100  85 88.75  B  Pass
Ibrahima     Shuhuru  45  65  54  60    56  F  Fail
   Burns  Antoinette  90  90  90  90    90  A  Pass
      Ng    Lawrence 100 100  90  76  91.5  A  Pass
 Ziggler      Bertha  65  55  58  58    59  F  Fail
 Ionella        Jean 100 100 100 100   100  A  Pass
  Vogler      Samuel  40  50  60  70    55  F  Fail
   Perry         Jim  67  87  76  54    71  C  Pass

и здесь выведено использование

if (class_list[x].last_name < class_list[x + 1].last_name)

в функции алфавита.

 Ziggler      Bertha  65  55  58  58    59  F  Fail
      Wu          Li  98  99 100  91    97  A  Pass
    West     Vincent  80  80  88  89 84.25  B  Pass
  Vogler      Samuel  40  50  60  70    55  F  Fail
   Smith       Peter  55  66  63  58  60.5  D  Pass
   Quest      Nicole  79  89  99  98 91.25  A  Pass
   Perry         Jim  67  87  76  54    71  C  Pass
      Ng    Lawrence 100 100  90  76  91.5  A  Pass
McCartin       Susan  80  90 100  85 88.75  B  Pass
   Jones        John  87  66  92  88 83.25  B  Pass
 Ionella        Jean 100 100 100 100   100  A  Pass
Ibrahima     Shuhuru  45  65  54  60    56  F  Fail
   Burns  Antoinette  90  90  90  90    90  A  Pass

Если я переключу

if (class_list[x].last_name < class_list[x + 1].last_name)

в функции алфавита в

if (class_list[x].last_name > class_list[x + 1].last_name)

Я думал, что это решит проблему и отсортирует массив от A до Z, а не от Z до A. Это то, что я получаю как результат:

                    -6.27744e+066-6.27744e+066-6.27744e+066-6.27744e+066-6.2
7744e+066  ═  Pass
   Burns  Antoinette  90  90  90  90    90  A  Pass
Ibrahima     Shuhuru  45  65  54  60    56  F  Fail
 Ionella        Jean 100 100 100 100   100  A  Pass
   Jones        John  87  66  92  88 83.25  B  Pass
McCartin       Susan  80  90 100  85 88.75  B  Pass
      Ng    Lawrence 100 100  90  76  91.5  A  Pass
   Perry         Jim  67  87  76  54    71  C  Pass
   Quest      Nicole  79  89  99  98 91.25  A  Pass
   Smith       Peter  55  66  63  58  60.5  D  Pass
  Vogler      Samuel  40  50  60  70    55  F  Fail
    West     Vincent  80  80  88  89 84.25  B  Pass
      Wu          Li  98  99 100  91    97  A  Pass

Как вы можете видеть, я сейчас пропускаю то, что было бы последним учеником в этом списке, и вместо этого вывод выплевывает эти числа. Я не понимаю, почему он работает в обратном порядке, и я не уверен, как это исправить. Любой совет будет очень благодарен!

EDIT: Благодаря Jarod42 я разработал решение моей проблемы. Это была проблема с границами с x + 1. Вот код, который я использовал для устранения проблемы. Он работает с входным файлом, который у меня есть, но я не уверен, что он будет работать с другим. Если кто-то видит проблему с этим, пожалуйста, дайте мне знать.

void alphabetize(student class_list[], int count)
{
    for (int pass = 0; pass < count; pass++)
        for (int x = 0; x < count - pass; x++)
            if (class_list[x].last_name > class_list[x + 1].last_name)
                if (count > x + 1)
                    swap(class_list, x);
}
  • 0
    Помогают ли эти пояснения в справочнике объяснить, что вы понимаете при сравнении std::string ?
  • 2
    Вы получаете индекс вне границ в этом вложенном цикле. Это вызывает неопределенное поведение независимо от того, как вы пытаетесь отсортировать массив, так что с другой попытки вы можете получить этот странный вывод даже при сортировке их из ZA.
Теги:
arrays
struct
function
alphabetized

2 ответа

2

С:

for (int x = 0; x < count - pass; x++)
    if (class_list[x].last_name < class_list[x + 1].last_name)

У вас может быть ограниченный доступ с x + 1 когда pass == 0.

С помощью STL вы можете просто выполнить:

std::sort(std::begin(students), std::end(students),
          [](const student& lhs, const student& rhs) {
              return lhs.last_name < rhs.last_name; // and > for the other order
          });
  • 1
    Для удовольствия: даже не используя std :: vector :)
  • 0
    Спасибо за ваш быстрый ответ! Я согласен с тем, что это скорее всего проблема с «x + 1». Я только начинаю с C ++, и я не знаком с STL. Мне бы очень хотелось поработать с этим, используя то, что мой учитель пережил в прошлом семестре. Есть ли какой-то способ, которым я могу использовать функцию подкачки и какой-то отказоустойчивый для решения проблемы за пределами?
0

Если вы действительно не хотите использовать стиль C++ (векторы и stl, например std :: sort), попробуйте изменить эту строку:

for (int x = 0; x < count - pass; x++)

в:

for (int x = 0; x < count - pass - 1; x++)

Вы должны понимать инварианты. Ваш алгоритм сортировки гарантирует, что на каждом шаге прохода, у вас есть последние позиции пасс в массиве отсортирован. Это откуда -pass. Это -1 объясняется тем, что на каждом шаге в этом цикле for вы сравниваете текущую позицию со следующей.

Тем не менее, я настоятельно рекомендую использовать std :: vector и std :: sort, если вы не пытаетесь научить себя алгоритму сортировки.

  • 0
    Спасибо за ваш ответ. Я пытаюсь завершить эту программу, используя то, чему меня учили в классе, и не слишком быстро продвигаться вперед. Мы еще не перешли на std :: vector или std :: sort, и часть присваивания требует, чтобы мы написали нашу собственную функцию алфавитизации. Я отредактировал свой основной пост с решением, которое я придумал внизу. Я хотел бы услышать ваши мысли. РЕДАКТИРОВАТЬ : Я попытался использовать код, который вы предложили с count - pass - 1, и это тоже работает. Есть ли разница в стабильности между кодом, который я отредактировал в своем основном посте, и кодом, который вы предложили?
  • 0
    С точки зрения функциональности нет, разницы нет. Это потому, что count> x + 1 <=> x <count - 1 гарантирует, что вы не попадете ни в один индекс за пределы массива. Тем не менее, предложенное мной решение лучше, во-первых, потому что оно менее многословно, а во-вторых, оно быстрее, так как оператор if вызывает некоторую задержку, если число итераций (то есть размер массива) действительно велико. Кроме того, вы делаете ненужные пошаговые сравнения: вы сравниваете позиции « пас» и « пас» + 1 на каждом шаге, даже если ваш алгоритм гарантирует, что ваши позиции последнего паса будут отсортированы.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню