Упорядочивание строки в верхнем регистре -первый алфавитный порядок C

#c #string #sorting

#c #строка #сортировка

Вопрос:

Я пытался создать программу на C , которая сортирует заданную строку в алфавитном порядке таким образом, чтобы прописные буквы предшествовали их строчному эквиваленту. Пример: отсортированная строка DCBAdcba: AaBbCcDd

Ниже приведен код.

 #include <iostream>
#include <string>
#include <cctype>
struct char_ {
    char c;
    char diff;
    char_();
    char_(char x);
};
char_::char_() {
    c = 0;
    diff = 0;
}
char_::char_(char x) {
    c = std::tolower(x);
    diff = c - x;
}

void charswap(char_amp; x, char_amp; y) {
    char_ temp;
    temp = x;
    x = y;
    y = temp;
}

int main() {
    std::string str;
    getline(std::cin, str);
    char_* str2 = new char_[str.length()];
    for (int i = 0; i < str.length(); i  ) {
        str2[i] = char_(str[i]);
    }

    /*
    for (int i = 0; i < str.length(); i  ) {
        std::cout << str2[i].c << std::endl;
    }
    */
    for (int i = 0; i < str.length(); i  ) {
        for (int j = i; j < str.length(); j  ) {
            if (str2[i].c > str2[j].c)
                charswap(str2[i], str2[j]);
        }
    }


    for (int k = 0; k < str.length(); k  ) {
    std::cout << str2[k].c << "t" << (int)str2[k].diff << std::endl;
    }

    for (int i = 0; i < str.length(); i  ) {

    str2[i].c = str2[i].c - str2[i].diff;
    }




    for (int i = 0; i < str.length(); i  ) std::cout << str2[i].c;
    std::cout << "n";
    return 0;
}
  

Создается структура char_ для хранения отдельных символов (преобразованных в нижний регистр) и их отличий от эквивалента в верхнем регистре (0 или 32, в зависимости от того, был ли исходный символ строчным или прописным соответственно). Затем он сортирует символы char_ на основе их строчных значений. И после сортировки мы добавляем обратно разницу к символу, чтобы получить форму в верхнем регистре.

Но когда я пытаюсь ввести эту строку, она дает следующий результат.

DCBAdcba

AabBCcdD

Я не могу понять, что здесь происходит.

Комментарии:

1. Похоже, вам может понадобиться научиться использовать отладчик для пошагового выполнения вашего кода. С хорошим отладчиком вы можете выполнить свою программу построчно и посмотреть, где она отклоняется от того, что вы ожидаете. Это незаменимый инструмент, если вы собираетесь заниматься каким-либо программированием. Дальнейшее чтение: Как отлаживать небольшие программы

2. Вы создали алгоритм сортировки без учета регистра. Я не вижу кода для придания приоритета заглавным буквам.

3. Подсказка — найдите «таблицу Ascii» и обратите внимание на значения, присвоенные каждому символу.

4. @UKMonkey C не обязательно использовать ASCII

5. EBCDIC должен вернуться!

Ответ №1:

Проблема в этой строке:

 if (str2[i].c > str2[j].c)
    charswap(str2[i], str2[j]);
  

Он сравнивает символы без учета регистра, без возможности разрыва связей, когда строчные символы одинаковы.

Вам нужно изменить это, чтобы поменять местами символы, когда нижний регистр справа больше, чем нижний регистр слева, или когда представления в нижнем регистре одинаковы, но исходный символ с правой стороны находится в верхнем регистре:

 if ((str2[i].c > str2[j].c) || (str2[i].c == str2[j].c amp;amp; str2[j].diff))
    charswap(str2[i], str2[j]);
  

Ответ №2:

сортирует заданную строку в алфавитном порядке таким образом, чтобы прописные буквы предшествовали их строчному эквиваленту.

Вы можете просто определить функтор сравнения, отражающий ваше намерение

 #include <cctype>
#include <iostream>
#include <vector>
#include <algorithm>

struct case_cmp {
    bool operator()(char lhs, char rhs) const {
        return (std::isupper(lhs) amp;amp; std::tolower(lhs) == rhs) || std::tolower(lhs) < std::tolower(rhs);
    }
};
  

Затем используйте std::sort :

 int main() {
    std::string s("DCBAdcba");
    std::sort(std::begin(s), std::end(s), case_cmp());
    // Outputs "AaBbCcDd"
    std::cout << s << std::endl;
}
  

Ответ №3:

std::string может рассматриваться как контейнер char s, и поэтому вы можете применять алгоритмы STL к его содержимому, в том числе std::sort() (точно так же, как вы применили бы алгоритм STL, например std::vector ).

Вы можете указать свои конкретные пользовательские критерии сортировки, используя лямбда-выражение, которое будет передано в качестве третьего параметра std::sort() , например (live на Ideone):

 #include <algorithm>    // for std::sort
#include <cctype>       // for std::isupper, std::tolower
#include <iostream>     // for std::cout
#include <string>       // for std::string
using namespace std;

int main() {
    string s{"DCBAdcba"};

    sort( s.begin(), s.end(), [](char x, char y) { 
        // Custom sorting criteria.
        // Return true if x precedes y.

        // This may work, but requires more testing...
        if (isupper(x)) {
            if (tolower(x) == y) {
                return true;    
            }   
        }
        return tolower(x) < tolower(y);
    });

    cout << s << 'n';
}