2010-04-04 4 views
2

Je travaille sur les exercices en C++ accéléré et je suis bloqué sur la question 5-6. Voici la description du problème: (en abrégé, j'ai supprimé les informations superflues.)Accéléré C++, problème 5-6 (copier les valeurs de l'intérieur d'un vecteur vers l'avant)

5-6. Écrivez les extract_fails fonction afin qu'il copie les dossiers pour les étudiants qui passent au début des étudiants, puis utilise la redimensionnez fonction pour supprimer les éléments supplémentaires de la fin des étudiants.

(étudiants est un vecteur de étudiant structures. étudiants structures contiennent un nom de chaque élève et des grades.)

Plus précisément, je vais avoir du mal à obtenir la vector.insert fonction pour copier correctement le passage étudiant structures au début du vecteur étudiants. Voici la fonction extract_fails comme je l'ai jusqu'à présent (notez qu'il ne redimensionne pas le vecteur encore, comme indiqué par la description du problème, ce qui devrait être trivial une fois que je reçois passé mon numéro actuel.)

// Extract the students who failed from the "students" vector. 
void extract_fails(vector<Student_info>& students) 
{ 
    typedef vector<Student_info>::size_type str_sz; 
    typedef vector<Student_info>::iterator iter; 
    iter it = students.begin(); 
    str_sz i = 0, count = 0; 

    while (it != students.end()) { 
     // fgrade tests wether or not the student failed 
     if (!fgrade(*it)) {   
      // if student passed, copy to front of vector 
      students.insert(students.begin(), it, it);  
      // tracks of the number of passing students(so we can properly resize the array) 
      count++;           
     } 

     cout << it->name << endl; // output to verify that each student is iterated to 
     it++; 
    } 
} 

Le code compile et s'exécute, mais le étudiants vecteur n'ajoute aucun étudiant structures à son front. La sortie de mon programme affiche que le vecteur students est inchangé.

Voici mon code source complet, suivi d'un fichier d'entrée de l'échantillon (rediriger l'entrée de la console en tapant « < grades » après le nom du programme compilé à l'invite de commande.)

#include <iostream> 
#include <string> 
#include <algorithm> // to get the declaration of `sort' 
#include <stdexcept> // to get the declaration of `domain_error' 
#include <vector>  // to get the declaration of `vector' 

//driver program for grade partitioning examples 

using std::cin; 
using std::cout; 
using std::endl; 
using std::string; 
using std::domain_error; 
using std::sort; 
using std::vector; 
using std::max; 
using std::istream; 

struct Student_info { 
    std::string name; 
    double midterm, final; 
    std::vector<double> homework; 
}; 


bool compare(const Student_info&, const Student_info&); 
std::istream& read(std::istream&, Student_info&); 
std::istream& read_hw(std::istream&, std::vector<double>&); 
double median(std::vector<double>); 

double grade(double, double, double); 
double grade(double, double, const std::vector<double>&); 
double grade(const Student_info&); 

bool fgrade(const Student_info&); 

void extract_fails(vector<Student_info>& v); 

int main() 
{ 
     vector<Student_info> vs; 
     Student_info s; 
     string::size_type maxlen = 0; 
     while (read(cin, s)) { 
       maxlen = max(maxlen, s.name.size()); 
       vs.push_back(s); 
     } 

     sort(vs.begin(), vs.end(), compare); 

    extract_fails(vs); 


    // display the new, modified vector - it should be larger than 
    // the input vector, due to some student structures being 
    // added to the front of the vector. 
    cout << "count: " << vs.size() << endl << endl; 
    vector<Student_info>::iterator it = vs.begin(); 
    while (it != vs.end()) 
     cout << it++->name << endl; 
    return 0; 
} 


// Extract the students who failed from the "students" vector. 
void extract_fails(vector<Student_info>& students) 
{ 
    typedef vector<Student_info>::size_type str_sz; 
    typedef vector<Student_info>::iterator iter; 
    iter it = students.begin(); 
    str_sz i = 0, count = 0; 

    while (it != students.end()) { 
     // fgrade tests wether or not the student failed 
     if (!fgrade(*it)) {   
      // if student passed, copy to front of vector 
      students.insert(students.begin(), it, it);  
      // tracks of the number of passing students(so we can properly resize the array) 
      count++;           
     } 

     cout << it->name << endl; // output to verify that each student is iterated to 
     it++; 
    } 
} 


bool compare(const Student_info& x, const Student_info& y) 
{ 
    return x.name < y.name; 
} 


istream& read(istream& is, Student_info& s) 
{ 
    // read and store the student's name and midterm and final exam grades 
    is >> s.name >> s.midterm >> s.final; 

    read_hw(is, s.homework); // read and store all the student's homework grades 
    return is; 
} 


// read homework grades from an input stream into a `vector<double>' 
istream& read_hw(istream& in, vector<double>& hw) 
{ 
    if (in) { 
     // get rid of previous contents 
     hw.clear(); 

     // read homework grades 
     double x; 
     while (in >> x) 
      hw.push_back(x); 

     // clear the stream so that input will work for the next student 
     in.clear(); 
    } 
    return in; 
} 


// compute the median of a `vector<double>' 
// note that calling this function copies the entire argument `vector' 
double median(vector<double> vec) 
{ 
    typedef vector<double>::size_type vec_sz; 

    vec_sz size = vec.size(); 
    if (size == 0) 
     throw domain_error("median of an empty vector"); 

    sort(vec.begin(), vec.end()); 

    vec_sz mid = size/2; 

    return size % 2 == 0 ? (vec[mid] + vec[mid-1])/2 : vec[mid]; 
} 


// compute a student's overall grade from midterm and final exam grades and homework grade 
double grade(double midterm, double final, double homework) 
{ 
    return 0.2 * midterm + 0.4 * final + 0.4 * homework; 
} 


// compute a student's overall grade from midterm and final exam grades 
// and vector of homework grades. 
// this function does not copy its argument, because `median' does so for us. 
double grade(double midterm, double final, const vector<double>& hw) 
{ 
    if (hw.size() == 0) 
     throw domain_error("student has done no homework"); 
    return grade(midterm, final, median(hw)); 
} 


double grade(const Student_info& s) 
{ 
    return grade(s.midterm, s.final, s.homework); 
} 


// predicate to determine whether a student failed 
bool fgrade(const Student_info& s) 
{ 
    return grade(s) < 60; 
} 

fichier d'entrée de l'échantillon :

Moo 100 100 100 100 100 100 100 100
fail1 45 55 65 80 90 70 65 60
Moore 75 85 77 59 0 85 75 89
Norman 78 73 66 57 78 70 88 89
Olson 89 86 70 90 55 73 80 84
Peerson 47 70 82 73 50 87 73 71
Baker 67 72 73 40 0 ​​78 55 70
Davis 77 70 82 65 70 77 83 81
Edwards 77 72 73 80 90 93 75 90
Fail2 55 55 65 50 55 60 65 60

Merci à tous ceux qui prennent le temps de regarder ça!

Répondre

3

L'insertion au début d'un vecteur invalide tous les itérateurs pointant dans ce vecteur. Si je ne me trompe pas, vous êtes censé utiliser <algorithm> - la paire std::remove/std::erase.

+0

Je n'ai pas utilisé mais de mentionner comment insérer au début d'un vecteur tous les itérateurs invalide était mort sur ... Je pense que je réécris la fonction à l'aide d'un index: \t while (i = étudiants. size()) { \t \t if (! fgrade (étudiants [i])) { students.insert (students.begin(), étudiants [i ++]); compte ++; } i ++; \t} students.resize (count); ça marche maintenant! Merci. – Darel

0

Je suis surpris que cela a fonctionné pour vous Darel.J'ai essayé d'utiliser

students.insert(students.begin(), students[i++]);

et je suis un bad_alloc jeté sur moi. J'ai dû utiliser ce format:

students.insert(students.begin(), 1, students[i+count]); 

pour le faire fonctionner. Le ajouté est le nombre d'éléments à insérer, initialisés à la valeur des étudiants [i + count]

La raison pour laquelle je i + compte pour l'indice des étudiants est parce que vous ajoutez plus étudiants au début, vous devez ajouter le compte à l'index pour compenser cela. Il en va de même pour l'indice des étudiants défaillants. J'écris ceci maintenant plus pour n'importe qui qui a des ennuis avec ce problème, je suis sûr que Darel est déjà fini avec le livre maintenant!

+0

J'ai encore mon code pour ça à la maison, je vais le regarder encore ce soir et voir si j'ai omis quelques nuances critiques de ma solution. – Darel

2

Il convient de noter pour d'autres personnes qui tentent ce problème qu'il y avait une autre question ici:

insert(students.begin(), it, it) 

est de ne pas mettre quoi que ce soit dans le début du vecteur, car la plage notée par les deux derniers itérateurs argument faire une plage semi-ouverte, ce qui signifie une plage qui commence au premier itérateur et va jusqu'à n'inclut pas l'élément désigné par le dernier itérateur. En d'autres termes, l'intervalle [it, it) est une plage vide. Pour obtenir une gamme de juste 'il', vous auriez besoin de [it, it+1).

Bien sûr, cela aurait toujours le problème d'invalider tous les itérateurs en amont.

Questions connexes