Все технические форумы на одном сайте Удобный поиск информации с популярных форумов в одном месте
Вопрос: кеширование данных

Здравствуйте

Проблема такая:
Появилась задача реализации живого поиска: у Вас есть некий контрол на форме, пользователь что-то вводит в него и в выпадающем списке появляются элементы, начинающиеся с введенной последовательности символов.

Нужно сделать так, чтобы не было обращения к базе данных при вводе каждой буквы, то есть организовать некоторый кеш.

Например, Вы ищете человека по фамилии. По первым 2 буквам нашлось 500 человек в базе, в кеш взято 300. Дальше при вводе 3 буквы надо принять решение:взять из кеша или обратиться к базе и обновить кеш.

Знаете ли Вы какие-нибудь паттерны решений такой задачи?
Ответ:
ViPRos
Где-то в степи,

как не крути все равно таблица
гы
как ни крути, все равно оперативная память
как ни крути, все равно компьютер
...
как ни крути, все равно энергия
Вопрос: Кеширование js/css через "?число" не работает...

Приветствую. Для кеширования файлов js и css добавил в код всем известную конструкцию с временем последнего изменения файла:
Код

  <link rel="stylesheet" type="text/css" href="css/general.css?<?= filemtime('css/general.css'); ?>" />
  <script type="text/javascript" src="js/functions.js?<?= filemtime('js/functions.js'); ?>"></script>

На всякий случай решил посмотреть в фаербаге как оно работает. Каково же было моё удивление, когда я увидел что никто ничего не кеширует.  :crazy
По-порядку. Захожу первый раз, с чистым кешем, всё берётся с сервера. Второй раз, уже всё берётся из кеша браузера, как и задумано:
(IMG:)

Но, немного погодя (буквально через минуту) захожу на страницу опять и вижу, что никакого кеширования искомых файлов не делается:
(IMG:)

Получается, все эти телодвижения бессмысленны? Но ведь так делает весь интернет. Зашел на вк, там всё работает как положено:
(IMG:)

Получается, грабли у меня? Но где? Посмотрел заголовки ответа сервера (это для страницы):
Код

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 18 Jul 2016 08:19:11 GMT
Content-Type: text/html
Content-Length: 775
Connection: keep-alive
X-Powered-By: PHP/5.4.45-0+deb7u2, PleskLin
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip

Может быть кеширования нет из за заголовков "no-cache, must-revalidate, post-check=0, pre-check=0"? Но кто их шлёт? В моём коде такого точно нет. Дальше, вот заголовок ответа и запроса непосредственно для самого файла general.css:
Код

HTTP/1.1 304 Not Modified
Server: nginx
Date: Mon, 18 Jul 2016 08:19:11 GMT
Last-Modified: Mon, 18 Jul 2016 07:41:22 GMT
Connection: keep-alive
Etag: "578c8822-9d7"
X-Powered-By: PleskLin



GET /------------/css/general.css?1468827682 HTTP/1.1
Host: ------------
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0 FirePHP/0.7.4
Accept: text/css,*/*;q=0.1
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://-----------------/
Cookie: PHPSESSID=03c85922138d003360ec7b3d545b60a7; imp_id=56802e9cc2317f3a15434e5850903671; adminer_version=0
Authorization: Basic ************
x-insight: activate
Connection: keep-alive
If-Modified-Since: Mon, 18 Jul 2016 07:41:22 GMT
If-None-Match: "578c8822-9d7"

Последние две строки намекают на то, что файл не менялся. Но он тем не менее не кешируется, ни в какую.
Ответ:
Приветствую. Для кеширования файлов js и css добавил в код всем известную конструкцию с временем последнего изменения файла:
Код

  <link rel="stylesheet" type="text/css" href="css/general.css?<?= filemtime('css/general.css'); ?>" />
  <script type="text/javascript" src="js/functions.js?<?= filemtime('js/functions.js'); ?>"></script>

На всякий случай решил посмотреть в фаербаге как оно работает. Каково же было моё удивление, когда я увидел что никто ничего не кеширует.  :crazy
По-порядку. Захожу первый раз, с чистым кешем, всё берётся с сервера. Второй раз, уже всё берётся из кеша браузера, как и задумано:
(IMG:)

Но, немного погодя (буквально через минуту) захожу на страницу опять и вижу, что никакого кеширования искомых файлов не делается:
(IMG:)

Получается, все эти телодвижения бессмысленны? Но ведь так делает весь интернет. Зашел на вк, там всё работает как положено:
(IMG:)

Получается, грабли у меня? Но где? Посмотрел заголовки ответа сервера (это для страницы):
Код

HTTP/1.1 200 OK
Server: nginx
Date: Mon, 18 Jul 2016 08:19:11 GMT
Content-Type: text/html
Content-Length: 775
Connection: keep-alive
X-Powered-By: PHP/5.4.45-0+deb7u2, PleskLin
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Pragma: no-cache
Vary: Accept-Encoding
Content-Encoding: gzip

Может быть кеширования нет из за заголовков "no-cache, must-revalidate, post-check=0, pre-check=0"? Но кто их шлёт? В моём коде такого точно нет. Дальше, вот заголовок ответа и запроса непосредственно для самого файла general.css:
Код

HTTP/1.1 304 Not Modified
Server: nginx
Date: Mon, 18 Jul 2016 08:19:11 GMT
Last-Modified: Mon, 18 Jul 2016 07:41:22 GMT
Connection: keep-alive
Etag: "578c8822-9d7"
X-Powered-By: PleskLin



GET /------------/css/general.css?1468827682 HTTP/1.1
Host: ------------
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0 FirePHP/0.7.4
Accept: text/css,*/*;q=0.1
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3
Accept-Encoding: gzip, deflate
DNT: 1
Referer: http://-----------------/
Cookie: PHPSESSID=03c85922138d003360ec7b3d545b60a7; imp_id=56802e9cc2317f3a15434e5850903671; adminer_version=0
Authorization: Basic ************
x-insight: activate
Connection: keep-alive
If-Modified-Since: Mon, 18 Jul 2016 07:41:22 GMT
If-None-Match: "578c8822-9d7"

Последние две строки намекают на то, что файл не менялся. Но он тем не менее не кешируется, ни в какую.
Вопрос: настройка кеширования eclipselink

Доброго времени суток!
Подскажите как можно корректно настроить кеширование eclipselink? Прежде не сталкивался с кешированием eclipselink...
Я не могу понять, работает он или нет..
может мне необходимо что-то добавить в настройки или же наоборот убрать??

<properties>
            <property name="javax.persistence.nonJtaDataSource" value="java:/comp/env/jdbc/myD"/>
            <property name="eclipselink.weaving" value="false"/>
            <property name="eclipselink.logging.level" value="INFO"/>
            <property name="eclipselink.logging.level.sql" value="FINE"/>
            <property name="eclipselink.logging.parameters" value="true"/>
            <property name="eclipselink.query-results-cache" value="false"/>

            <property name="eclipselink.cache.shared.MyEntity" value="true"/>
            <property name="eclipselink.cache.type.MyEntity" value="SOFT"/>
            <property name="eclipselink.cache.size.MyEntity" value="64000"/>

            <!--<property name="eclipselink.batch" value="true"/>-->
            <property name="eclipselink.jdbc.batch-writing" value="JDBC"/> <property name="eclipselink.jdbc.batch-writing.size" value="15"/>
        </properties>
Ответ:
Kachalov
vlad2018
[Ниже привожу пример реализации, но все еще не могу понять работает кэш или нет.. может я что-то не так делаю??

- этот пример ничего не проверяет (точнее в нем задействован только кэш первого уровня). Вам необходимо несколько инстансов EntityManager-а в приложении и изменение данных не через EntityManager. Ничего этого здесь нет.


Так как мне правильно его настроить??
Вопрос: Отловить завершение чужих потоков

Вопрос знатокам WinAPI (и желательно POSIX)

В произвольное время разные потоки дёргают мою функцию. Причём потоки могут быть созданы в отдельном Dll кем угодно.
В момент вызова функции я могу получить CurretThreadId.
Необходимо, зная эти ThreadId, навесить на потоки какой-нибудь калбек, который будет вызываться после завершения потока. С эксепшном или в штатном режиме.
Каким образом?

Опережая вопрос "зачем тебе это".
Есть несколько мультипоточных высоконагруженных проектов. Причём бывает потоки создаются в сторонней Dll.
Было решено поменять принципы обработки данных, задействуя threadvar и кеширование данных/буферов.
Но беда в том, что threadvar-области не финализируются при завершении потока.
Тот же TParallel постоянно создаёт и удаляет потоки, а у нас течёт память, причём серьёзно.
Ответ:
SOFT FOR YOU
Вопрос знатокам WinAPI (и желательно POSIX)

В произвольное время разные потоки дёргают мою функцию. Причём потоки могут быть созданы в отдельном Dll кем угодно.
В момент вызова функции я могу получить CurretThreadId.
Необходимо, зная эти ThreadId, навесить на потоки какой-нибудь калбек, который будет вызываться после завершения потока. С эксепшном или в штатном режиме.
Каким образом?

Опережая вопрос "зачем тебе это".
Есть несколько мультипоточных высоконагруженных проектов. Причём бывает потоки создаются в сторонней Dll.
Было решено поменять принципы обработки данных, задействуя threadvar и кеширование данных/буферов.
Но беда в том, что threadvar-области не финализируются при завершении потока.
Тот же TParallel постоянно создаёт и удаляет потоки, а у нас течёт память, причём серьёзно.



температуру мерил?
Вопрос: запрет кеширования

можно ли с помощью PHP запретить кеширования?

В сети нащел такой код

header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
	header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); 
	header("Cache-Control: no-store, no-cache, must-revalidate"); 
	header("Cache-Control: post-check=0, pre-check=0", false);
	header("Pragma: no-cache");


