Консультация № 177305
17.03.2010, 19:25
45.00 руб.
0 11 1
Здравствуйте.
Работаю в C++ builder 2010
Нужно отсортировать в StringGrid по фамилии данные, веденные пользователем.
Имя фамилия отчество
Андрей Андреев Сидорович
Саша Сидоров Аркадьевич

Вот пример кода, но он не сортирует почему то. Прошу помочь в написании кода.




Приложение:
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
struct btrud
{ char family [20];//фамилия
char name [20];//имя
char Patronymic [20];//отчество
char pol [8];//пол
char address [20];//адрес
char speciality [20];//должность
char experience[4];//стаж
char education [20];//образование
char phone [20];//телефон
};
btrud rabotnik[10];
FILE* f;

void __fastcall TForm1::N14Click(TObject *Sender) //сортировка по фамилии
//метод пузырька
{btrud temp;
/*for(int i=9;i<1;i++)
{for(int j=0;j<i;j++)
if(rabotnik[j].family>rabotnik[j+1].family)
{temp=rabotnik[j];
rabotnik[j]=rabotnik[j+1];
rabotnik[j+1]=temp;}}

for(int i=0;i<10;i++)
StringGrid1->Cells[0][i+1]=rabotnik[i].family;}
//---------------------------------------------------------------------------

Обсуждение

давно
Академик
320937
2216
17.03.2010, 21:17
общий
novij2011:
Код:

if(strcmp(rabotnik[j].family,rabotnik[j+1].family)==1)
{temp=rabotnik[j];
rabotnik[j]=rabotnik[j+1];
rabotnik[j+1]=temp;}}

И сам "пузырек" у Вас как-то запутан.
Неизвестный
17.03.2010, 21:30
общий
novij2011:
Здравствуйте.

Строчкой
if(rabotnik[j].family>rabotnik[j+1].family)
Вы сравниваете адреса первых символов, а не строк. Т.е. у Вас происходит сортировка, но не по тому признаку, который Вас интересует. Так же неплохо предусмотреть возможность совпадения фамилий у работников и сравнивать в таком случае имена, а потом и отчества.
давно
Старший Модератор
17042
808
18.03.2010, 08:45
общий
это ответ
Здравствуйте, novij2011!
Во-первых, непонятно, для чего Вы для хранения информации о работнике выбрали массивы символов: в Borland C++ Builder строки удобнее хранить в виде объектов класса AnsiString, что облегчает взаимодействие с компонентами среды и работу с данными, поскольку класс AnsiString включает в себя много полезных методов, в том числе операторы сравнения строк.
Во-вторых, лучше список работников хранить в виде вектора (std::vector) объектов класса работника (в моём варианте - класс TWorker) - члена главной формы (см. приложение).
Для удобства в заголовочном файле класса главной формы приложения (TMainForm) я объявил класс TWorker только с теми членами, которые будут выводиться в StringGrid (т.е. имя, отчество, фамилия).
Внешний вид приложения показан на рисунке ниже (введённые данные отсортированы):


Ввод данных осуществляется при нажатии на кнопку SubmitButton, при этом данные сохраняются в векторе, а поля ввода очищаются (см. приложение).
При нажатии на кнопку ShowButton осуществляется сортировка объектов вектора, если он не пуст, и данные выводятся в таблицу (см. приложение).
Проект Borland Developer Studio 2006 прикреплён к ответу.
Удачи!

Приложение:
// Заголовочный файл класса главной формы
//---------------------------------------------------------------------------

#ifndef MainUnitH
#define MainUnitH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <Grids.hpp>
//---------------------------------------------------------------------------
#include <vector> // Подключаем вектор STL
using namespace std; // Подключаем пространство имён std;
//---------------------------------------------------------------------------
class TWorker // Класс работника
{
public:
TWorker(){}; // Пустой конструктор

AnsiString sName; // Имя
AnsiString sMiddleName; // Отчество
AnsiString sLastName; // Фамилия
};
//---------------------------------------------------------------------------
class TMainForm : public TForm
{
__published: // IDE-managed Components
TLabel *InputLabel;
TEdit *NameEdit;
TEdit *MiddleNameEdit;
TEdit *LastNameEdit;
TLabel *NameLabel;
TLabel *MiddleNameLabel;
TLabel *LastNameLabel;
TButton *SubmitButton;
TStringGrid *WorkersGrid;
TButton *ShowButton;
void __fastcall SubmitButtonClick(TObject *Sender);
void __fastcall ShowButtonClick(TObject *Sender);
private:
vector<TWorker> Worker; // Вектор - список работников
public: // User declarations
__fastcall TMainForm(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TMainForm *MainForm;
//---------------------------------------------------------------------------
#endif

// Файл реализации класса главной формы
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "MainUnit.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TMainForm *MainForm;
//---------------------------------------------------------------------------
__fastcall TMainForm::TMainForm(TComponent* Owner)
: TForm(Owner)
{
WorkersGrid->Cells[1][0] = "Имя"; // Заголовки таблицы
WorkersGrid->Cells[2][0] = "Фамилия";
WorkersGrid->Cells[3][0] = "Отчество";
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::SubmitButtonClick(TObject *Sender)
{
// Если поля ввода не заполнены - сообщаем об ошибке
if(NameEdit->Text.IsEmpty() || MiddleNameEdit->Text.IsEmpty() || LastNameEdit->Text.IsEmpty())
{
MessageBox(0, "Введите данные!", "Ошибка!", MB_ICONWARNING | MB_OK);
return;
}

TWorker Worker;
Worker.sName = NameEdit->Text;
Worker.sMiddleName = MiddleNameEdit->Text;
Worker.sLastName = LastNameEdit->Text;
this->Worker.push_back(Worker); // Добавляем данные о работнике в вектор

NameEdit->Clear(); // Очищаем поля ввода
MiddleNameEdit->Clear();
LastNameEdit->Clear();
}
//---------------------------------------------------------------------------
void __fastcall TMainForm::ShowButtonClick(TObject *Sender)
{
if(Worker.size() == 0) // Если вектор пуст - сообщаем об ошибке
{
MessageBox(0, "Нет введённых данных о работниках.", "Ошибка!", MB_ICONWARNING | MB_OK);
return;
}

TWorker TempWorker; // Сортируем вектор
for(unsigned i = 0; i <= (Worker.size() - 1); i++)
{
for(unsigned j = i + 1; j < Worker.size(); j++)
{
if(Worker[i].sLastName > Worker[j].sLastName)
{
TempWorker = Worker[i];
Worker[i] = Worker[j];
Worker[j] = TempWorker;
}
}
}

// И выводим данные в таблицу.
WorkersGrid->RowCount = (int)(Worker.size() + 1);
for(unsigned i = 0; i < Worker.size(); i++)
{
WorkersGrid->Cells[0][i + 1] = IntToStr(i + 1);
WorkersGrid->Cells[1][i + 1] = Worker[i].sName;
WorkersGrid->Cells[2][i + 1] = Worker[i].sLastName;
WorkersGrid->Cells[3][i + 1] = Worker[i].sMiddleName;
}
}
//---------------------------------------------------------------------------
Прикрепленные файлы:
5
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
Неизвестный
18.03.2010, 09:49
общий
большое вам спасибо.
Неизвестный
18.03.2010, 17:27
общий
я извиняюсь. А можно как- нибудь сделать так чтобы сортировалась по кнопке(напр. при нажатии "сортировать по фамилии" или "сортировать по имени"?
А то ваша программа сортирует сразу же.
давно
Старший Модератор
17042
808
18.03.2010, 18:45
общий
novij2011:
Да, конечно. Сортировка по фамилии происходит в цикле:

Код:

TWorker TempWorker;
for(unsigned i = 0; i <= (Worker.size() - 1); i++)
{
for(unsigned j = i + 1; j < Worker.size(); j++)
{
if(Worker[i].sLastName > Worker[j].sLastName)
{
TempWorker = Worker[i];
Worker[i] = Worker[j];
Worker[j] = TempWorker;
}
}
}


(т.е. вам нужно просто заменить текст кнопки "Показать" на "Сортировать по фамилии").

Соответственно, добавляете кнопку "Сортировать по имени", переносите предыдущий код в обработчик события щелчка по ней и заменяете строчку

Код:

if(Worker[i].sLastName > Worker[i + 1].sLastName)


на

Код:

if(Worker[i].sName > Worker[i + 1].sName)


Код вывода отсортированного вектора в таблицу одинаков для обоих случаев (можете оформить его в виде функции-члена класса главной формы и вызывать эту функцию из обработчиков щелчка по кнопкам).
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
Неизвестный
18.03.2010, 19:48
общий
спасибо за разъяснение.

И еще.
Не могли бы вы дописать к этой программе реализацию поиска(чтоб вводил слово пользователь в edit) и это слово находилось в stringgrid (если найдено две записи, то выводились только они)
и чтобы можно было из stringgrid сохранять в файл(напр.txt) и открывать из него данные.

доп. оплата гарантируется
просто я думал сохранить БД сам смогу, а раз тут используются вектора, то выдаются ошибки.
Неизвестный
19.03.2010, 10:06
общий
пожалуйста
Неизвестный
19.03.2010, 10:14
общий
и если можно объясните эту строку
i != (Worker.size() - 1);
Это вычисляется размер вектора, т.е. количество записей, занесенных в него?
давно
Старший Модератор
17042
808
19.03.2010, 12:49
общий
novij2011:
Вектор - это контейнер библиотеки STL языка C++ для хранения набора элементов того или иного типа, т.е. представляет собой динамический массив плюс ряд функций для работы с данными. Когда мы объявляем

Код:

vector<int> Integers;


то тем самым создаём пустой вектор для хранения целых чисел. Соответственно, в нашем случае

Код:

vector<TWorker> Worker;


- это вектор для хранения объектов созданного нами класса TWorker.
Метод push_back() используется для добавления элементов класса в конец вектора:

Код:

TWorker TmpWorker;
Worker.push_back(TmpWorker);


Метод size() возвращает число элементов вектора (unsigned int). Когда вектор пуст, size() == 0. Поскольку в C++ нумерация начинается с 0, то индекс последнего элемента вектора - size() - 1.
Об авторе:
We have but faith: we cannot know;
For knowledge is of things we see;
And yet we trust it comes from thee,
A beam in darkness: let it grow.
-----
https://www.linkedin.com/in/andreynkuznetsov
https://www.researchgate.net/profile/Andrey_Kuznetsov11
http://www.researcherid.com/rid/K-8824-2014
Неизвестный
19.03.2010, 15:28
общий
спасибо.
Форма ответа