2016-11-29 4 views
2

Je dois lire un fichier .txt et le sortir avec un fichier .txt différent. Je dois utiliser le tri d'insertion afin de les trier en fonction de deux nombres. Je pourrais seulement aller aussi loin, je ne sais pas comment faire le tri d'insertion dans ce programme où j'ai deux nombres à trier.Tri d'insertion C++ à partir d'un fichier txt

Voici mon code:

#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"; 
} 

c'est le fichier texte (numéros dans le support doivent être utilisés, d'abord avec le numéro avant deux points, et d'autre part avec nombre après deux points):

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) 

sortie courant:

  1. ne soyez pas impoli dans le discours (3: 159)
  2. colère Retiens (3: 134)
  3. Soyez bien aux autres (4:36)
  4. Craignez aux parents (17:23)

de sortie prévue:

  1. Anger (RESTRICTION 3: 134)
  2. ne soyez pas impoli dans le discours (3: 159)
  3. Soyez bien aux autres (04:36)
  4. Craignez aux parents (17:23)

trié en termes de chiffres et le numéro de série reste le même

+0

Allez lire le centre d'aide sur « comment poser une bonne question ». Lisez également [Comment déboguer de petits programmes] (https://ericlippert.com/2014/03/05/how-to-debug-small-programs/) par Eric Lippert. Vous avez actuellement une énorme fonction principale. À tout le moins diviser en trois fonctions: lire l'entrée, trier les données, écrire la sortie. Vous pouvez ensuite tester "lire l'entrée" et "écrire la sortie" avant de commencer à tester le tri. –

+0

@MartinBonner J'ai un fichier txt que je dois lire et il nécessite un tri. exemple de données présentes dans mon fichier txt est 1. Ne pas être impoli dans la parole (3: 159) "ces chiffres entre parenthèses" 2. Restreindre la colère (3: 134) 3. Être bon aux autres (4:36) –

+0

@YSC des suggestions? –

Répondre

0

Afin de comparer deux paires de nombres, vous pouvez faire des comparaisons comme:

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

Ou vous pouvez utiliser une expression: expr = suratno * 10000 + ayatno. Et faire une seule comparaison:

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

Aussi, j'ai quelques observations au sujet de votre algorithme/code:

  • Ne pas utiliser using namespace std. Spécialement dans les gros programmes, car il peut causer des bugs obscurs (voir un exemple here). Utilisez plutôt using std::<name> si vous voulez éviter std::. Ex. using std::string. En général, évitez using namespace xxxx.
  • Je vois que vous avez analysé les lignes d'entrée manuellement, je préfère utiliser des expressions régulières, beaucoup plus polyvalentes et puissantes, mais qui demandent un peu d'apprentissage.
  • Lorsqu'il est nécessaire d'écrire un message d'erreur, écrivez toujours dans le flux stderr cerr en C++.
  • Dans l'algorithme de tri, il vaut mieux commencer par 1 que par 0, car le premier élément n'a pas d'élément précédent à comparer.
  • Enfin, le swap peut être fait avec une fonction C++ existante.

Voici votre code réorganisé et utilisant des expressions régulières que j'ai essayé d'expliquer autant que possible:

#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; 
} 

Note: L'expression régulière est vraiment une chaîne "\\d+\\. (.*\\((\\d+):(\\d+)\\))", j'ai utilisé un C/fonction C++ qui concatène les chaînes séparées par des espaces avant la compilation, de sorte que le compilateur ne voit qu'une seule chaîne. Ne pas oublier de compiler avec -std=c++11 option.

0

using namespace std; est considéré comme une mauvaise pratique et peut parfois être dangereux. Vérifiez this

Voici votre solution:

#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; 
}