Но чтото не работает!.
Ответ:
SharuPoNemnogu
ой простите, тут наоборот, не работает..
А время на компе и на сервере совпадает? В системе не используется кеширование? есть проверенный дедовский метод, дописать ?v=<?php echo time(); ?>


Спасибо за совет!
Вопрос: C# стрим и кеширование видео

Хорошего настроения каждому зашедшему.
Не могу справиться с проблемой.
Дано: приложение на с#, удаленный сервер с видео, приложение стримит видео с удаленного сервера.

Нужно сделать: сохранение стрима на компьютер, чтобы каждое просмотренное видео можно было отыграть в оффлайне.

Идея: сорц видеокомпонента посылает запрос не на сервер, а на "локальную прокси" (класс listener), этот класс заменяет Host  в хедере с 127.0.0.1:1489 на айпишник удаленного сервера, начинает стримить с сервера в видеокомпонент, попутно записывая получаемую информацию (видео) на диск.

Что есть: собственно, готов сам стрим без использования прокси, класс прокси (подключение к нему проходит успешно).

Что не получается сделать: наадить стрим в приложение через класс listener.

Не знаю, как послать запрос на получение данных из прокси на сервер.

Класс listener (прокси):

Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;


using System.IO;
using System.Threading;
using System.Text.RegularExpressions;

namespace Teacher
{
    public class Listener
    {

        public TcpListener _listener;

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //blocks until a client sends a message
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch
                {
                    //a socket error has occured
                    break;
                }

                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    break;
                }

                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                string resp = encoder.GetString(message, 0, bytesRead);
                System.Diagnostics.Debug.WriteLine(resp);

                //вот где-то тут нужно формировать и посылать хедер, но я не знаю, как
                int indx = resp.IndexOf("Host");
                string pattern = @"\b(\w+)\s\1\b";
                                
                Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
                
                var address = Dns.GetHostAddresses("hanker.ru")[0];

                string newresp = rgx.Replace(resp, "Host: 127.0.0.1:1488", "Host: " + address + ":1488");




            }

            tcpClient.Close();
        }

        public Listener()
        {
            new Thread(Start) { IsBackground = true }.Start();

        }

        private void Start()
        {
            _listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1488);
            //catch the MediaPlayer requests here 
            _listener.Start();
            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = _listener.AcceptTcpClient();
                // here was first an message that send hello client
                //
                ///////////////////////////////////////////////////
                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }


        //do streaming and caching here

        private int StreamAndSave(Stream outputNetStream, Stream responceStream, Stream fileStream, long fileSize)
        {
            int bytesRead = 0;
            byte[] buffer = new byte[4096];
            while (fileSize > 0)
            {
                int readBytes = responceStream.Read(buffer, 0, buffer.Length);
                if (readBytes > 0)
                {
                    try
                    {
                        //write bytes to response and send it to MediaPlayer
                        outputNetStream.Write(buffer, 0, readBytes);
                        //save to the file system
                        fileStream.Write(buffer, 0, readBytes);
                        bytesRead += readBytes;
                    }
                    catch (Exception e)
                    {
                        break;
                    }
                }
                else break;
                fileSize -= readBytes;
            }
            return bytesRead;
        }
    }
}
 

Код обращения к прокси:

Код

private void btnPlayVideo_Click(object sender, RoutedEventArgs e)
        {
            var w = SecondWindow.Instance;
            Listener SnS = new Listener(); //http://serverwithvideo.ru/files/{0}/{1}/video/{2}/{3}.mp4
            var uri = new Uri(string.Format(@"http://127.0.0.1:1488/files/{0}/{1}/video/{2}/{3}.mp4", w.DBroot.ShortName, w.CurrentFrame.Episode.Part.SelfIndex + 1, w.CurrentFrame.Episode.SelfIndex + 1, w.CurrentFrame.Scene.SelfIndex + 1));
            if (videoPlayer.Source != uri)
                videoPlayer.Source = uri;
            if (State == Teacher.VideoState.Playing)
            {
                Pause();
            }
            else
            {
                Play();
            }
        }
 

Помогите разобраться!
Ответ:
Хорошего настроения каждому зашедшему.
Не могу справиться с проблемой.
Дано: приложение на с#, удаленный сервер с видео, приложение стримит видео с удаленного сервера.

Нужно сделать: сохранение стрима на компьютер, чтобы каждое просмотренное видео можно было отыграть в оффлайне.

Идея: сорц видеокомпонента посылает запрос не на сервер, а на "локальную прокси" (класс listener), этот класс заменяет Host  в хедере с 127.0.0.1:1489 на айпишник удаленного сервера, начинает стримить с сервера в видеокомпонент, попутно записывая получаемую информацию (видео) на диск.

Что есть: собственно, готов сам стрим без использования прокси, класс прокси (подключение к нему проходит успешно).

Что не получается сделать: наадить стрим в приложение через класс listener.

Не знаю, как послать запрос на получение данных из прокси на сервер.

Класс listener (прокси):

Код
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;


using System.IO;
using System.Threading;
using System.Text.RegularExpressions;

namespace Teacher
{
    public class Listener
    {

        public TcpListener _listener;

        private void HandleClientComm(object client)
        {
            TcpClient tcpClient = (TcpClient)client;
            NetworkStream clientStream = tcpClient.GetStream();

            byte[] message = new byte[4096];
            int bytesRead;

            while (true)
            {
                bytesRead = 0;

                try
                {
                    //blocks until a client sends a message
                    bytesRead = clientStream.Read(message, 0, 4096);
                }
                catch
                {
                    //a socket error has occured
                    break;
                }

                if (bytesRead == 0)
                {
                    //the client has disconnected from the server
                    break;
                }

                //message has successfully been received
                ASCIIEncoding encoder = new ASCIIEncoding();
                string resp = encoder.GetString(message, 0, bytesRead);
                System.Diagnostics.Debug.WriteLine(resp);

                //вот где-то тут нужно формировать и посылать хедер, но я не знаю, как
                int indx = resp.IndexOf("Host");
                string pattern = @"\b(\w+)\s\1\b";
                                
                Regex rgx = new Regex(pattern, RegexOptions.IgnoreCase);
                
                var address = Dns.GetHostAddresses("hanker.ru")[0];

                string newresp = rgx.Replace(resp, "Host: 127.0.0.1:1488", "Host: " + address + ":1488");




            }

            tcpClient.Close();
        }

        public Listener()
        {
            new Thread(Start) { IsBackground = true }.Start();

        }

        private void Start()
        {
            _listener = new TcpListener(IPAddress.Parse("127.0.0.1"), 1488);
            //catch the MediaPlayer requests here 
            _listener.Start();
            while (true)
            {
                //blocks until a client has connected to the server
                TcpClient client = _listener.AcceptTcpClient();
                // here was first an message that send hello client
                //
                ///////////////////////////////////////////////////
                //create a thread to handle communication
                //with connected client
                Thread clientThread = new Thread(new ParameterizedThreadStart(HandleClientComm));
                clientThread.Start(client);
            }
        }


        //do streaming and caching here

        private int StreamAndSave(Stream outputNetStream, Stream responceStream, Stream fileStream, long fileSize)
        {
            int bytesRead = 0;
            byte[] buffer = new byte[4096];
            while (fileSize > 0)
            {
                int readBytes = responceStream.Read(buffer, 0, buffer.Length);
                if (readBytes > 0)
                {
                    try
                    {
                        //write bytes to response and send it to MediaPlayer
                        outputNetStream.Write(buffer, 0, readBytes);
                        //save to the file system
                        fileStream.Write(buffer, 0, readBytes);
                        bytesRead += readBytes;
                    }
                    catch (Exception e)
                    {
                        break;
                    }
                }
                else break;
                fileSize -= readBytes;
            }
            return bytesRead;
        }
    }
}
 

Код обращения к прокси:

Код

private void btnPlayVideo_Click(object sender, RoutedEventArgs e)
        {
            var w = SecondWindow.Instance;
            Listener SnS = new Listener(); //http://serverwithvideo.ru/files/{0}/{1}/video/{2}/{3}.mp4
            var uri = new Uri(string.Format(@"http://127.0.0.1:1488/files/{0}/{1}/video/{2}/{3}.mp4", w.DBroot.ShortName, w.CurrentFrame.Episode.Part.SelfIndex + 1, w.CurrentFrame.Episode.SelfIndex + 1, w.CurrentFrame.Scene.SelfIndex + 1));
            if (videoPlayer.Source != uri)
                videoPlayer.Source = uri;
            if (State == Teacher.VideoState.Playing)
            {
                Pause();
            }
            else
            {
                Play();
            }
        }
 

Помогите разобраться!
Вопрос: Как сделать ввод данных в файл с использованием связанного списка

у меня есть односторонний связанный список который расставляет данные в порядке увеличения.
данные это порядковый номер персонала.
проблема заключается в том чтобы данные записывались в файл именно по принципу связанного списка. в порядке возрастания 1,3,5,6,7 и т.д.
данные в файл записываются, но в хаотичном порядке.
но как это реализовать пока не знаю.
также буду рад, если оцените мой код и скажите примерно на каком уровне програмирования я нахожусь.
соответствую ли я junior уровню.
учусь около четырех месяцев.
спасибо заранее за помощь

вот исходный код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
#include <iostream>
#include <string>
#include<fstream>
typedef unsigned short USHORT;
using namespace std;
#include "данные.h"
#include "связанный список.h"
#include "ввод и вывод данных.h"
 
 
void Interface()
{
 
 
}
 
