Функция с ++ std :: sort не завершена?

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

Я делаю все это в RAD Studio 10.2 (Embarcadero IDE) на C++.

Итак, это мой код:

std::string Line;
int count = 0;
int i = 0;
ifstream File("Highscore.txt");
if (File.is_open())
{
    while(getline(File, Line))
    {
        count += 1;

    }

    File.close();

}

ifstream ReadFile("Highscore.txt");
if (ReadFile.is_open())
{
    string *scores = NULL;
    scores = new string[count];

    while(getline(ReadFile, Line))
    {
        scores[i] = Line;
        i += 1;
    }

    ReadFile.close();


    std::sort(scores, (scores+count));

    UnicodeString Uscores1 = scores[0].c_str();
    UnicodeString Uscores2 = scores[1].c_str();
    UnicodeString Uscores3 = scores[2].c_str();
    UnicodeString Uscores4 = scores[3].c_str();
    UnicodeString Uscores5 = scores[4].c_str();
    LScore1->Caption = Uscores1;
    LScore2->Caption = Uscores2;
    LScore3->Caption = Uscores3;
    LScore4->Caption = Uscores4;
    LScore5->Caption = Uscores5;

}

Я не получаю ошибок от компилятора / компоновщика, и все должно работать нормально. Строковый массив заполняется правильно и так далее.

Но это не сортировка.

Чтобы показать вам проблему, я сделал снимок экрана - слева вы видите текстовый файл с оценками; справа вы можете увидеть результат после алгоритма сортировки:

Функция с ++ std :: sort не завершена?

Теперь у меня вопрос: почему это происходит?

Спасибо за помощь

Это действительно сортировка. Если вы хотите выполнить числовую сортировку, вам следует использовать числовой тип.

tkausl 23.04.2018 15:41

Если вам этого раньше не говорили, загляните на нашу страницу на минимальные полные примеры. Не публикуйте снимок экрана с данными, жестко закодируйте его в своем примере.

Beta 23.04.2018 15:43

Я ошибся и удалил свой комментарий через несколько секунд после публикации.

Max Langhof 23.04.2018 15:46

Когда у меня, как в примере, 5 оценок в моем txt-файле и результаты вывода [4], на выходе получается 5 = пятый элемент в моем txt-файле.

Samy Dressel 23.04.2018 15:47

@SamyDressel у вас есть 5 оценок и 2 «пустые» строки, которые являются действительными значениями для std::string. Проверить значение count

Caleth 23.04.2018 17:12
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
5
173
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Как насчет чего-то вроде:

int i = 0;
int * scoresInteger = NULL;
scoresInteger = new int[count];
for(i = 0; i < count; i++)
{
    scoresInteger[i] = std::stoi(scores[i]);
}
std::sort(scoresInteger, scoresInteger + count);

При необходимости вы можете преобразовать целые числа обратно в строки с помощью targetStrings[i] = std::to_string(scoresInteger[i]).

string * targetScores = NULL;
targetScores = new std::string[count];
for(i = 0; i < count; i++)
{
    targetScores[i] = std::to_string(scoresInteger[i]);
}
delete [] scoresInteger;
scoresInteger = NULL;

Не забудьте позже к delete [] targetScores.

Пожалуйста, delete память для массива, так как вы его распределяете. Копирование этого кода приведет к утечке памяти.

Petar Velev 23.04.2018 16:10

@PetarVelev Или вы знаете ... используйте std :: vector

Borgleader 23.04.2018 16:10

My question now is why this is happening?

Потому что ваши оценки сравниваются как string, а не как int. Из-за этого «3» больше, чем «25».

std::cout << std::boolalpha << (std::string("3") > std::string("25")) << std::endl; // true

К счастью, вы можете передать std::sort собственный компаратор (или лямбда), чтобы он вел себя так, как вы хотите:

#include <iostream>
#include <string>
#include <algorithm>

int main()
{
    const int count = 5;
    std::string scores[count] = { "35","25","3","4","5" };

    // TWEAKED SORT
    std::sort(scores, scores + count, [](std::string const &s1, std::string const &s2)
    {
        return std::stoi(s2) < std::stoi(s1);
    });

    // TEST
    for (auto const &s : scores)
    {
        std::cout << s << std::endl;
    }
}

