Для подбора паролей существуют специализированные программы и специализированные методологии которые достаточно тяжело освоить. Способ же увидеть исходный код - пользоваться дизассемблерами.
по этому я и написал IDA + плагин HexRay сливай с кряклаба. Потому как IDA офегительно дизасемблит, а хексрей сторит на основе этого исходник сишный
Сейчас читаю книгу Джесса Либерти(освой с++ за 21 день). Дошел до связных списков. Там довольно таки сложно и не понятно для меня написано(я про тот огромный пример что в книге). Общий принцип понял, но все еще смутно понимаю эти листы. Напишите плз, кому не сложно какой-то интересный и очень простой примерчик работы с листами с хорошими коментами. Заранее спасибо!
давай немного по-другому - ты пишешь пример, как ты понял листы. это как бы лучше запоминается и понимается. вся суть сводится к такому. Code: struct LIST_ITEM{ LIST_ITEM* next; //LIST_ITEM* prev; // если двунаправленный int data; }; LIST_ITEM* head; // начало списка //Добавление: LIST_ITEM* old_head = head; head = new LIST_ITEM; head->next = old_head; Удаление сделай сам. Как и проход, и признак конца, и циклический список, двунаправленный.
Я понимаю листы так: Он состоит из головы, узла с данными и хвоста. Но я не могу понять роли каждого из элементов. Ну на пример, я вижу роли так - в узле содержатся данные и адрес следующего узла. В голове содержится адрес первого узла. В хвосте содержится адрес головы или как? В общем посидел, подумал поэкспериментировал... Code: #include <iostream> using namespace std; class List { public: List* next; int data; }; class Head { public: List* next; }; /*class Tail { public: List* last; };*/ void main() { // начало списка, создание первого узла и головы List* Node = new List; Head* head = new Head; //Tail* tail = new Tail; head->next = Node; int i = 1; //Добавление: while(1) { cout << "data #" << i << " = "; cin >> Node->data; i++; if(!Node->data) { //tail->last = Node; break; } Node->next = new List; Node = Node->next; } cout << head->next->data << endl; } 1. Правильный ли я лист создал? 2. Как мне вывести все значения в листе, начиная с головы?(данный вариант вывода показывает только одно значение с первого узла, хотя в отладке я вижу полную иерархию всех значений) 3. Если лист правильный, то можно ли его оптимизировать? 4. Что вообще нужно с хвостом делать?
Смысл в том, ч то у нас есть элемент, в котором Code: Односвязный список info - тело несущее информацию after - адрес следующего элемента Code: Двусвязный список befor - адрес предидущего элемента info - тело несущее информацию after - адрес следующего элемента тогда зная адрес первого элемента - можно обрататиться к цепочки. Когда after = NULL - значит конец цепочки Чтобы получить нужный элемент, мы начиная с первого в цикле прыгаем на адрес следуеющего элемента => количество прыжков = индекс эелмента Пример на C - работа с односвязным списком: Code: #include <iostream> #include <cstdlib> #define length 20 void create(char filename[]); void open(char filename[], struct s_item *item[]); int find(struct s_item *item[]); int add_item(struct s_item item, int position); int del_item(int position); int erase_item(); int show_items(); struct s_item { int id; char name[length]; }; struct p_item { struct s_item info; struct p_item *next; }; struct p_item *first; struct p_item *counter; int main() { system("chcp 1251"); printf("\n"); struct s_item item; char menu; char filename[length]; int high; int size; int position; first = NULL; while(true) { printf("Введите номер действия :\n"); printf("========================\n"); printf("1 - Добавить\n"); printf("2 - Вставить\n"); printf("3 - Удалить\n"); printf("4 - Очистить\n"); printf("5 - Вывести\n"); printf("6 - Выход\n\n"); printf("Номер = "); scanf("%i", &menu); printf("\n"); if (menu == 1 || menu == 2) { printf("Введите номер товара : "); scanf("%i", &item.id); printf("Введите наименование товара : "); scanf("%s", &item.name); printf("\n"); } switch(menu) { case 1: position = -1; add_item(item, position); break; case 2: printf("Введите позицию вставки : "); scanf("%i", &position); printf("\n"); add_item(item, position); break; case 3: printf("Введите позицию удаления : "); scanf("%i", &position); printf("\n"); del_item(position); break; case 4: erase_item(); break; case 5: show_items(); break; case 6: return EXIT_SUCCESS; break; default: return EXIT_SUCCESS; break; } } return EXIT_SUCCESS; } int erase_item() { struct p_item *now; counter = first; while (counter != NULL) { now = counter->next; counter->next = NULL; free(counter); counter = now; } first = NULL; } int add_item(struct s_item item, int position) { struct p_item *now; struct p_item *tmp; now = (p_item *) malloc(sizeof(p_item)); if (now == NULL) { printf("Not enough memory to allocate buffer\nProgramm halted...\n"); } else { now->info = item; now->next = NULL; if (first == NULL) { first = now; } else { switch (position) { case -1: counter = first; while (counter->next != NULL) { counter = counter->next; } counter->next = now; break; case 0: tmp = first; first = now; now = tmp; first->next = now; printf("%i - %i = %i", first->next, now, now->next); break; default: counter = first; for (int i = 2; i <= position; i++) { counter = counter->next; if (counter == NULL) { printf("Position not in array!\n"); return 0; } } now->next = counter->next; counter->next = now; break; } return 1; } } return 0; } int del_item(int position) { struct p_item *now; if (first == NULL) { return 0; } else { if (position > -1) { if (position == 0) { now = first; first = first->next; } else { counter = first; now = counter->next; for (int i = 2; i <= position; i++) { counter = counter->next; now = counter->next; if (now == NULL) { printf("Position not in array!\n"); return 0; } } counter->next = now->next; now->next = NULL; } free(now); } else { counter = first; now = counter->next; while (now->next != NULL) { counter = counter->next; now = counter->next; } free(now); counter->next = NULL; } return 1; } return 0; } int show_items() { counter = first; if (first == NULL) { printf("Записей нет!\n\n"); } else { printf("Вывод товара\n"); printf("=============\n"); while(counter != NULL) { printf("Номер товара = %i\n", counter->info.id); printf("Наименование товара = %s\n", counter->info.name); printf("\n"); counter = counter->next; } printf("\n"); } }
FireFenix, спасибо, но мне пока сложно большие примеры разбирать. В книге тоже не маленький, потому и много сложностей. Если не сложно - разберите прогу что я написал с ответами на вопросы тобишь доработкой. Спасибо.
ты представь состав из вагонов. как понять, что вагон начинает состав? у него нет предыдущего вагона. как понять, что вагон последний - у него нет следующего. так и со списками. голова и хвост - это логические описание конкретного элемента списка. это не отдельный тип элемента списка. в этом собсно суть. в твоем примере нужен только класс лист. переименуй его в ListItem. он сожержит данные и указатель на следующий элемент. Добавь еще один класс - List. он как раз управляет элементами и содержит поле ListItem* head; Если кратко получишь такое Code: class ListItem{ public: ListItem(int _data){ data = _data; next = 0; }; int data; ListItem* next; }; class List{ public: void add(int data){ getTail()->next = new ListItem(data); }; bool find(int data); bool del(int data); private: ListItem* getTail(){ ListItem* item = head; while(item->next){ item = item->next; } return item; }; ListItem* head; };
и кстати, нашел интересную инфу о листах, главное очень понятно и толково рассказано. линк Там в нескольких шагах рассказано все. З.Ы. Что значит к примеру такое объявление, выделенное красным цветом, тоесть две звездочки и для чего оно нужно?: void POSTROENIE (node **phead)
только так можно сделать многомерные массивы аля матрица на счет описания. сложно оценить. в списке я не вижу никаких трудностей. то что ты стал мутить с классами - проблема не в списке. проблема в использовании ООП. ты создал отдельные классы для сущностей, которые не отличаются ничем в поведении. все равно что создавать класс для числа 1, другой класс для числа 2, итд. Так что стоит внимательнее перечитать, что пишут про выделение классов. Все таки их разделяют не именам, а по поведению. Если поведение не отличается - делается переменная этого класса, имеющая имя, которое характеризует назначение этого объекта. вот если бы хвост например не мог содержать число 555, а голова число 777, то тут есть повод выделить доп классы, потому как поля вроде как одинаковые, но поведение отличается. ps: стиль именования в статье ужасен просто аж ппц. и постоянные размыеновавния. как будто человек не знает про "->"
Ну про код - согласен, но картинки сделали более понятным представление головы и дальнейшее построение списка. З.Ы. Сейчас пишу прогу по созданию листа. Уже реализовал заполнение листа данными, вывод данных на экран, поиск во всем листе и вывод найденных данных на экран и удаление всего листа. Теперь хочу реализовать добавление в средину (или куда-то еще, то есть сдвиг) узла в лист и удаление одного узла. З.Ы.Ы Можно плз примерчик многомерными массивами(с использованием **указателя) З.Ы.Ы.Ы Еще раз спасибо за объяснения
Поищи в разделе, выкладывалось несколько раз вот например Это если ты хотел просто пример работы, а не применительно к спикам.
И снова я с вопросом. В общем такая ситуация: Code: #include <iostream> using namespace std; class node { public: void C(node* _node); int data; }; void main() { node* _node = 0; _node->C(_node); cout << _node->data << endl;//и тут ступор } void node::C(node *_node) { _node = new node; _node->data = 5; } Что я тут не правильно сделал? Почему после возвращения в мейн, данные теряются? Вроде как указатели юзаю... Я то проблему решил, но совсем не так как мне этого хотелось. Вышло что-то типа: Code: #include <iostream> using namespace std; class node { public: node* C(node* _node); int data; }; void main() { node* _node = 0; _node = _node->C(_node); cout << _node->data << endl; } node* node::C(node *_node) { _node = new node; _node->data = 5; return _node; } Почему первый вариант не работает? Как решить проблему?
жуть. почитай ка лучше дейтела. я даже не могу понять, что ты хочешь этим кодом сделать... тут не список даже. чем то напоминает фабричный метод, тока зачем он здесь?
Code: node* _node = 0; _node->C(_node); Как это может быть? Ты делаешь у указателя значение 0 и пытаешься потом по этому адресу обратиться...