int main()
{
    setlocale(LC_ALL, "rus");
    Data personal;
    bool OnOf = true;
    
 
    while (OnOf)
    {
        short selection;
        cout << "Выберите операцию - (1)Ввод данных, (2) Чтение данных, (3) Очистка файла. (0) Выход\n";
        cin >> selection;
        //выбор операции файла.
        switch (selection)
        {
        case 1:personal.SpisokPersonal(); break;
        case 2:personal.SetFileName(); personal.Readfile(); break;
        case 3:personal.SetFileName(); personal.CleanFile(); break;
        case 0:  OnOf = false; break;
        default:continue;
        }
         
    }
    
    
    
    system("pause");
    return 0;
}
заголовочный файл - данные:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
//класс данных персонала
 
class Employee
{
public:
    Employee();
    
    Employee(char *, char *, char *, long, long);
    ~Employee();
    Employee(const Employee&);
    Employee & operator=(const Employee &);
    long Compare(const Employee &);
    virtual void Display()const
    {   
        cout << "*****************************\n";
        cout.setf(ios::left);
        cout << " Номер персонала: \t\a"<< ItsNumberPersonal << endl;
        cout << " Имя: \t" << ItsFirstName << endl;
        cout << " Фамилия: \t" << ItsLastName << endl;
        cout << " Адресс: \t" << ItsAddress << endl;
        cout << " Зарплата: \t" << ItsSalary << endl;
        cout << "*****************************\n";
        cout << "\n";
    }
 
    //Функции вывода инфорамации 
    const string   & GetFirstName()const
    {
        return ItsFirstName;
    }
    const string  & GetLastName()const
    {
        return ItsLastName;
    }
    const  string & GetAddress()const
    {
        return ItsAddress;
    }
    long GetSalary()const
    {
        return ItsSalary;
    }
    long GetNumberPersonal()const
    {
         return ItsNumberPersonal;
    }
 
 
    //Функции Ввода информации.
    void  SetFirstName(const string & FName)
    {
        ItsFirstName = FName;
    }
    void SetLastName(const string & LName)
    {
        ItsLastName = LName;
    }
    void SetAddress(const string & address)
    {
        ItsAddress = address;
    }
    void SetSalary(long salary)
    {
        ItsSalary = salary;
    }
    void SetNumberPersonal(long numberpersonal)
    {
        ItsNumberPersonal = numberpersonal;
    }
private:
    string ItsFirstName;
    string ItsLastName;
    string ItsAddress;
    long ItsSalary;
    long ItsNumberPersonal;
};
 
 
 
Employee::Employee() :
ItsFirstName(" "),
ItsLastName(" "),
ItsAddress(" "),
ItsSalary(0),
ItsNumberPersonal(1)
{}
 
 
Employee::Employee(char  * firstName, char * lastName, char * address, long salary,long numberPersonal) :
ItsFirstName(firstName),
ItsLastName(lastName),
ItsAddress(address),
ItsSalary(salary),
ItsNumberPersonal(numberPersonal)
{}
 
Employee::Employee(const Employee & rhs) :
ItsFirstName(rhs.GetFirstName()),
ItsLastName(rhs.GetLastName()),
ItsAddress(rhs.GetAddress()),
ItsSalary(rhs.GetSalary()),
ItsNumberPersonal(rhs.GetNumberPersonal())
{}
Employee::~Employee(){}
Employee & Employee::operator= (const Employee & rhs)
{
    if (this == &rhs)
    {
        return *this;
    }
    ItsFirstName = rhs.GetFirstName();
    ItsLastName = rhs.GetLastName();
    ItsAddress = rhs.GetAddress();
    ItsSalary = rhs.GetSalary();
    ItsNumberPersonal = rhs.GetNumberPersonal();
 
    return *this;
}
заголовочный файл - связанный список:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
//Шаблон связанного списка.
// константные перечисления для определения местоположения данных, в связаном списке.
enum { KisSmaller, KisLarger, KisSame };
 
///сами данные и функция сравнения.
long Employee::Compare(const  Employee & TheOtheNumber)
{
    if (ItsNumberPersonal < TheOtheNumber.ItsNumberPersonal)
    {
        return KisSmaller;
    }
    else if (ItsNumberPersonal> TheOtheNumber.ItsNumberPersonal)
        return KisLarger;
 
    else
        return KisSame;
}
 
 
template<class T_Spisok>
//чистый виртуальный класс ADT.
class Node
{
public:
    Node(){}
    virtual ~Node(){}
    //чиста виртуальная а функция сравнения.
    virtual Node * pInsert(T_Spisok * TheObject) = 0;
//чиста виртуальная функция отображения
    virtual void Display()const = 0;
private:
};
 
template<class T_Spisok>
//Внутрений узел. здесь храняться адрес расположения данных
class InternalNode : public Node<T_Spisok>
{
public:
    InternalNode(T_Spisok * TheObject, Node<T_Spisok> * next);
 
    virtual ~InternalNode(){ delete T_MyNext, delete T_MyOblect; }
    //виртуальная функция отображения адрессов, расположения данных.
    virtual void Display()const
    {
        T_MyOblect->Display(); T_MyNext->Display();
    }
    virtual Node<T_Spisok> * pInsert(T_Spisok * TheObject);
private:
    T_Spisok * T_MyOblect;
    Node<T_Spisok> * T_MyNext;
};
template<class T_Spisok>
InternalNode<T_Spisok>::InternalNode(T_Spisok * TheObject, Node<T_Spisok> * next) :
T_MyOblect(TheObject),
T_MyNext(next)
{}
 
template <class T_Spisok>
 
// функция распределения данных.
Node<T_Spisok> * InternalNode<T_Spisok>::pInsert(T_Spisok * TheObject)
{
    long result = T_MyOblect->Compare(*TheObject);
    switch (result)
    {
    case KisSame:
    case KisLarger:
    {
                      InternalNode<T_Spisok> * ObjectNode = new  InternalNode<T_Spisok>(TheObject, this);
                      return ObjectNode;
    }
    case KisSmaller:
        T_MyNext = T_MyNext->pInsert(TheObject);
        return this;
 
        
    }
    return this;
}
template <class T_Spisok>
class TailNode :public Node<T_Spisok>
{
public:
    TailNode(){}
    virtual ~TailNode(){}
    virtual Node<T_Spisok>  * pInsert(T_Spisok * TheObject);
    virtual void Display() const { }
private:
 
};
template <class T_Spisok>
Node<T_Spisok> * TailNode<T_Spisok>::pInsert(T_Spisok * TheObject)
{
    InternalNode<T_Spisok> * ObjectNode = new InternalNode<T_Spisok>(TheObject, this);
    return ObjectNode;
}
template <class T_Spisok>
    class HeadNode :public Node<T_Spisok>
{
public:
    HeadNode();
    virtual ~HeadNode(){ delete T_MyNext; }
    virtual Node<T_Spisok> * pInsert(T_Spisok * TheObject);
    virtual void Display()const { T_MyNext -> Display(); }
private:
    Node<T_Spisok> * T_MyNext;
};
    template <class T_Spisok>
    HeadNode<T_Spisok>::HeadNode()
{
        T_MyNext = new TailNode<T_Spisok>;
}
    template <class T_Spisok>
 
    Node<T_Spisok> * HeadNode<T_Spisok>::pInsert(T_Spisok * TheObject)
{
    T_MyNext = T_MyNext->pInsert(TheObject);
    return this;
 
}
    template <class T_Spisok>
class LinkedList
{
public:
    LinkedList();
    ~LinkedList(){ delete MyHead; }
    void Insert(T_Spisok * TheObject);
    void ShowAll(){ MyHead->Display(); }
private:
    HeadNode<T_Spisok> * MyHead;
};
 
template <class T_Spisok>
LinkedList<T_Spisok>::LinkedList()
{
    MyHead = new HeadNode<T_Spisok>;
}
template <class T_Spisok>
void LinkedList<T_Spisok>::Insert(T_Spisok * TheObject)
{
    MyHead->pInsert(TheObject);
}
заголовочный файл - ввод и вывод данных:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
class Data
{
public:
    
    void SpisokPersonal();
    void Readfile();
    //очистка содержимого файла
    void CleanFile()
    {
        ofstream fout(ItsDataFileName,ios::trunc);
    }
    void SetFileName(){ ItsDataFileName = "файл данных персонала: \n"; }
    
private:
    string ItsDataFileName;
};
//Ввод данных 
void Data::SpisokPersonal()
{
    Employee * pEmployee;
    long val, salary;
    //данные подключенные к шаблону связанного списка
    LinkedList<Employee> List;
    string firsName, lastName, address;
    char address2[31];
    string buffer, filename = "файл данных персонала: \n"; // инициализация переменной filename названием файла
 
    //отерытие файла с возможностью вводить данные в конце файла
    ofstream fout(filename, ios::app);
    //если файл равно нулю, то выйдет сообщение об открытии нового файла
    if (!fout)
    {
        cout << "Unable to open " << filename << " for appending. \n";
 
    }
    for (;;)
    {
 
        cout << "Введите номер персонала (0 стоп): ";
        (cin >> val).get();
        if (!val)
            break;
        cout << endl;
        cout << "Введите имя работника: ";
        cin >> firsName;
 
        cout << endl;
        cout << "Введите фамилию работника: ";
        cin >> lastName;
        cout << endl;
        cout << "Введите адресс работника: ";
        cin.ignore(30, '\n');
        cin.getline(address2, 30);
        address = address2;
        cout << endl;
        cout << "Введите зарплату работника: ";
        (cin >> salary).get();
        cout << endl;
        pEmployee = new Employee(" none", "none", "usa sexy", salary, val);
 
        pEmployee->SetFirstName(firsName);
        pEmployee->SetLastName(lastName);
        pEmployee->SetAddress(address);
        pEmployee->SetSalary(salary);
        pEmployee->SetNumberPersonal(val);
 
        ///Ввод данных в файл!
        fout << "*****************************\n";
        fout << "Номер персонала: \t" << val << endl;
        fout << "Имя: \t" << firsName << endl;
        fout << " Фамилия: \t" << lastName << endl;
        fout << " Адресс: \t" << address << endl;
        fout << " Зарплата: \t" << salary << endl;
        fout << "*****************************\n";
        fout << endl;
 
 
        //передача данных в связанный список.
        List.Insert(pEmployee);
        //инициализация файла именем
        ItsDataFileName = filename;
        
 
    }
    fout.close();
 
    system("cls");
 
    List.ShowAll();
    
}
 