Сравниваемые string в приведенном выше примере преобразуются в int, а затем сравниваются, что дает желаемый порядок сортировки.

35
25
5
4
3

Обратите внимание, что я не согласен с остальной частью вашего кода, и я думаю, вам следует переосмыслить реализацию, так как было бы намного проще, безопаснее и эффективнее использовать std::vector<std::string> для вашей задачи.

Вы спросил, почему Jive отклонил ваш ответ (хотя я понятия не имею, почему вы считаете, что Джайв виноват; с равной вероятностью его ответ привлек внимание к этому вопросу, и последующий посетитель проголосовал против), и я могу назвать вам по крайней мере одну причину для отрицательного голоса (я не , но это достаточно большая ошибка, и некоторые могут). В вашей демонстрации сравнения строк вы сравнивали пару строк в стиле C, а не std::string, и результат этого сравнения не всегда будет true ...

ShadowRanger 02.05.2018 20:36

… Потому что строки в стиле C сравнивают адреса указателей (технически сравнение указателей, которые не указывают на один и тот же массив, является неопределенным поведением IIRC, но на практике оно работает предсказуемо на всех машинах с плоскими моделями памяти). Таким образом, если данные, поддерживающие "3", хранятся в двоичном файле до данных, поддерживающих "25", то результат будет ложным, а если он будет сохранен после, он верен (и это может варьироваться между компиляторами или даже перекомпилировать с одним и тем же компилятором). Для нормальной работы вам понадобится std::string("3") > "25" или (с C++ 14 + и using namespace std::literals) "3"s > "25"s.

ShadowRanger 02.05.2018 20:41

@ShadowRanger Достаточно честно, правильная точка зрения, и я исправил ее, спасибо. Стоит ли отрицательный голос без объяснения причин? Я лично оставил бы комментарий и дал бы автору ответить. Что касается того, кто проголосовал против, допустим, у меня есть неопровержимые доказательства того, кто это сделал.

Killzone Kid 02.05.2018 21:47

Да, я не верю в отрицательное голосование за ошибки без объяснения (полный мусор ответы, которые не столько неточны, сколько сбивают с толку, получайте отрицательные голоса без объяснения, и я буду отрицать, не объясняя, если кто-то другой объяснил свой отрицательный голос, и я согласен) , и когда я сделаю отрицательный голос и объясню, я отзову их, когда проблема будет исправлена ​​(если я заметлю это позже), но да, нет никаких оснований для тихого отрицательного голоса для отдельных, трудно обнаруживаемых ошибок. Тем не менее, я только что привык к случайным необъяснимым ложным голосам против; Я перепроверяю себя, затем пожимаю плечами и продолжаю.

ShadowRanger 03.05.2018 02:10
Ответ принят как подходящий

Добро пожаловать в C++. Поскольку вы хотите перечислить номера по рангу, читайте их как int, а не как string. Забудьте про оператора new. Он вам не понадобится годами, если вообще когда-нибудь. Используйте стандартные контейнеры, такие как std::vector, которые прозрачно заботятся о выделении и освобождении памяти.

#include <iostream>
#include <vector>
#include <fstream>
#include <algorithm>
int main() {
    using namespace std;
    vector<int> scores;
    {
        ifstream inp("Highscore.txt");
        int next;
        while (inp >> next) {
            scores.push_back(next);
        }
    }
    sort(scores.begin(), scores.end());
    for (auto s : scores) {
        cout << s << '\n';
    }
    return 0;
}

Не могли бы вы назвать причину, по которой вы проголосовали против моего ответа?

Killzone Kid 23.04.2018 19:39

Спасибо - это мне очень помогло. И это дало мне повод разобраться в C++ и контейнерах: D За годичный модуль разработки программного обеспечения на C++ в моем университете никто никогда не упоминал такие вещи, как векторы. Это печально: D

Samy Dressel 24.04.2018 09:46

Действительно печально, но типично. Десятилетия ушли на то, чтобы сделать C++ простым. Студентов учат делать вещи способами, которые не только подвержены ошибкам, но и совершенно неприемлемы при проверке кода в реальном мире. youtu.be/YnWhqhNdYyk

Jive Dadson 25.04.2018 01:51

Другие вопросы по теме