#include <iostream> #include <Windows.h> #include <conio.h> #include <string.h> #include <stdlib.h> #include <stdio.h> using namespace std; int main() { /* Фамилия студента Номер зачетки Массив из 4 оценок  Сортировка структур по фамилии или среднему баллу  Удаление всех зачеток троечников */ const int n=2; struct ZACHETKA { char last_name[30]; int no; int ocenka[3]; }; int j,i; ZACHETKA* box = new ZACHETKA[n]; ZACHETKA tmp; for(i=0; i<n; i++) { cin.sync(); cout<<"Vvedite Familiy"<<endl; cin.getline(box[i].last_name, 30); cout<<"Vvedite nomer"<<endl; cin>>box[i].no; cout<<"Vvedite ocenki (4)"<<endl; for(j=0; j<4; j++) cin>>box[i].ocenka[j]; } //- Cортировка по фамилии for(i=n-1; i>0 ; i--) for(j=0; j<i ; j++) if(strcmp( box[ j ].last_name, box[ j+1 ].last_name ) > 0) { tmp = box[ j ]; box[ j ]= box[ j+1 ]; box[ j+1 ]= tmp; } //- Удаление всех зачеток троечников for(i=0; i<n; i++) for(j=0; j<4; j++) if(box[i].ocenka[j] == 3) delete [] box[i]; for(i=0; i<n; i++) { cout<<box[i].last_name<<endl; cout<<box[i].no<<endl; for(j=0; j<4; j++) cout<<box[i].ocenka[j]<<endl; } system("pause"); return 0; } 

How to work correctly with a dynamic array of structures and why an error is generated at a distance of troechnik. And for some reason, the third estimate in the first entered record on the output is some kind of left healthy number. Well, I would like to hear what at once shoals are evident.

  • @RubyNub, from the answers and comments you apparently already understood that the main mistake is the impossibility of using delete to delete an element of an array. Instead, you just need to “wipe” the records of troechnik, shifting the rest to the left. Suppose found k troechnikov. As a result, you should have actual nk elements in the array, i.e. then you need to print not n , but nk lines. (The size of the allocated memory will not change). - By the way, the search for troechnikov and the transfer of actual records to the left, can be combined in one cycle. Perhaps this is what the teacher wants from you. - avp

2 answers 2

The code is written poorly, you need to decide exactly what you are writing - C, C + or C ++ (C + is such a joke. When the code is written in C ++, but as much as possible in C style).

why does the error give at the distance of troechnik

Look at your code

 for(i=0; i<n; i++) for(j=0; j<4; j++) if(box[i].ocenka[j] == 3) delete [] box[i]; 

If the very first assessment is a troika, then when checking the second assessment there will be a mess. Because the item is already deleted. And this is wrong. But the problem is that you cannot delete it from a regular array. This is not a vector. But if you want to remove all non-troeshnikov, it is not necessary to delete. You can just skip the output. In your case it will be easier.

Well, I would like to hear what at once shoals are evident.

The worst thing that catches is the following lines.

 #include <Windows.h> #include <conio.h> 

The first is definitely not needed, and the second is for ancient compilers.

I corrected the code a bit, it is now compiled with a clean C compiler.

 #include <string.h> #include <stdlib.h> #include <stdio.h> const int n=2; struct ZACHETKA { char last_name[30]; int no; int ocenka[3]; }; int main() { /* Фамилия студента Номер зачетки Массив из 4 оценок Сортировка структур по фамилии или среднему баллу Удаление всех зачеток троечников */ int j,i; struct ZACHETKA* box = (struct ZACHETKA*)malloc(sizeof(struct ZACHETKA) * n); struct ZACHETKA tmp; for(i=0; i<n; i++) { puts("Vvedite Familiy\n"); scanf("%s", box[i].last_name); puts("Vvedite nomer\n"); scanf("%d", &box[i].no); puts("Vvedite ocenki (3)\n"); scanf("%d %d %d", &box[i].ocenka[0], &box[i].ocenka[1], &box[i].ocenka[2]); } //- Cортировка по фамилии for(i=n-1; i>0 ; i--) for(j=0; j<i ; j++) if(strcmp( box[ j ].last_name, box[ j+1 ].last_name ) > 0) { tmp = box[ j ]; box[ j ]= box[ j+1 ]; box[ j+1 ]= tmp; } for(i=0; i<n; i++) { for (int j = 0; j < 3; j++) { if (box[i].ocenka[j] == 3) goto fin; // да, в данном случае это оправдано, это си } printf("%s\n", box[i].last_name); printf("%d\n", box[i].no); for(j=0; j<3; j++) printf("%d ", box[i].ocenka[j]); printf("\n"); fin:; } free(box); return 0; } 