//чтение файла
void Data::Readfile()
{
    
    char ch;
    ifstream fin(ItsDataFileName);
    if (fin)
    {
        cout << "curent file contents: \n";
 
        char ch;
        while (fin.get(ch))
            cout << ch;
        cout << "\n*** end of  file contents***\n";
    }
    fin.close();
    cout << "\n Opening " << ItsDataFileName << "in append mode...\n";
 
}
Ответ: вот решение. нужно Ввод данных описать внутри класса самих данных, тогда данные будут записываться во время показа на экран.

вот участок кода данных в которых был непосредственно добавлен изменеие.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
virtual void Display()const
    {   
        string filename = "файл данных персонала: \n"; // инициализация переменной filename названием файла
 
        //отерытие файла с возможностью вводить данные в конце файла
        ofstream fout(filename, ios::app);
        
        if (!fout)
        {
            cout << "Unable to open " << filename << " for appending. \n";
 
        }
        else
 
        {
 
 
            cout << "*****************************\n";
            cout << " Номер персонала: \t\a";
            cout << ItsNumberPersonal << endl;
            cout << " Имя: \t" << ItsFirstName << endl;
            cout << " Фамилия: \t" << ItsLastName << endl;
            cout << " Адресс: \t" << ItsAddress << endl;
            cout << " Зарплата: \t" << ItsSalary << endl;
            cout << "*****************************\n";
            cout << "\n";
 
            ///Ввод данных в файл!
            fout << "*****************************\n";
            fout << "Номер персонала: \t" << ItsNumberPersonal << endl;
            fout << "Имя: \t" << ItsFirstName << endl;
            fout << " Фамилия: \t" << ItsLastName << endl;
            fout << " Адресс: \t" << ItsAddress << endl;
            fout << " Зарплата: \t" << ItsSalary << endl;
            fout << "*****************************\n";
            fout << endl;
            fout.close();
        }
    }
полный код:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
//класс данных персонала
 
class Employee
{
public:
    Employee();
    
    Employee(char *, char *, char *, long, long);
    ~Employee();
    Employee(const Employee&);
    Employee & operator=(const Employee &);
    long Compare(const Employee &);
    virtual void Display()const
    {   
        string filename = "файл данных персонала: \n"; // инициализация переменной filename названием файла
 
        //отерытие файла с возможностью вводить данные в конце файла
        ofstream fout(filename, ios::app);
        
        if (!fout)
        {
            cout << "Unable to open " << filename << " for appending. \n";
 
        }
        else
 
        {
 
 
            cout << "*****************************\n";
            cout << " Номер персонала: \t\a";
            cout << ItsNumberPersonal << endl;
            cout << " Имя: \t" << ItsFirstName << endl;
            cout << " Фамилия: \t" << ItsLastName << endl;
            cout << " Адресс: \t" << ItsAddress << endl;
            cout << " Зарплата: \t" << ItsSalary << endl;
            cout << "*****************************\n";
            cout << "\n";
 
            ///Ввод данных в файл!
            fout << "*****************************\n";
            fout << "Номер персонала: \t" << ItsNumberPersonal << endl;
            fout << "Имя: \t" << ItsFirstName << endl;
            fout << " Фамилия: \t" << ItsLastName << endl;
            fout << " Адресс: \t" << ItsAddress << endl;
            fout << " Зарплата: \t" << ItsSalary << endl;
            fout << "*****************************\n";
            fout << endl;
            fout.close();
        }
    }
 
    //Функции вывода инфорамации 
    const string   & GetFirstName()const
    {
        return ItsFirstName;
    }
    const string  & GetLastName()const
    {
        return ItsLastName;
    }
    const  string & GetAddress()const
    {
        return ItsAddress;
    }
    long GetSalary()const
    {
        return ItsSalary;
    }
    long GetNumberPersonal()const
    {
         return ItsNumberPersonal;
    }
 
 
    //Функции Ввода информации.
    void  SetFirstName(const string & FName)
    {
        ItsFirstName = FName;
    }
    void SetLastName(const string & LName)
    {
        ItsLastName = LName;
    }
    void SetAddress(const string & address)
    {
        ItsAddress = address;
    }
    void SetSalary(long salary)
    {
        ItsSalary = salary;
    }
    void SetNumberPersonal(long numberpersonal)
    {
        ItsNumberPersonal = numberpersonal;
    }
private:
    string ItsFirstName;
    string ItsLastName;
    string ItsAddress;
    long ItsSalary;
    long ItsNumberPersonal;
};
 
 
 
Employee::Employee() :
ItsFirstName(" "),
ItsLastName(" "),
ItsAddress(" "),
ItsSalary(0),
ItsNumberPersonal(1)
{}
 
 
Employee::Employee(char  * firstName, char * lastName, char * address, long salary,long numberPersonal) :
ItsFirstName(firstName),
ItsLastName(lastName),
ItsAddress(address),
ItsSalary(salary),
ItsNumberPersonal(numberPersonal)
{}
 
Employee::Employee(const Employee & rhs) :
ItsFirstName(rhs.GetFirstName()),
ItsLastName(rhs.GetLastName()),
ItsAddress(rhs.GetAddress()),
ItsSalary(rhs.GetSalary()),
ItsNumberPersonal(rhs.GetNumberPersonal())
{}
Employee::~Employee(){}
Employee & Employee::operator= (const Employee & rhs)
{
    if (this == &rhs)
    {
        return *this;
    }
    ItsFirstName = rhs.GetFirstName();
    ItsLastName = rhs.GetLastName();
    ItsAddress = rhs.GetAddress();
    ItsSalary = rhs.GetSalary();
    ItsNumberPersonal = rhs.GetNumberPersonal();
 
    return *this;
}
Вопрос: Динамические структуры данных (списки, очереди, стеки, деревья)

Решил я начать писать мини FAQ по моим любимым Динамическим структурам данных.
Все программы я пишу на Turbo Pascal 7.0 версии, не проверяю их работоспособности на разновидностях компиляторов под Pascal, прошу принять это во внимание.

И начну я своё повествование со стеков.
И так, что же такое стек?
Стек (англ. stack — стопка) — структура данных с методом доступа к элементам LIFO (англ. Last In — First Out, «последним пришел — первым вышел»). Чаще всего принцип работы стека сравнивают со стопкой тарелок: чтобы взять вторую сверху, нужно взять верхнюю.
просвещаемся на википедии
По своей сути это структура, где мы не можем обратиться к элементу стоящему "ниже" вершины, если мы не "сняли" вершину. Но я решил писать программу так, как будто у нас "видно" весь стек и мы можем просматривать любой элемент в любое время (если будет не понятен этот момент, пишите в теме, я расскажу подробнее что поменяется тогда).
Я тут набросал программу, демонстрирующую работу со стеком, опишу процедуры и функции для ясности:
1) procedure AddElem(var stek1:List;znach1:TInf) - процедура добавление элемента в стек.
2) procedure Print(stek1:List) - вывод стека.
3) Procedure FreeStek(stek1:List) - освобождение памяти использованного под стек.
4) Function SearchElemZnach(stek1:List;znach1:TInf):List - поиск в стеке по значению, функция возвращает адрес найденного элемента.
5) Procedure DelElem(var stek1:List;tmp:List) - процедура удаления из стека элемента с адресом tmp.
6) procedure DelElemZnach(var Stek1:List;znach1:TInf) - удаление из стека элемента со значением znach1.
7) Procedure DelElemPos(var stek1:List;posi:integer) - удаление из стека элемента с порядковым номером posi.
8) procedure SortBublInf(nach:list) - сортировка стека "пузырьком" (самый простой вариант), с обменом данными между элементами.
9) procedure SortBublLink(nach:List)- сортировка стека "пузырьком" (самый простой вариант), с изменением лишь указателей на элементы.

Ну а вот и сам код проекта:
Код Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
Program Stek;
uses
  crt; {Для использования readkey и clrscr}
type
  Tinf=integer; {тип данных, который будет храниться в элементе стека}
  List=^TList;  {Указатель на элемент типа TList}
  TList=record {А это наименование нашего типа "запись" обычно динамические структуры описываются через запись}
    data:TInf;  {данные, хранимые в элементе}
    next:List;   {указатель на следующий элемент}
  end;
 
{Процедура добавляющая элемент в стек}
procedure AddElem(var stek1:List;znach1:TInf);
var
  tmp:List;
begin
  GetMem(tmp,sizeof(TList)); {выделяем в памяти место для нового элемента}
  tmp^.next:=stek1;  {указатель на следующий элемент "направляем" на вершину стека}
  tmp^.data:=znach1; {добавляем к элементу данные}
  stek1:=tmp; {вершина стека изменилась, надо перенести и указатели на неё}
end;
 
{Процедура вывода стека}
procedure Print(stek1:List);
begin
  if stek1=nil then {проверка на пустоту стека}
  begin
    writeln('Стек пуст.');
    exit;
  end;
  while stek1<>nil do {пока указатель stek1 не станет указывать в пустоту}
  begin   {а это произойдёт как только он перейдёт по ссылке последнего элемента}
    Write(stek1^.data, ' '); {выводить данне}
    stek1:=stek1^.next  {и переносить указатель вглубь по стеку}
  end;
end;
 
{Процедура освобождения памяти занятой стеком}
Procedure FreeStek(stek1:List);
var
  tmp:List;
