Сортировка вставками С++ из текстового файла

Мне нужно прочитать файл .txt и вывести его с помощью другого файла .txt. Я должен использовать сортировку вставками, чтобы отсортировать их по двум числам. Я мог только зайти так далеко, я не знаю, как выполнить сортировку вставками в этой программе, где у меня есть два числа для сортировки.

Вот мой код:

#include <iostream>
#include <fstream>
#include <string>

using namespace std;

int main(void)
{
    int serialno[100], suratno[100], ayatno[100];
    string order;

    string str;
    char ch;
    int i = 0;
    int j, temp;

    ifstream fin;
    fin.open("text.txt");

    if(!fin)
    {
        cout << "Cannot open file \'text.txt\'! Quitting.\n";
        exit(0);
    }

    while(fin)
    {

        fin.get(ch); //gets .

        getline(fin, order, '('); //allegedly it removes the delimiter char from stream too

        fin >> suratno;
        fin.get(ch); //gets :
        fin >> ayatno;
        fin.get(ch); //gets )
        fin.get(ch); //gets \n

        cout << serialno << "." << order << "("<<suratno<<":<<ayatno<<")\n";
    }

    fin.close();

    //sort algorithm            
    for (int i = 0; i < length; i++){
        j = i;

        while (j > 0 && suratno [j] < suratno [j-1]){
              temp = suratno [j];
              suratno [j] = suratno [j-1];
              suratno [j-1] = temp;
              j--;
              cout << serialno << endl;
              }
        }
    }

    ofstream fout;
    fout.open("newtext.txt");

    if(!fout)
    {
        cout << "Cannot open output file\'orderedquranorders.txt\'!Quitting.\n";
        exit(0);
    }

    i = 0;
    //write sorted list to output file

    fout.close();

    cout << i << " orders successfully sorted and written.\n";
}

это текстовый файл (следует использовать числа в квадратных скобках, сначала с номером перед двоеточием, а затем с номером после двоеточия):

1. Do not be rude in speech (3:159) 
2. Restrain Anger (3:134)
3. Be good to others (4:36)
4. Do not be arrogant (7:13)
5. Forgive others for their mistakes (7:199)
6. Speak to people mildly (20:44)
7. Lower your voice (31:19)
8. Do not ridicule others (49:11)
9. Be dutiful to parents(17:23)

текущий выход:

  1. Не будь груб в речи (3:159)
  2. Сдерживать гнев (3:134)
  3. Будьте добры к другим (4:36)
  4. Будьте послушны родителям (17:23)

ожидаемый результат:

  1. Сдерживать гнев (3:134)
  2. Не будь груб в речи (3:159)
  3. Будьте добры к другим (4:36)
  4. Будьте послушны родителям (17:23)

сортируется как по номерам, так и по серийным номерам. no остается прежним