I decided to comb a little code and translate it into a more flattened one. I would say it with a plus and a half.

 #include <string> #include <iostream> #include <vector> const int max_number_of_students=2; const int grades_count = 3; struct RecordBook // да, так будет зачетка { std::string last_name; int no; int grades[grades_count]; // раньше это называлось "ocenka" }; int main() { /* Фамилия студента Номер зачетки Массив из 4 оценок Сортировка структур по фамилии или среднему баллу Удаление всех зачеток троечников */ std::vector<RecordBook> box; RecordBook t; for(int i = 0; i < max_number_of_students; i++) { std::cout << "Enter Last Name:" << std::endl; getline(std::cin, t.last_name); std::cout << "Enter Nomer:" << std::endl; std::cin >> t.no; std::cout << "Enter grades (count:"<< grades_count <<")" << std::endl; for (int j = 0; j < grades_count; j++) std::cin >> t.grades[j]; // почему эта строка ниже - http://modwind.ru/publ/cpp_io_input_output_advice/6-1-0-7 std::cin.ignore(50, '\n'); box.push_back(t); } //- Cортировка по фамилии // Здесь хорошо бы применить стандартный алгоритм сортировки, но боюсь это будет перебор. for(size_t i=box.size()-1; i>0 ; i--) for(size_t j=0; j<i ; j++) if(box[ j ].last_name > box[ j+1 ].last_name) { std::swap(box[j], box[j+1]); // три строки ниже - олд-скул вариант. //RecordBook t = box[j]; //box[j] = box[j+1]; //box[j+1] = t; } for(size_t i=0; i<box.size(); i++) { bool is_find = false; for (int j = 0; j < grades_count; j++) { if (box[i].grades[j] == 3) { is_find = true; break; } } if (is_find) continue; std::cout << box[i].last_name << std::endl << box[i].no << std::endl; for(int j=0; j<grades_count; j++) std::cout << box[i].grades[j] << " "; std::cout << std::endl; } return 0; } 

The code is a little combed, the transliteration is altered into more or less English, many magic numbers are rendered into constants. The number of students you need to enter is now set only in one place and this is easy to change. I didn’t turn on many changes that I would have done (I would then write another 20 pages of decryption for the teacher).

  • Wow how many kind of "kaki". Can you show on the pros? Because all the same it is better to be right on the pros, than with such a primitive to be perverted. - RubyNub
  • The cycle with j < 4 not quite true, it is necessary to 3 - and probably better to declare a named constant. - VladD
  • @RubyNub - You have already decided. pure si is bad, s ++ is bad. @VladD from a minus someone put just for fun. - KoVadim
  • @KoVadim, I came to the conclusion that I would try to focus on the advantages and, as the level of knowledge increased, write without C + similarities. Please help me with the implementation of this problem in pure C ++, and I will take at least the same straustup and will understand it little by little. - RubyNub
  • @KoVadim thanks, it's really easier if you use standard containers. But I still do not understand why you can not just delete the records with triples? And I would like to know what standard sorting algorithm do you mean? - RubyNub

(This part of the answer is for C ++).

For starters, use standard containers and std::string . Immediately striking, honestly.

Then break the code into procedures! Small, with meaningful names.

Then encapsulate the type comparison operations inside your classes. Now you are writing as if on pure C, only without procedures.

Then, don't reinvent bicycles where you don't need them. For example, manual sorting inserts is not interesting to anyone. Use library sorting - reduce the number of errors.


Now within pure C.

First, you should not copy potentially large structures by value ( tmp = box[ j ] , etc.). Store pointers to structures in the array.

Then, for some reason, you have a cycle of j to 4 in “Deleting all the record books of troechnik students”. This is wrong, you have only 3 assessments. In general, this error would not have happened if you had used instead of literal 4 a named constant.

Then, delete [] box[i] is not allowed. You cannot delete an element from the middle of the native array, sorry, this is not C ++. You have to do it differently: move all elements to the left by one, and remember the new length. Complicated? Yes. In the next iteration of the loop, you need not make a mistake with the index.

  • Please explain what are standard containers and why is it better to clog the code with permanent std :: string? - RubyNub 5:03 pm
  • Standard containers are std::vector , std::map , std::set and the like. You should use them instead of native arrays. Do you really not know the difference between a native string and std::string ? As long as you do not answer this question yourself, the use of the correct lines will be considered a “clogging” for you. That's because you don’t work with C ++ classes that are easy to use, but try to write very low-level code (without proper skill), and errors like the "left healthy number" occur. - VladD pm
  • one
    Do not give harmful advice. This is an educational task and its essence is to write bicycles, thereby acquiring essential skills. - AlexDenisov
  • one
    @RubyNun, in your place I would write as it should. You can certainly make such a miracle, as the teacher recommends, then maybe you have chosen the wrong institute? - KoVadim
  • 2
    I do not know what the "best technical college" of this country is. When I studied (as I understand it, I did not study in "this country"), then it was possible to get a bad mark for such a code right away. My institute is definitely among the top ten technicals, but the specialty is not programming, not even close programming. Although, to be honest, on the one hand, I support such teachers - they kill competitors on the approach :), but on the other hand, it makes me very sad ... - KoVadim