begin
  while stek1<>nil do {пока stek1 не станет указывать в "пустоту" делать}
  begin
    tmp:=stek1; {указатель tmp направим на вершину стека}
    stek1:=stek1^.next; {вершину стека перенесём на следующий за данной вершиной элемент}
    FreeMem(tmp,SizeOf(Tlist)); {освободим память занятую под старую вершину}
  end;
end;
 
{Поиск элемента в стеке по значению}
Function SearchElemZnach(stek1:List;znach1:TInf):List;
begin
  if stek1<>nil then {если стек не пуст, то}
    while (Stek1<>nil) and (znach1<>stek1^.data) do {пока stek1 не укажет в "пустоту" или пока мы не нашли нужный нам элемент}
      stek1:=stek1^.next; {переносить указатель}
  SearchElemZnach:=stek1;{функция возвращает указатель на найденный элемент}
end;         {в случае если элемент не найден, она вернёт nil}
 
{Процедура удаления элемента по указателю}
Procedure DelElem(var stek1:List;tmp:List);
var
  tmpi:List;
begin
  if (stek1=nil) or (tmp=nil) then {если стек пуст или указатель никуда не указывает, то выходим}
    exit;
  if tmp=stek1 then {если мы удаляем элемент который является вершиной стека, то}
  begin
    stek1:=tmp^.next;{следует перенести вершину и}
    FreeMem(tmp,SizeOf(TList)); {высвободить память из под элемента}
  end
  else {в случае, если удаляемый элемент не вершина стека, то}
  begin
    tmpi:=stek1; {ставим указатель на вершину стека}
    while tmpi^.next<>tmp do {доходим до элемента стоящего "перед" тем, который нам следует удалить}
      tmpi:=tmpi^.next;
    tmpi^.next:=tmp^.next; {указатель элемента переносим на следующий элемент за удаляемым}
    FreeMem(tmp,sizeof(TList)); {удаляем элемент}
  end;
end;
 
{Процедура удаления элемента по значению}
procedure DelElemZnach(var Stek1:List;znach1:TInf);
var
  tmp:List;
begin
  if Stek1=nil then {Если стек пуст, то выводим сообщение и выходим}
  begin
    Writeln('Стек пуст');
    exit;
  end;
  tmp:=SearchElemZnach(stek1,znach1); {tmp указывает на удаляемый элемент}
  if tmp=nil then {если элемент не был найден, то выводим сообщение и выходим}
  begin
    writeln('Элемент с искомым значением ' ,znach1, ' отсутствует в стеке.');
    exit;
  end;
  DelElem(stek1,tmp); {удаляем элемент из стека }
  Writeln('Элемент удалён.'); {сообщаем о выполнении действия}
end;
 
{Удаление элемента по порядковому номеру (вершина имеет номер 1)}
Procedure DelElemPos(var stek1:List;posi:integer);
var
  i:integer;
  tmp:List;
begin
  if posi<1 then {проверка на ввод информации}
    exit;
  if stek1=nil then {если стек пуст}
  begin
    Write('Стек пуст');
    exit
  end;
  i:=1; {будет считать позиции}
  tmp:=stek1;
  while (tmp<>nil) and (i<>posi) do {пока tmp не укажет в "пустоту" или мы не найдём искомый элемент}
  begin
    tmp:=tmp^.next; {переходим на следующий элемент}
    inc(i)   {увеличиваем значение счётчика}
  end;
  if tmp=nil then {если элемента нет выводим соответствующие сообщения и выходим}
  begin
    Writeln('Элемента с порядковым номером ' ,posi, ' нет в стеке.');
    writeln('В стеке ' ,i-1, ' элемента(ов).');
    exit
  end;
  DelElem(stek1,tmp); {если мы не вышли, то элемент есть и его следует удалить}
  Writeln('Элемент удалён.'); {сообщаем о выполнении действия}
end;
 
{Процедура сортировки "пузырьком" с изменением только данных}
procedure SortBublInf(nach:list);
var
  tmp,rab:List;
  tmps:Tinf;
begin
  GetMem(tmp,SizeOf(Tlist)); {выделяем память для рабочего "буфера" обмена}
  rab:=nach; {рабочая ссылка, становимся на вершину стека}
  while rab<>nil do {пока мы не дойдём до конца стека делать}
  begin
    tmp:=rab^.next; {перейдём на следующий элемент}
    while tmp<>nil do {пока не конец стека делать}
    begin
      if tmp^.data<rab^.data then {проверяем следует ли менять элементы}
      begin
        tmps:=tmp^.data; {стандартная замена в 3 операции}
        tmp^.data:=rab^.data;
        rab^.data:=tmps
      end;
      tmp:=tmp^.next {переход к следующему элементу}
    end;
    rab:=rab^.next {переход к следующему элементу}
  end
end;
 
{Процедура сортировки "пузырьком" с изменением только адресов}
procedure SortBublLink(nach:List);
var
  tmp,pered,pered1,pocle,rab:List; {все рабочие ссылки}
begin
  rab:=nach; {становимся на вершину стека}
  while rab<>nil do{пока не конец стека делать}
  begin
    tmp:=rab^.next; {переходим к следующему за сортируемым элементу}
    while tmp<>nil do {пока не конец стека делать}
    begin
      if tmp^.data<rab^.data then {если следует произвести замену, то}
      begin
        pered:=nach; {становимся в вершину стека}
        pered1:=nach; {становимся в вершину стека}
        if rab<>nach then {если мы не стоим на изменяемом элементе, то}
          while pered^.next<>rab do pered:=pered^.next; {станем на элементе перед изменяемым}
        while pered1^.next<>tmp do pered1:=pered1^.next; {станем на элементе перед изменяемым, который находится за
        первым изменяемым}
        pocle:=tmp^.next; {запоминаем адрес элемента после второго изменяемого}
        if rab^.next=tmp then {если элементы "соседи", то}
        begin
          tmp^.next:=rab; {меняем ссылки, тут если не понятно рисуйте на листочке}
          rab^.next:=pocle
        end
        else {в случае если элементы не соседи, то}
        begin
          tmp^.next:=rab^.next;{меняем ссылки, тут если не понятно рисуйте на листочке}
          rab^.next:=pocle;
        end;
        if pered1<>rab then{советую просмотреть на листочке}
          pered1^.next:=rab;
        if rab<>nach then{советую просмотреть на листочке}
          pered^.next:=tmp
        else{всё советую просмотреть на листочке}
          nach:=tmp;
        pered1:=tmp;{советую просмотреть на листочке}
        tmp:=rab;{советую просмотреть на листочке}
        rab:=pered1;{советую просмотреть на листочке}
      end;
      tmp:=tmp^.next; {переходим на следующий элемент}
    end;
    rab:=rab^.next;{переходим на следующий элемент}
  end;
end;
 
var
  Stk, {переменная, которая всегда будет указывать на "вершину" стека}
  tmpl:List; {рабочая переменная}
  znach:Tinf; {данные вводимые пользователем}
  ch:char; {для работы менюшки}
begin
    Stk:=nil;
    repeat {цикл для нашего меню}
    clrscr; {очистка экрана, далее идёт вывод самого меню}
    Write('Программа для работы со ');
    Textcolor(4);
    Writeln('стеком.');
    Textcolor(7);
    Writeln('Выберите желаемое действие:');
    Writeln('1) Добавить элемент.');
    Writeln('2) Вывод стека.');
    Writeln('3) Удаление элемента по значению.');
    Writeln('4) Удаление элемента по порядковому номеру.');
    Writeln('5) Поиск элемента по значению');
    Writeln('6) Сортировка стека методом "Пузырька", меняя только данные.');
    Writeln('7) Сортировка стека с изменением адресов.');
    Writeln('8) Выход.');
    writeln;
    ch:=readkey; {ожидаем нажатия клавиши}
    case ch of {выбираем клавишу}
      '1':begin
            write('Введите значение добавляемого элемента: ');
            readln(znach); {считываем значение добавляемого нового элемент}
            AddElem(Stk,znach);
          end;
      '2':begin
            clrscr; {очистка экрана}
            Print(Stk); {вызов процедуры вывода}
            readkey; {ожидаем нажатия клавиши}
          end;
      '3':begin
            Write('Введите значение удаляемого элемента: ');
            readln(znach); {ввод значения удаляемого элемента}
            DelElemZnach(Stk,znach); {вызов процедуры удаления элемента по значению}
            readkey;{ожидаем нажатия клавиши}
          end;
      '4':begin
            Write('Введите порядковый номер удаляемого элемента: ');
            readln(znach); {ввод позиции удаляемого файла}
            DelElemPos(Stk,znach);{вызов процедуры удаления элемента по значению}
            readkey;{ожидаем нажатия клавиши}
          end;
      '5':begin
            write('Введите значение искомого элемента: ');
            readln(znach); {ввод искомого значения}
            tmpl:=SearchElemZnach(Stk,znach); {вызываем процедуру поиска элемента по значению}
            if tmpl=nil then {проверяем найден ли элемент и выводим соответствующие сообщения}
              write('Искомый элемент отсутствует в стеке')
            else
              write('Элемент ',tmpl^.data,' найден');
            readkey;{ожидаем нажатия клавиши}
          end;
      '6':begin
            if Stk=nil then {проверяем не пустой ли стек}
            begin
              Write('Стек пуст.');
              readkey{ожидаем нажатия клавиши}
            end
            else
            begin
              SortBublInf(Stk);{вызов процедуры сортировки стека с изменением данных}
              Write('Стек отсортирован.');
              readkey;{ожидаем нажатия клавиши}
            end
          end;
      '7':begin
            if Stk=nil then{проверяем не пустой ли стек}
            begin
              Write('Стек пуст.');
              readkey{ожидаем нажатия клавиши}
            end
            else
            begin
              SortBublLink(Stk);{вызов процедуры сортировки стека с изменением адресов}
              Write('Стек отсортирован.');
              readkey;{ожидаем нажатия клавиши}
            end
          end;
    end;
  until ch='8';
  FreeStek(Stk); {освобождаем память занятую стеком}