person Fahad Khalid    schedule 29.11.2016    source источник
comment
Прочитайте справочный центр о том, как задать хороший вопрос. Также прочитайте Как отлаживать небольшие программы Эрика. Липперт. В настоящее время у вас есть одна огромная основная функция. По крайней мере, разделите это на три функции: чтение ввода, сортировка данных, запись вывода. Затем вы можете проверить чтение ввода и запись вывода, прежде чем начинать тестировать сортировку.   -  person Martin Bonner supports Monica    schedule 29.11.2016
comment
@MartinBonner У меня есть текстовый файл, который я должен прочитать, и он требует сортировки. Пример данных, представленных в моем текстовом файле: 1. Не грубить в речи (3:159) эти цифры в скобках 2. Сдерживать гнев (3:134) 3. Делать добро другим (4:36)   -  person Fahad Khalid    schedule 29.11.2016
comment
@YSC есть предложения?   -  person Fahad Khalid    schedule 29.11.2016
comment
@FahadKhalid: четко опишите, что ваша программа принимает на вход, что она должна выводить, ваш код и текущий результат, который вы получаете. Все в вопросе (редактировать его). Затем спросите что-нибудь простое, например, что я сделал не так?   -  person YSC    schedule 29.11.2016
comment
@YSC берет ввод из текстового файла, в котором есть числа вроде (3:159). он сортирует их, а затем выводит отсортированный список в другой текстовый файл   -  person Fahad Khalid    schedule 29.11.2016
comment
Хорошо, а теперь каков ожидаемый результат для примера, который вы привели, и каков фактический результат, который вы получите от своей реализации? (добавьте их к вашему вопросу)   -  person YSC    schedule 29.11.2016
comment
@YSC спасибо за подсказку, я обновил свой вопрос, надеюсь, на этот раз вы сможете понять его лучше.   -  person Fahad Khalid    schedule 29.11.2016
comment
@MartinBonner, ты можешь мне помочь??   -  person Fahad Khalid    schedule 29.11.2016
comment
Почти. Я не понимаю, почему записи с 4 по 8 не должны быть в выводе. Вы не только их сортируете, но и фильтруете, не так ли?   -  person YSC    schedule 29.11.2016
comment
@YSC точно должен их фильтровать или, можно сказать, манипулировать ими таким образом, чтобы оба числа в скобках были в порядке возрастания. Да и записи 4-8 должны быть в выводе. Я просто не написал их в вопросе.   -  person Fahad Khalid    schedule 29.11.2016
comment
Извините, мы не можем догадаться о таких вещах. Вам нужно отредактировать вопрос, чтобы включить полный ожидаемый и фактический результат. (Пожалуйста, максимально уменьшите входной файл, сохранив при этом неожиданный результат — это может означать удаление строк в середине.)   -  person Martin Bonner supports Monica    schedule 29.11.2016
comment
Я даже не вижу, как это компилируется для вас. Это недопустимый С++. Например, for (int i = 0; i < length; i++){ вы никогда не определяете length. Этот простой код не работает. Вам также не хватает двойной кавычки.   -  person Cinder Biscuits    schedule 29.11.2016


Ответы (2)


Чтобы сравнить две пары чисел, вы можете сделать сравнения, например:

 if(suratno[i] < suratno[i-1] || (suratno[i] == suratno[i-1] && ayatno[i] < ayatno[i-1])){
    /* swap */
 }

Или вы можете использовать одно выражение: expr = suratno * 10000 + ayatno. И сделать только одно сравнение:

 if(expr[i] < expr[i-1]){
    /* swap */
 }

Кроме того, у меня есть несколько замечаний по поводу вашего алгоритма/кода:

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

#include <iostream>
#include <fstream>
#include <string>
#include <regex>
#include <vector>
#include <algorithm>

using std::string;

struct Line {
    int expr;   // Expression used to compare
    string text;    // Original line without initial number
};

int main() {
    std::regex linePattern(
        "\\d+"      // 1 or more digits
        "\\. "      // '. ' (dot followed by 1 space)
        "("         // begin char group #1
           ".*"     // zero or more chars
           "\\("    // '(' (left parenthesis)
           "(\\d+)" // char group #2 (suratno: 1+ digits)
           ":"      // ':' (colon)
           "(\\d+)" // char group #3 (ayatno: 1+ digits)
           "\\)"    // ')' (right parenthesis)
        ")"         // end char group #1
    );
    std::smatch groups;         // Regular expression found char groups
    std::vector<Line> lines;    // Vector to store the readed lines

    // Read lines parsing content
    std::ifstream fin("text.txt");
    if(!fin){
        std::cerr << "Cannot open file 'text.txt'! Quitting.\n";
        return 1;
    }
    string line;
    while (std::getline(fin, line))
        if (std::regex_search(line, groups, linePattern) && groups.size() > 0) {
            int suratno = std::stoi(groups[2]);
            int ayatno = std::stoi(groups[3]);
            int compExpr = suratno * 10000 + ayatno; // assumes ayatno < 10,000
            lines.push_back({ compExpr, groups[1] });
        }
    fin.close();

    // sort algorithm (better start in 1)
    for (size_t i = 1; i < lines.size(); i++)
        for (size_t j = i; j > 0 && lines[j].expr < lines[j - 1].expr; j--)
            std::swap(lines[j], lines[j - 1]);

    std::ofstream fout("newtext.txt");
    if(!fout){
        std::cerr << "Cannot open output file 'orderedquranorders.txt'! Quitting.\n";
        return 1;
    }
    for (size_t i = 0; i < lines.size(); i++)
        fout << i + 1 << ". " << lines[i].text << std::endl;
    fout.close();

    std::cout << lines.size() << " orders successfully sorted and written.\n";
    return 0;
}

Примечание. Регулярное выражение на самом деле представляет собой одну строку "\\d+\\. (.*\\((\\d+):(\\d+)\\))", я использовал функцию C/C++, которая объединяет строки, разделенные пробелами, перед компиляцией, поэтому компилятор видит только одну строку.

Не забудьте скомпилировать с опцией -std=c++11.

person WPomier    schedule 29.11.2016

using namespace std; считается плохой практикой и иногда может быть опасным. Проверьте это

Вот ваше решение:

#include <iostream>
#include <fstream>
#include <string>

int main()
{
    int suratno[100], ayatno[100];
    std::string order[100];

    char ch;
    int count = 0;
    int tempInt;
    std::string tempStr;

    std::ifstream fin;
    fin.open("text.txt");

    if (!fin)
    {
        std::cout << "Cannot open file \'text.txt\'! Quitting.\n";
        exit(0);
    }
    else
    {
        while (fin)
        {
            fin.get(ch); //gets the numbers
            fin.get(ch); //gets .

            getline(fin, order[count], '('); //allegedly it removes the delimiter char from stream too

            fin >> suratno[count];
            fin.get(ch); //gets :
            fin >> ayatno[count];
            fin.get(ch); //gets )
            fin.get(ch); //gets \n

            std::cout << count + 1 << "." << order[count] << "(" << suratno[count] << ":" << ayatno[count] << ")\n";
            count++;
        }
    }
    fin.close();
    std::cout << std::endl;

    // sort algorithm (we must sort two times)
    for (int i = 0; i < count; i++)
    {
        for (int j = i; j > 0 && suratno[j] < suratno[j - 1]; j--)
        {
            tempInt = suratno[j];
            suratno[j] = suratno[j - 1];
            suratno[j - 1] = tempInt;

            tempInt = ayatno[j];
            ayatno[j] = ayatno[j - 1];
            ayatno[j - 1] = tempInt;

            tempStr = order[j];
            order[j] = order[j - 1];
            order[j - 1] = tempStr;
        }
    }

    for (int i = 0; i < count; i++)
    {
        for (int j = i; j > 0 && suratno[j] == suratno[j - 1] && ayatno[j] < ayatno[j - 1]; j--)
        {
            tempInt = ayatno[j];
            ayatno[j] = ayatno[j - 1];
            ayatno[j - 1] = tempInt;

            tempInt = suratno[j];
            suratno[j] = suratno[j - 1];
            suratno[j - 1] = tempInt;

            tempStr = order[j];
            order[j] = order[j - 1];
            order[j - 1] = tempStr;
        }       
    }

    // print the sorted list just to check
    for (int i = 0; i < count; i++)
    {
        std::cout << i + 1 << "." << order[i] << "(" << suratno[i] << ":" << ayatno[i] << ")\n";
    }

    // write sorted list to output file
    std::ofstream fout;
    fout.open("newtext.txt");

    if (!fout)
    {
        std::cout << "Cannot open output file\'orderedquranorders.txt\'!Quitting.\n";
        exit(0);
    }
    else
    {
        for (int i = 0; i < count; i++)
        {
            fout << i + 1 << "." << order[i] << "(" << suratno[i] << ":" << ayatno[i] << ")\n";
        }
    }
    fout.close();

    std::cout << std::endl;
    std::cout << count << " orders successfully sorted and written.\n";

    return 0;
}
person yahiheb    schedule 30.11.2016