end.
В дальнейшем в этой теме будут выложены программы по работе со списками (однонаправленными, двунаправленными (дек), кольцевыми), бинарными деревьями, очередями.

Готов выслушать критику относительно кода, материла и конечно же Ваши пожелания. (Я готов в самой этой теме дать пояснения что такое стек, списки, деревья, с картинками и моими разъяснениями, готов дописывать код, под какие-нибудь интересные задачи по работе с динамическими структурами).Все Ваши просьбы высылайте мне средствами ЛС (Личных Сообщений).

З.Ы. Работа с динамическими массивами рассматриваться не будет, т.к. она идентична работе со статическими массивами, разница лишь в выделении памяти во время работы программы.
З.Ы.Ы. Могу поискать информацию о том, где используются динамические структуры, хотя опять же всё есть в инете, не хочется повторяться.

С нетерпением жду ответов.
 Комментарий модератора Mawrat
Исправил кодировки. (Например: "Џа®Ја*¬¬*" -> "Программа").
Ответ: Постановка задачи
Реализовать хранилище стеков, с операциями добавления, поиска, удаления стеков, а так же со всеми стандартными операциями внутри отдельного стека. Среда программирования Turbo Pascal 7.1.

Ход решения

1.Реализовать стек в ООП со всеми стандартными операциями: добавление элемента, взятие вершины, проверки на пустоту и заполнение, вывод содержимого стека на экран.

2.Реализовать список, в каждом узле которого содержится стек.

3.В основной программе реализовать меню, для удобства работы.

Стек

Структура данных – это множество элементов данных и связей между ними. Они разделяются на статические и динамические. Статические формируются в памяти одномоментно до начала работы со структурами и во время своего существования не меняют свои размеры и место положения в памяти. Примерами являются массивы и записи. Динамические структуры данных могут менять свои размеры и расположение, их состав может постоянно меняться в ходе работы с программой. Они в свою очередь делятся на линейные (списки, стеки, очереди) и нелинейные (деревья, графы). В линейных структурах элементы идут один за другим, в нелинейных – возможно ветвление.

Рассмотрим подробнее линейные структуры данных, а именно списки. Списки бывают односвязными, двусвязными, циклическими. В каждом элементе односвязного списка содержится указатель на следующий элемент, двусвязного – на следующий и предыдущий, в циклическом последний элемент содержит указатель на первый.
В списке в любой момент времени можно обратиться к любому его элементу. Для ряда задач произвольность доступа является недопустимой, для этого введено понятие дисциплины обработки данных (стек, очередь, дек). Дисциплина определяет к какому элементу и каким образом пользователь может обратиться в данный момент времени.

Стек (англ. stack — стопка) — структура данных с методом доступа к элементам LIFO (англ. Last In — First Out, «последним пришел — первым вышел»). Чаще всего принцип работы стека сравнивают со стопкой тарелок: чтобы взять вторую сверху, нужно взять верхнюю.

Стек – это дисциплина обработки данных, имеющая линейную структуру, доступ в которой разрешается только к последнему добавленному элементу( вершине стека). Стек работает по принципу LIFO (Last In, First Out. Последний вошёл, первый вышел ). Простым примером использования стека может послужить ситуация, когда мы просматриваем множество данных и составляем список особых данных, которые должны обрабатываться позднее. Когда первоначальное множество обработано, мы возвращаемся к этому списку и выполняем обработку, удаляя элементы, пока наш список не станет пустым. Например, рекурсивные функции, пока не обработан последний вызов, все предыдущие вызовы находятся в своеобразном стеке. Стек активно используется в архитектуре компьютера, в ней преобладает стековая адресация.

Рассмотрим основные функции обработки стека:

Push – добавление в вершину стека, в процедуру передаётся добавляемое значение.
Pop – взятие элемента из вершины стека, возвращает содержимое вершины
IsEmpty – проверка на пустоту, возвращает True или False.
IsFull – проверка на заполнение, максимальное число элементов в стеке определяет константа MaxStack, возвращает True или False.
Top – указатель на вершину стека

Рассмотрим структуру узла стека:

Код Pascal
1
2
3
4
5
6
7
8
type
    pStackEl = ^StackEl;
    data = Integer;
 
    StackEl = record
        Value:data;
        Prev:pStackEl;
    End;

Value – значение узла стека ( data = Integer; указывает, что стек числовой)
Prev – указатель на предыдущий элемент.

Для реализации хранилища стеков использован односвязный список с указателем на начало и конец. Рассмотрим узел списка:

Код Pascal
1
2
3
4
5
6
7
8
type
    pNode = ^listEl;
 
    ListEl = record
           Name:string;
           Stack:StackOfData;
           Next:pNode;
    End;
Name – имя стека
Stack – непосредственно стек, описанный как объект в модуле UStack.
Next – указатель на следующий элемент списка.

Рассмотрим функции обработки данного списка:

AddNode – добавление узла, в процедуру передаётся имя нового стека.
DelNode – удаление узла, в процедуру передаётся указатель на удаляемый узел
Find – поиск стека, возвращает указатель на узел
ChangeStack – процедура обработки отдельного стека, в процедуру передаётся указатель на узел с обрабатываемым стеком.

Процедура ChangeStack вызывает соответствующие процедуры обработки стека из модуля со стеком, посредством активного меню.

Процедура Find выводит все стеки, поиск осуществляется посредством активного меню, которое организованно следующим образом: считается количество стеков, далее с нажатием клавиш вверх и вниз, на экране передвигается стрелка, изменяется значение переменной m, которая указывает на порядковый номер стека в списке. Затем снова отсчитывается стек с порядковым номером m и возвращается указатель на него.

После добавлений и удалений стеков, которые происходит в основной программе, список изменяется.

Остальные функции обработки стеков и списка реализованы по стандартным алгоритмам.


Как работать с программой (этот пунк мы опустим)

!!!!! Программа написана в Turbo Pascal 7.1, чтобы подключить модули, нужно скопировать файлы UList.TPU и UStack.TPU в директорию компилятора BIN\.

Код программы.

Модуль «Стек»

Код Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
Unit UStack;
Interface
Const
     MaxStack = 7;
type
    pStackEl = ^StackEl;
    data = Integer;
 
    StackEl = record
        Value:data;
        Prev:pStackEl;
    End;
 
    StackOfData = object
    public
        procedure Create;
        function IsEmpty:boolean;
        function IsFull:boolean;
        procedure Push(val:data);
        function Pop:data;
        procedure Print;
    private
        Top:pStackEl;
    End;
Implementation
Var
    i : Integer;
    stack1:stackOfData;
{///////////////////////////////////////////////}
procedure StackOfData.Create;
Begin
     Top:=Nil;
End;
{///////////////////////////////////////////////}
function StackOfData.IsEmpty:boolean;
Begin
     If Top = Nil Then
        IsEmpty:=True
     Else
        IsEmpty:=False;
End;
{///////////////////////////////////////////////}
function StackOfData.IsFull:boolean;
Var
   count:Integer;
   PSE:PstackEl;
Begin
   PSE:=Top;
   count:=0;
   While PSE<>Nil Do
   Begin
        count:=count+1;
        PSE:=PSE^.Prev;
   End;
   If count>=MaxStack Then
        IsFull:=True
     Else
        IsFull:=False;
End;
{///////////////////////////////////////////////}
procedure StackOfData.Push(val:data);
Var
   NewStackEl:pStackEl;
Begin
   New(NewStackEl);
   NewStackEl^.value:=val;
   NewStackEl^.prev:=Top;
   Top:=NewStackEl;
End;
{///////////////////////////////////////////////}
function StackOfData.Pop:data;
Var
   PSE:pStackEl;
Begin
     Pop:=Top^.value;
     PSE:=Top;
     Top:=Top^.prev;
     Dispose(PSE);
End;
{////////////////////////////////////////////}
procedure StackOfData.Print;
Var
   PSE:PstackEl;
Begin
   PSE:=Top;
   While PSE<>Nil Do
   Begin
        Write(PSE^.Value,' ');
        PSE:=PSE^.Prev;
   End;
End;
{///////////////////////////////////////////////}
Begin
     
End.


Модуль «Список стеков»


Код Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
Unit UList;
Interface
Uses UStack,crt;
 
type
    pNode = ^listEl;
 
    ListEl = record
           Name:string;
           Stack:StackOfData;
           Next:pNode;
    End;
    ListOfStack = object
    public
        procedure Create;
        procedure AddNode(klox:string);
        procedure DelNode(var delEl:pNode);
        function Find:pNode;
        procedure ChangeStack(var ple:pNode);
   private
        head:pNode;
        tail:pNode;
    End;
 
Implementation
{////////////////////////////////////////////}
procedure ListOfStack.Create;
Begin
     head:=Nil;
     tail:=Nil;
End;
{////////////////////////////////////////////}
procedure ListOfStack.AddNode(klox:string);
var
    NewNode:pNode;
Begin
    If head<>Nil Then
    Begin
        New(NewNode);
        NewNode^.name:=klox;
        NewNode^.Stack.Create;
        NewNode^.next:=Nil;
        tail^.next:=NewNode;
        tail:=NewNode;
    End
    Else
    Begin
        New(head);
        head^.name:=klox;
        head^.Stack.Create;
        Head^.next:=Nil;
        tail:=head;;
    End;
End;
{////////////////////////////////////////////}
procedure ListOfStack.DelNode(var delEl:pNode);
var
    ple:pNode;
Begin
    If delEl<>Nil Then
    Begin
        If delEl=head Then
        Begin
           head:=head^.next;
           Dispose(delEl);
        End
        Else
        Begin
           ple:=head;
           While ((ple^.next<>delEl) and (ple <> Nil )) Do  ple:=ple^.next;
           If delEl=tail Then tail:=ple;
           ple^.next:=delEl^.next;
           Dispose(delEl);
        End;
    End;
End;
{////////////////////////////////////////////}
function ListOfStack.Find:pNode;
Var
    ple:pNode;
    c:char;
    count,m:Integer;
Begin
    ple:=head;
    count:=0;
    m:=0;
    writeln('->BACK');
    While ple<>Nil Do
    Begin
        writeln('  ',ple^.name);
        ple:=ple^.next;
        count:=count+1;
    End;
    writeln;
    repeat
        c := readkey;
        if ((c=#72) and (m>0)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m-1;
             GoToXY(1,m+1);
             write('->');
        End;
        if ((c=#80) and (m<count)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m+1;
             GoToXY(1,m+1);
             Write('->');
        End;
    until c=#13;
    If m = 0 Then
       Find:=Nil
    Else
    Begin
       ple:=head;
       While m>1 Do
       Begin
            ple:=ple^.next;
            m:=m-1;
       End;
       Find:=ple;
    End;
    clrscr;
End;
{////////////////////////////////////////////}
procedure ListOfStack.ChangeStack(var ple:pNode);
var
   m:Integer;
   c:char;
   val:data;
Begin
If ple<>Nil Then
Begin
m:=1;
While m<>0 Do
Begin
   clrscr;
   Writeln('->BACK');
   Writeln('  Push');
   Writeln('  Pop');
   Writeln('  Print');
   m:=0;
   repeat
        c := readkey;
        if ((c=#72) and (m>0)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m-1;
             GoToXY(1,m+1);
             write('->');
        End;
        if ((c=#80) and (m<3)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m+1;
             GoToXY(1,m+1);
             Write('->');
        End;
    until c=#13;
    clrscr;
    If m=1 Then
    Begin
         If Not ple^.Stack.IsFull Then
         Begin
              write('Please enter value: ');
              readln(Val);
              ple^.Stack.Push(val);
 
         End
         Else
         Begin
             Writeln('Stack is full!');
             readln;
         End;
    End;
    If m = 2 Then
    If Not ple^.Stack.IsEmpty Then
    Begin
       Writeln(ple^.Stack.Pop);
       readln;
    End
    Else
    Begin
       write('Stack is empty!');
       readln;
    End;
    If m = 3 Then
    Begin
         ple^.Stack.Print;
         readln;
    End;
End;
End;
End;
{////////////////////////////////////////////}
Begin
     
End.
Главное меню

Код Pascal
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
Program Multistack;
Uses UList,crt;
var
   i,m:Integer;
   c:char;
   klox:string;
   Node:pNode;
   List:ListOfStack;
Begin
   clrscr;
   List.Create;
   m:=1;
   While m<>0 Do
   Begin
   clrscr;
   Writeln('->EXIT');
   Writeln('  ADD STACK');
   Writeln('  DELETE STACK');
   Writeln('  CHANGE STACK');
   Writeln('  INFORMATION');
   m:=0;
   repeat
        c := readkey;
        if ((c=#72) and (m>0)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m-1;
             GoToXY(1,m+1);
             write('->');
        End;
        if ((c=#80) and (m<4)) Then
        Begin
             GoToXY(1,m+1);
             write('  ');
             m:=m+1;
             GoToXY(1,m+1);
             Write('->');
        End;
    until c=#13;
    clrscr;
    Case m Of
    1:
    Begin
         Writeln('Please enter name: ');
         readln(klox);
         List.AddNode(klox);
         writeln('Stack is added!');
         readln;
    End;
    2:
    Begin
 
         clrscr;
         Node:=List.Find;
         List.DelNode(Node);
    End;
    3:
    Begin
         Node:=List.Find;
         If Node<>Nil Then
         List.ChangeStack(Node);
    End;
    4:
    Begin
 
         Writeln('MultiStack');
         Writeln('Chelyabinsk State University');
         Writeln('Faculty of Mathematics');
         Writeln(‘ xxx yyy’);
         Writeln('2010');
         readln;
    End;
 
    End;
    End;
End.
Заключение

В ходе работы были закреплены навыки работы с модулями, с динамическими структурами данных в объектно ориентированном программировании. Была написана программа для работы со стеками с интуитивно понятным для пользователя интерфейсом.


Не по теме:

зы Это оригинальный текст написанный группой программистов для сдачи зачета( xDDD ),и впервые публикуется тут cyberforum.ru (28.10.10)
Если вы хотите опубликовать у себя наш пост или его фрагмент, делайте это без дополнительного разрешения при условии, что будет стоять активная ссылка на первоисточник. cyberforum.ru/

Вопрос: Не выполняется вывод данных из таблицы БД на страницу

Доброго времени суток!
Писал код для заполнения профиля пользователя (ФИО, смена пароля, специальность, год выпуска, мыло и т.д.). Проверил работоспособность скрипта для одного пользователя. Все хорошо записал в таблицу. Но через пару часов создал нового пользователя, авторизовался и также редактировал для него данные. В итоге ФИО не записывается в таблицу.
Обработчик profile.php:
Код PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
<?php session_start();
ini_set('display_errors','On');
error_reporting(E_ALL | E_STRICT);
$link = mysqli_connect("mysql.hostinger.ru", "u104639590_root", "Rad89177376317rad", "u104639590_mydb" ) or die ("Не могу подключиться к серверу");
   // mysqli_set_charset('utf8'); 
    if( isset($_SESSION['login']) && isset($_SESSION['password']) ){
$query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'
             AND `password` = '".$_SESSION['password']."';";
$res = mysqli_query($link, $query) or die(mysqli_error());
$row = mysqli_fetch_array($res, MYSQLI_NUM);
if (empty($row[0])) {
        echo "Вы не можете изменять данные, пока не авторизуетесь на сайте! Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
        header("Refresh:5;url=/index.html");
        exit;
                    }
else {
        if ($res){
            // принимаем параметры из страницы редактирования профиля
    $new_password = mysqli_real_escape_string($link, (stripslashes(trim($_POST['new_password']))));
    $old_password = mysqli_real_escape_string($link, (stripslashes(trim($_POST['old_password']))));
    $conf_password = mysqli_real_escape_string($link, (stripslashes(trim($_POST['conf_password']))));
            if (isset($new_password) && isset($old_password) && isset($conf_password)) {
                $query = "SELECT COUNT(1) FROM users WHERE password = '".$old_password."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
                if (strlen($new_password) >=6) {
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET password = '".$new_password."', old_password = '".$password."' WHERE `login` = '".$_SESSION['login']."'";
                $result = mysqli_query($link, $sql) or die(mysqli_error());}}
                //echo "<strong> ".$_SESSION['login']." </strong>, Ваш пароль успешно изменен.";}}
            else echo "Слишком короткий пароль.";
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    }
    if ($res){
            // принимаем параметры из страницы редактирования профиля
            if (isset($last_name) && isset($name) && isset($patronymic)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET last_name = '".$last_name."', name = '".$name."', patronymic = '".$patronymic."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());
                //echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
//echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
//header("Refresh:5;url=/index.html");
         
            //echo 'Вы ввели не все данные!';
        
    }
    if ($res){
            // принимаем параметры из страницы редактирования профиля
    $select = $_POST['graduation'];
    
            if (isset($select)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET graduation = '".$select."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());
                echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
//header("Refresh:5;url=/index.html");
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    }
    }
        if ($res){
            // принимаем параметры из страницы редактирования профиля
    $speciality = $_POST['speciality'];
    
            if (isset($speciality)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET speciality = '".$speciality."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());}
                //echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
//echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
//header("Refresh:5;url=/index.html");
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    if ($res){
            // принимаем параметры из страницы редактирования профиля
    $work = $_POST['work'];
    
            if (isset($work)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET work = '".$work."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());}
                //echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
//echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
//header("Refresh:5;url=/index.html");
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    if ($res){
            // принимаем параметры из страницы редактирования профиля
    $email = $_POST['email'];
    
            if (isset($email)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
                extract($row);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET user_email = '".$email."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());}
                //echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
//echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
//header("Refresh:5;url=/index.html");
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    if ($res){
            // принимаем параметры из страницы редактирования профиля
    $telephone = $_POST['telephone'];
    
            if (isset($telephone)) {
                $query = "SELECT COUNT(1) FROM `users` WHERE `login` = '".$_SESSION['login']."'";
                $res = mysqli_query($link, $query);
                $row = mysqli_fetch_array($res, MYSQLI_NUM);
    if (($new_password == $_SESSION['password']) or ($old_password !=$conf_password))
    { echo "Новый пароль совпадает со старым или старый пароль и пароль подтверждения не совпадают.";}
    else {
            $sql = "UPDATE users  SET tel = '".$telephone."' WHERE `login` = '".$_SESSION['login']."'";
            $result = mysqli_query($link, $sql) or die(mysqli_error());
                echo "<strong> ".$_SESSION['login']." </strong>, Ваши данные успешно изменены.";}
echo "Вы будете перенаправлены на <a href = 'index.html'>Главную страницу </a> через 5 секунд.";
header("Refresh:5;url=/index.html");
        }else{
            echo 'Вы ввели не все данные!';
        }
    }
    }
?>
Написал перед этим скрипт для поиска пользователей по 2 параметрам (фамилия, имя). С 1 уникальным пользователем работает, выводит все данные (ФИО, год выпуска, телефон, мыло, специальность и т.д.). Для 2 пользователей с одинаковой фамилией и именем еще не тестил.
Обработчик search_user.php:
Код PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$link = mysqli_connect("", "", "", "" ) or die ("Не могу подключиться к серверу");
$name = trim($_REQUEST['name']);
$last_name = trim($_REQUEST['last_name']);
 
$sql_select = "SELECT * FROM users WHERE name='".$name."' && last_name='".$last_name."'";
$result = mysqli_query($link,$sql_select);
$row = mysqli_fetch_assoc($result);
 
if($row)
{
    extract($row);
    printf("<p>ФИО Пользователя: <strong> ".$row['last_name'] ." ".$row['name'] ." ".$row['patronymic'] ."</strong></p> 
    <p><i>Данные пользователя</i></p><p>E-mail: ".$row['user_email']."</p><p>Специальность: ".$row['speciality']."</p><p>Год выпуска: ".$row['graduation']."</p><p>Место работы, должность: ".$row['work']."</p><p>Номер телефона: ".$row['tel']."</p>---------<br/>"
    );
}
else{echo ("Пользователя с таким именем не существует<br/><br/>");}
 
 
?>
Попробовал написать скрипт для поиска пользователей по определенной специальности, но при выборе используется datalist:
Код HTML5
1
2
3
4
5
6
7
8
9
10
11
12
            <p>
                    <label for="speciality" class="speciality" data-icon="s">Специальность *</label>
                    <input list="speciality" name="speciality" type="text" required="required" placeholder="Выберите специальность, на которую Вы обучались">
                    <datalist id="speciality" >
        <option value = "Математика и физика">Математика и физика</option>
        <option value = "Математика и информатика">Математика и информатика</option>
        <option value = "Физика">Физика</option>
        <option value = "Физика и информатика">Физика и информатика</option>
        <option value = "Прикладная математика и информатика">Прикладная математика и информатика</option>
        <option value = "МОАИС">МОАИС</option> 
                    </datalist>
                    </p> 
А сам обработчик all_users.php:
Код PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
<?php
$link = mysqli_connect("mysql.hostinger.ru", "u104639590_root", "Rad89177376317rad", "u104639590_mydb" ) or die ("Не могу подключиться к серверу");
$speciality = $_REQUEST['speciality'];
if (isset($speciality)) {
$sql_select = "SELECT * FROM users WHERE `speciality` = '".$speciality."'";
$result = mysqli_query($link,$sql_select);
$row = mysqli_fetch_assoc($result);}
else echo "Вы не выбрали специальность!";
//while ($row = mysqli_fetch_assoc($result))    
$table = "<table class=\"main-table\" align=\"center\">;
                                <tr class=\"table-head\">
                                    <td class=\"table-last_name\">Фамилия</td>
                                    <td class=\"table-name\">Имя</td>
                                    <td class=\"table-patronymic\">Отчество</td>
                                    <td class=\"table-user_email\">Е-mail</td>
                                    <td class=\"table-speciality\">Специальность</td>
                                    <td class=\"table-graduation\">Год выпуска</td>
                                    <td class=\"table-work\">Метос работы, должность</td>
                                    <td class=\"table-tel\">Номер телефона</td>
                                </tr>";
    $row_counter = 1;
//while($row = mysqli_fetch_array($result,MYSQLI_NUM));
while ($row = mysqli_fetch_assoc($result))  {
     if(is_int($row_counter/2)) {
                    $row_color = 'cyan';
                } else {
                    $row_color = 'white';
                }
                  $table .= "<tr class=\"$row_color-color\">";
                  $table .= "<td >".$row['last_name']."</td>";
                  $table .= "<td >".$row['name']."</td>";
                  $table .= "<td >".$row['patronymic']."</td>";
                  $table .= "<td >".$row['user_email']."</td>";
                  $table .= "<td >".$row['speciality']."</td>";
                  $table .= "<td >".$row['graduation']."</td>";
                  $table .= "<td >".$row['work']."</td>";
                  $table .= "<td >".$row['tel']."</td>";
                  $table .= "</tr>";
                  $row_counter++;
}
    $table .= "</table>";
    echo $table;
//while($row = mysqli_fetch_array($result,MYSQLI_NUM));
?>
В итоге, у меня не выводится ни 1 строка в таблице. До этого использовал цикл do-while, там выводилась информация, если кол-во пользователей по данной специальности =1, если 2 и больше, то почему-то ФИО вообще не пишутся в таблицу.
Подскажите, в чем мои косяки? Где, что исправить?
Кстати, если возникнет необходимость проверить сей код на деле, то вот сайт, для которого он написан:

Добавлено через 5 часов 50 минут
Исправил. как это часто бывает, невнимательность меня подвела.
Код PHP
1
2
3
    $last_name = $_POST['last_name'];
    $name = $_POST['name'];
    $patronymic = $_POST['patronymic'];
Теперь поиск по специальности работает, но не работает правильный вывод при совпадении фамилий и имен, если выбрать поиск конкретного пользователя.

Добавлено через 18 секунд
Может кто подсказать?
Ответ:
Код PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?php
$link = mysqli_connect("mysql.hostinger.ru", "u104639590_root", "Rad89177376317rad", "u104639590_mydb" ) or die ("Не могу подключиться к серверу");
$name = trim($_REQUEST['name']);
$last_name = trim($_REQUEST['last_name']);
if (isset($name) && isset ($last_name)) {
$sql_select = "SELECT * FROM users WHERE name='".$name."' && last_name='".$last_name."'";
$result = mysqli_query($link,$sql_select);
$row = mysqli_fetch_assoc($result);}
else echo "Вы не ввели данные для поиска.";
if (!empty($row)) {
    $table = "<table class=\"main-table\" align=\"center\">;
                                <tr class=\"table-head\">
                                    <td class=\"table-last_name\">Фамилия</td>
                                    <td class=\"table-name\">Имя</td>
                                    <td class=\"table-patronymic\">Отчество</td>
                                    <td class=\"table-user_email\">Е-mail</td>
                                    <td class=\"table-speciality\">Специальность</td>
                                    <td class=\"table-graduation\">Год выпуска</td>
                                    <td class=\"table-work\">Метос работы, должность</td>
                                    <td class=\"table-tel\">Номер телефона</td>
                                </tr>";
    $row_counter = 1;
//while($row = mysqli_fetch_array($result,MYSQLI_NUM));
while ($row = mysqli_fetch_assoc($result))  {
     if(is_int($row_counter/2)) {
                    $row_color = 'cyan';
                } else {
                    $row_color = 'white';
                }
                  $table .= "<tr class=\"$row_color-color\">";
                  $table .= "<td >".$row['last_name']."</td>";
                  $table .= "<td >".$row['name']."</td>";
                  $table .= "<td >".$row['patronymic']."</td>";
                  $table .= "<td >".$row['user_email']."</td>";
                  $table .= "<td >".$row['speciality']."</td>";
                  $table .= "<td >".$row['graduation']."</td>";
                  $table .= "<td >".$row['work']."</td>";
                  $table .= "<td >".$row['tel']."</td>";
                  $table .= "</tr>";
                  $row_counter++;
}
    $table .= "</table>";
    echo $table;
}
    
else echo ("Пользователя <strong>".$name." ".$last_name."</strong> не существует<br/><br/>");
?>
Почему в табилце не выводит данные пользователей? В другом скрипте все хорошо работает, где поиск идет по специальности.

Добавлено через 2 часа 52 минуты
И с этим разобрался. Но протестировал: создал 2 пользователей с фамилией Иванов и именем Иван. При поиске Иванова Ивана выводится в таблицу только 1 из них. Как сделать чтобы выводились все пользователи удовлетворяющие запросу поиска? Тему хоть кто-то читает?
Вопрос: Разрядность данных и смещение - что это?

Используется 32 разрядные данные, 16 разрядные данные.
Хочу для себя прояснить, под этим подразумевается использование кол-ва разрядов регистров для записи\чтения данных и разрядность сегментов ?
Т.е.
а) если необходимо использовать 32 разрядные данные, в ход идут регистры : EAX,EBX и так далее.
б) если необходимо использовать 16 разрядные данные, в ход идут регистры ax,bx и т.д.
в) если необходимо использовать данные 32 и 16 разрядности, в ход идут регистры eax,ebx+ смещение(если данные 16тиразрядные)

Трактовать следующее: "Разрядность данных и адресов: 16- разрядные данные и смещения в сегменте, 32 -разрядные данные и смещения не используются" следует как пункт В) ?

Подскажите, правильно ли я реализовал условия?
Условие 1:
Разрядность данных и адресов: 16- разрядные данные и смещения в сегменте
and [sp + dx + 10] , ax
подчеркнутый операнд- смещение, регистры 16 разрядные, результат суммы содержимого регистров записываем по адресу со смещением [sp + dx + 10].

Условие 2:
Разрядность данных и адресов: 32 -разрядные данные и смещения не используются
and edx , eax
смещение не используется, 32 разрядные регистры задействованы, результат суммы содержимого двух регистров записываем в edx.

Написать вот так при условии 2 будент неправильно:
and [esp + edx + 10] , eax

Буду рад любой критике и правкам
Ответ:
Сообщение от i7otep9wka
смещением [sp + dx + 10].
В х86 такое индексирование не допустимо, возможно использование BX, SP, BP вместе с числом и/или регистрами SI , DI, другие регистры не допустимы.
ps: SP меняется часто, по этому обычно SP вешают на BP.
Но нужно помнить, что BX по умолчанию работает с DS, a SP, BP c SS. Другими словами SP нельзя использовать, только если Вы не хотите запутать код.
pps: Использование ВР в сегменте данных возможно с префиксом DS:[BP+xx].
Удачи!

Добавлено через 9 минут
Сообщение от i7otep9wka
[esp + edx + 10]
В процессорах х386+ все регистры общего назначения являются индексными, т.е. такая запись допустима.