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

Здравствуйте есть задача на работу файлами, массивами
Суть задачи такова
Есть 5 строк примерно которые я записываю в memo
Теперь из memo нам нужно записать все 5 строк в массив
А уже из массива все это записать в файл *.txt
Как мне все это реализовать
Всем заранее спасибо....
Ответ: Про кириллицу в исходном тексте задания ни слова не было... Но именно по этой причине я навсегда отказался от сишных методов работы с текстовыми файлами: то что работало со времен DOS - с юникодом работать перестало...
Вопрос: Функция поиска файлов, и вывод списка найденных (использую FindFirstFile, FindNextFile)

Друзья, возникла следующая сложность, написал функцию для поиска файлов(.txt) в текущей директории, название файлов нейзвестно, поэтому, с помощью FindFirstFile, я находил файл, запихивал его имя в std::string затем функция возвращала указатель на эту строку, указатель благополучно запихивался в ifstream, и файл открывался..., всё было чудесно и прекрасно пока я не решил модернезировать эту функцию(ибо файлов то может быть найдено несколько, а работать надо с определённым), эту проблему я решил осилить очевидным мне на тот момент способом - создать массив string'ов затем под конец функции вывести их на экран, и с помощью консоли выбрать нужный номер строки с названием cin >> 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
40
41
42
/*ФУНКЦИЯ составляет список файлов с ИД*/
string* findFiles(){
    int i;// счётчик для циклов
    int j = 0;
    string** strList = new string*; //выделяем память под массив указателей на string
    WIN32_FIND_DATA FindFileData;
 
    /* ИЩЕМ ПЕРВЫЙ ФАЙЛ.*/
    HANDLE oneFileName = FindFirstFile("*.txt", &FindFileData); //ищем .txt'эшные файлы
    if (oneFileName == INVALID_HANDLE_VALUE){
        printf("FindFirstFile failed (%u)\n", GetLastError()); //выводим если не нашли ничего
    }
    else{ /*..............Иначе записываем в strList.*/
        for (i = 0; FindFileData.cFileName[i] != '\0'; i++)
            strList[j] = new string; // выделяем память
            strList[j++]->push_back(FindFileData.cFileName[i]);/*Записываем что нашли...собственно
                                                               как выяснится позже, ничерта не записывается,
                                                               как мне кажется проблема в LPCWSTR(тип, возвращаемый
                                                               FindFileData.cFileName[i]), мало того, мне пршлось
                                                               в настройках проекта поменять кодировку с юникода на 
                                                               мультибитную чтобы LPCWSTR воспринимался "в серьёз"*/
    }
    /* ИЩЕМ СЛЕДУЮЩИЕ ФАЙЛЫ.*/
    do {
        if (FindNextFile(oneFileName, &FindFileData)){
            /*..............Иначе записываем в strList.*/
            for (i = 0; FindFileData.cFileName[i] != '\0'; i++)
                strList[j] = new string; // выделяем память
                strList[j++]->push_back(FindFileData.cFileName[i]);/*Записываем что нашли... ну понятно, тут таже проблема,
                                                                   читайте выше*/
        }
    } while (GetLastError() != ERROR_NO_MORE_FILES); // делать пока не обнаружит ни одного файла
    FindClose(oneFileName);
    /* Смотрим что нашли*/
    for (i = 0; i < j; i++){
        printf("%d) %s\n", i, strList[i]->c_str()); /* тут выводится только нумерация и пустота(VS2008) 
                                                    или нумерация и кракозябры(англ. буквы)(VS2013)*/
    }
    /*Выбираем нужный для работы файл*/
    cin >> i;
    return strList[i]; /*Возвращаем нужный указатель*/
}
Самое смешное, пока писал на VS2013 проблема была только в том что в strList ничего не заносилось(я расценил вывод кракозябр именно так), затем, волей судьбы я пересел за другой компьютер (там VS2008) и появилась еще гора проблем в виде
cannot convert parameter 1 from 'std::string *' to 'const char *' (мне начало казаться VS2013 слишком много на себя берёт)
однако с этими неприятными моментами я, как выможете убедиться, справился, но проблему отсутствия записи LPCWSTR в массив стрингов у меня осилить вот уже несколько часов не получается.
Друзья помогите советом, может я тупо в синтаксисе ошибся, или проблема глобальнее, или может я вообще творю не понятно что, и есть более легкие инструменты реализации того что я задумал..., короче говоря... не сдерживайте себя!!! научите меня уму разуму.
Вот еще кусок кода из мэйна - вход в функцию и выход с открытием файла.
Код C++
1
2
3
ifstream openedFile(findFiles()->c_str()); // открываем файл
    if (!openedFile.is_open()) // проверка наличия файла
        cout << "File hasn't found!" << endl;
Ответ: Какая функция? Поиск файлов? В стандартных библиотеках нет. Есть что-то подобное в boost.
Ну можно и с TCHAR, если ты знаешь как им пользоваться. Не знаю, в чём это проще, тогда и для string/wstring должно быть общее имя.
Вопрос: Исключение при парсинге файлов

Есть программа

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
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
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Data;
using System.Collections;
using System.Text.RegularExpressions;
using System.Threading;
using System.Text;
using System.Collections.Concurrent;
using System.Threading.Tasks;
 
namespace LabWork2
{
public class Line
{
    public string User;
    public string Address;
    public int Traffic;
    public DateTime Date;
 
    public string ToCsv(bool header = false)
    {
        var s = ", ";
        return header
        ? String.Concat("User", s, "Address", s, "Traffic", s, "Date")
        : String.Concat(
            this.User, s, 
            this.Address, s, 
            this.Traffic, s, 
            this.Date.ToString("d.MM"));
    }
 
 
    public static IEnumerable<Line> Parse(string logDir, string pattern = "log?.txt", int skip = 0)
    {
        string result = Path.GetFileName(pattern);
        foreach (var file in Directory.EnumerateFiles(logDir, result))
        {
            //foreach (var file in Directory.GetFiles(logDir,result))
            //  while()
            while (File.Exists(pattern))
            {
                foreach (var line in ParseFile(logDir, file, 1))
                    yield return line;
            }
        }
    }
 
   public static IEnumerable<Line> ParseFile(string logDir,string file, int skip = 0)
   {
       return Parse(logDir,file, skip);
    }
}
 
   
class Stat 
{
    public class Item
    {
        public string Key;
        public string Address;
        public int Traffic;
        public DateTime From;
        public DateTime To;
 
        public string ToCsv(bool header=false)
        {
            var s = ", ";
            return header 
            ? String.Concat("Key", s, "Traffic", s, "From", s, "To")
            : String.Concat(
                this.Key, s,
                this.Traffic, s,
                this.From.ToString("d.MM"), s,
                this.To.ToString("d.MM"));
        }
 
        public string ToCsv1(bool header = false)
        {
            var s = ", ";
            return header
            ? String.Concat("Adress", s, "Traffic", s)
            : String.Concat(
                this.Address, s,
                this.Traffic, s);
        }
 
        public string ToCsv2(bool header = false)
        {
            var s = ", ";
            return header
            ? String.Concat( "Traffic", s, "From", s, "To")
            : String.Concat(               
                this.Traffic, s,
                this.From.ToString("d.MM"), s,
                this.To.ToString("d.MM"));
        }
 
    }
 
    Dictionary<string, Item> tbl = new Dictionary<string, Item>();
 
    public void Add(string key, Line line) 
    {
        Item itm;
        if (tbl.TryGetValue(key, out itm) == false)
        {
            itm = new Item { Key = key, From = line.Date, To = line.Date };
            tbl.Add(key, itm);
        }
        itm.From = new DateTime(Math.Min(itm.From.Ticks, line.Date.Ticks));
        itm.To = new DateTime(Math.Max(itm.To.Ticks, line.Date.Ticks));
        itm.Traffic += line.Traffic;
    }
 
    public IEnumerable<Item> Items { get { return tbl.Values; } }
}
    class Program
    {
        static Queue<String> m_workFiles = new Queue<String>();//файлы на обработку
        static System.Collections.Generic.List<Stat> m_threadResult; //результат выполнения потока
        static bool m_iscomplete = false;//флаг завершения ввода
        static readonly object m_locker = new object();//мьютекс для регулирования доступа к очереди файлов на обработку
 
        public void processDirectory(String logDir)//извлечь все файлы очередь для обработки
        {
            if (!Directory.Exists(logDir))
            {
                return;
            }
 
            lock (m_locker)//захватить мьютекс
            {
                foreach (var x in Directory.EnumerateFiles(logDir))
                {
                    m_workFiles.Enqueue(x);
                }
            }
            m_iscomplete = true;//установить флаг завершения
        }
 
 
        static void Main(string[] args)
        {
            var cq = new ConcurrentQueue<Stat>();
            var logDir = @"D:\logfiles";
            Program pr = new Program();
            pr.processDirectory(logDir);
            var userstat = new Stat();     
            Line ln = new Line();
            Stat st = new Stat();
             foreach (var line in Line.ParseFile(logDir,"log*.txt", 1))
             userstat.Add(line.User, line);
             //Console.WriteLine(ln.ToCsv(true));
 
 
            // параллельно ...
            Directory.EnumerateFiles(logDir, "log*.txt").AsParallel().ForAll(file =>
            {
                Console.WriteLine("@" + Environment.CurrentManagedThreadId + "\t" + file);
                //var userstat = new Stat();
                // собрать статистику из файла
                foreach (var line in Line.ParseFile(logDir,file, 1))
                    userstat.Add(line.User, line);
                // сохранить статистику для дальнейшего агрегирования
                cq.Enqueue(userstat);
            });
            Console.WriteLine(cq.Count);    
            foreach (var si in userstat.Items) Console.WriteLine(si.ToCsv());                            
            Console.WriteLine("Запись файлов-отчётов");
            File.WriteAllLines(logDir + "userstat.txt",userstat.Items.Select(si => si.ToCsv()));
            File.WriteAllLines(logDir + "adrestat.txt",userstat.Items.Select(si => si.ToCsv1()));
            File.WriteAllLines(logDir + "datastat.txt",userstat.Items.Select(si => si.ToCsv2()));
            Console.WriteLine("Файлы записаны");
        }
    }
}
Вроде прописал цикл что пока не закончатся файлы,продолжать работу(файлы прикреплены ниже)
Он открыл 2 файла,а остальные 2 он не открыл и выкинул исключение.

Мне нужно принять свои файлы и распарсить их,что я делаю не так уже при изъятии пути к каталогу.
Я создал отдельную тему так как вопрос другой уже.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
public static IEnumerable<Line> Parse(string logDir, string pattern = "log?.txt", int skip = 0)
    {
        string result = Path.GetFileName(pattern);
        foreach (var file in Directory.EnumerateFiles(logDir, result))----Исключение StackOverFlow
        {
            //foreach (var file in Directory.GetFiles(logDir,result))
            //  while()
            while (File.Exists(pattern))
            {
                foreach (var line in ParseFile(logDir, file, 1))
                    yield return line;
            }
        }
    }
 
   public static IEnumerable<Line> ParseFile(string logDir,string file, int skip = 0)
   {
       return Parse(logDir,file, skip);
    }
}
Ответ: UPD!!!
Исключений нету

Но на этом моменте кода программа останавливается и не идёт дальше.

Просто стоит.Я по шагово прошёлся отладчиком и тоже самое(выдаёт 2 адреса файлов из 4-рёх и стоит и не работает дальше)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
string logDir = @"D:\logfiles"; ;
            var userstat = new Stat();
            var cq = new ConcurrentQueue<Stat>();
            // параллельно ...
            Directory.EnumerateFiles(logDir, "log*.txt").AsParallel().ForAll(file =>
            {
                Console.WriteLine("@" + Environment.CurrentManagedThreadId + "\t" + file);               
                // собрать статистику из файла
                foreach (var line in Line.ParseFiles(logDir,file, 1))
                    userstat.Add(line.User, line);
                // сохранить статистику для дальнейшего агрегирования
                cq.Enqueue(userstat);
            });
Вопрос: Лабораторная работа. Файлы

Добрый вечер форумчани!

Помогите пожалуйста решить несколько задачек на тему "Файлы" для примера на будущее:

1) Дан файл, содержащий текст, записанный строчными буквами. Получить в другом файле тот же текст, записанный заглавными
буквами.

2) Дан файл, содержащий текст. Переписать в другой файл только слова, начинающиеся и заканчивающиеся гласной.

3) Создать структуру из двух строковых полей. Записать в файл n компонент типа этой структуры. В другой файл записать строки, полученные соединением полей каждой из структур, записанных в предыдущий файл.

4) Создать структуру из двух полей: вещественное и символьное. Записать в файл n компонент типа этой структуры. Переписать
в другой файл первые К компонент из записанных в предыдущий файл.
Ответ:
Сообщение от David Sylva
int size = strlen(buffer);
в этой строчке компилятор ругается :с
Вопрос: Работа файлами, ошибка при наличии повреждённых папок

Хочу получить список файлов по определённому пути.
Использую
C#
1
var files = Directory.GetFiles(@tbPathFrom.Text, "*.*", SearchOption.AllDirectories).Where(str => str.EndsWith(".mp3") || str.EndsWith(".wma") || str.EndsWith(".aac") || str.EndsWith(".wav") || str.EndsWith(".pcm") || str.EndsWith(".flac"));
Получаю ошибку: "Файл или папка повреждены. Чтение невозможно.". И правда, обнаружил, что среди папок существуют повреждённые. Я новичок в этом деле, подскажите пожалуйста, как бы получить список файлов с обязательным заходом в подпапки, Directory.GetFiles я так понял не справляется с задачей при наличии повреждённых папок. Не предлагайте взять и выкинуть испорченные папки - прога должна выявить наименование таких папок и отобразить их список юзеру в случае наличия проблемных папок
Ответ: SearchOption.AllDirectories лучше не использовать, ибо могут быть папке без доступа и тп , а исключение остановит весь поиск.
Осуществляйте поиск с использованием рекурсии (на форуме неоднократно были подобные темы) и обрабатывайте исключения в try/catch сообщая нужную инфу юзеру
Вопрос: Не могу проверить работу файла

Я работаю в MoonDevelop (Xamarin Studio) . При вписывании в код
C#
1
SendKeys.Send("{ENTER}");
программа перестаёт работать , я понимаю что так и должно быть , можно ли обойти это ?
Если нет то киньте ссылку на инструкцию по созданию exe файлов на C# .
То есть я создал файл в Xamarin но я не могу запустить его без него .
Как сделать так что бы я мог создать C# файл ну к примеру , в блокноте.
Ответ: Спс
Вопрос: Переписать в другой файл количество слов второй строки, содержащих буквосочетание "но"

Имеется текстовый файл, переписать в другой файл:
1. Количество слов 2 строки, содержащих буквосочетание "но"
2. Самую длинную строку файла
3. Последние 4 символов 1 строки

Работа в Паскале. Если сможете помочь, старайтесь не использовать сложные имена, процедур, а только тех, что может знать 10-тиклассник. ( for, if, while) (имена, которые связаны с работами файлов не касаются (assign, reset)
Ответ: 2.
Вопрос: Как делать полный исполняемый .exe файл в Borland C++ Builder 2006?

Ребята, всем привет! Очень важный вопрос!
Как делать полный исполняемый .exe файл в C++ Builder?
Проблема: делаю курсовой в Builder и подключаю бд (таблицы) из MS Accses, компонент ADOConnection запрашивает ПУТЬ к базе данных, но ладно, все подключено и все работает. Теперь мы переносим проект на другой ПК (к примеру делали на диске D, а с флешки запустилось по адресу F) то пишет, что не может найти путь к БД..
Был вариант сделать .exe файл. Пересмотрел много статей и все говорят: «Project Options for ProjectName.exe», Build with runtime packages,Use dynamic RTL.
Мне это ни минуты не помогло.
Подскажите как быть, очень вас прошу!
Ответ:
Сообщение от kotik95
Был вариант сделать .exe файл
Так, для справки, чтобы Вы знали... При любом запуске проекта на выполнение из среды (нажатие зеленого треугольника) C++Builder делает exe-файл!
kotik95, в событии OnCreate() той формы, на которой у Вас лежит ADOConnection, напишите следующее:
C++
1
2
3
4
ADOConnection1->Connected = false;
ADOConnection1->ConnectionString = String().sprintf("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=%sDatabase1.mdb;Persist Security Info=False", ExtractFilePath(ParamStr(0)));
ADOConnection1->LoginPrompt = false;
ADOConnection1->Connected = true;
1. Во второй строке приведенного кода исправьте имя Database1.mdb на имя своего файла БД, обязательно с расширением.
2. При работе файл БД должен находится рядом с ехе-файлов Вашего приложения.
Вопрос: Постоянная работа с xml-файлом настроек программы и возникающие ошибки

Всем привет. У меня в моей программе реализовано хранение настроек в xml-файле. Я сделал специальную библиотеку отдельно в которой всего-то один класс. Вот весь код:
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
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
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Linq;
 
namespace mpSettings
{
    public class MpSettings
    {
        /// <summary>
        /// Файл настроек в виде XElement
        /// </summary>
        public static XElement XmlMpSettingsFile;
        /// <summary>
        /// Полное имя файла настроек (включая путь)
        /// </summary>
        public static string FullFileName;
        // Разделы (зоны) в файле
        private static readonly List<string> Zones = new List<string> { "User", "Config", "Settings" };
 
        /// <summary>
        /// Элементы (узлы), содержащиеся в файле настроек (for Settings)
        /// </summary>
        public enum Elements
        {
            MainSet = 1, // Основные настройки
        }
        /// <summary>
        /// Получение списка имен атрибутов в зависимости от элемента (узла)
        /// </summary>
        /// <param name="element">Элемент (узел)</param>
        /// <returns>Список имен атрибутов для указанного элемента (узла)</returns>
        private static List<string> BaseAttrNames(Elements element)
        {
            switch (element)
            {
                case Elements.MainSet:
                    return new List<string>
                {
                        "Theme", "AccentColor","ConfigTheme", "ConfigAccentColor","BordersType", "Ribbon", "FloatMenu",
                        "ChkDrwsOnMnu", "Separator",
                        "FloatMenuCollapseTo", "DrawingsAlone", "DrawingsCollapseTo"
                };
 
                default: return null;
            }
        }
        /// <summary>
        /// Получение списка значений атрибутов в зависимости от элемента (узла)
        /// </summary>
        /// <param name="element">Элемент (узел)</param>
        /// <returns>Список значений атрибутов для указанного элемента (узла)</returns>
        private static List<string> BaseAttrValues(Elements element)
        {
            switch (element)
            {
                case Elements.MainSet:
                    return new List<string>
                {
                        "BaseLight", "Blue","BaseLight", "Blue","Shadow", "True", "True",
                        "False", "0",
                        "0", "False", "0"
                };
 
                default: return null;
            }
        }
        /// <summary>
        /// Проверка файла настроек на наличие вхождений
        /// При отсутствии требуемых вхождений создает их
        /// </summary>
        private static void CheckFilesForEntries()
        {
            const string zone = "Settings";
            // Только для раздела Settings!!!!!
            foreach (Elements element in Enum.GetValues(typeof(Elements)))
            {
                var attNames = BaseAttrNames(element);
                var attValues = BaseAttrValues(element);
                if (attNames != null & attValues != null)
                {
                    for (var i = 0; i < attNames.Count; i++)
                        if (string.IsNullOrEmpty(GetValue(zone, Enum.GetName(typeof(Elements), element), attNames[i])))
                            SetValue(zone, Enum.GetName(typeof(Elements), element), attNames[i], attValues[i], true);
                }
            }
            //SaveFile();
        }
        /// <summary>
        /// Загрузка файла настроек, установка полного имени, проверка его наличия и проверка узлов
        /// </summary>
        /// <param name="file">Файл конфигурации</param>
        public static void LoadFile(string file)
        {
            try
            {
                // Полное имя (включая путь)
                FullFileName = file; //Path.Combine(directory, FileName);
                // Если файл существует, то грузим его. Иначе - создаем новый
                XmlMpSettingsFile = File.Exists(FullFileName) ? XElement.Load(FullFileName) : new XElement("ModPlus");
                // Добавляем разделы
                foreach (var zone in Zones)
                {
                    if (XmlMpSettingsFile.Element(zone) == null)
                        XmlMpSettingsFile.SetElementValue(zone, string.Empty);
                }
                SaveFile();
                // Проверяем вхождения
                CheckFilesForEntries();
            }
            catch (Exception)
            {
                // ignored
            }
        }
        /// <summary>
        /// Перезагрузка файла настроек
        /// </summary>
        private static void ReloadSettingsFile()
        {
            XmlMpSettingsFile = XElement.Load(FullFileName);
        }
        /// <summary>
        /// Сохранение файла настроек
        /// </summary>
        public static void SaveFile()
        {
            // Сохраняем
            XmlMpSettingsFile.Save(FullFileName);
            // Перезагружаем
            ReloadSettingsFile();
        }
        /// <summary>
        /// Получение значения из файла настроек для указанного элемента (узла)
        /// </summary>
        /// <param name="zone">Группа</param>
        /// <param name="element">Имя элемента (узла)</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <returns>Значение атрибута. Если узла или атрибута не существует, то возвращает пустую строку</returns>
        public static string GetValue(string zone, string element, string attrName)
        {
            try
            {
                // Перезагружаем, т.к. могли исправить вручную или еще как-то
                ReloadSettingsFile();
                var xElement = XmlMpSettingsFile.Element(zone)?.Element(element);
                var attribute = xElement?.Attribute(attrName);
                if (attribute != null) return attribute.Value;
            }
            catch (Exception)
            {
                return string.Empty;
            }
            return string.Empty;
        }
        /// <summary>
        /// Получение значения из файла настроек для указанного элемента (узла)
        /// </summary>
        /// <param name="zone">Группа</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <returns>Значение атрибута. Если узла или атрибута не существует, то возвращает пустую строку</returns>
        public static string GetValue(string zone, string attrName)
        {
            try
            {
                // Перезагружаем, т.к. могли исправить вручную или еще как-то
                ReloadSettingsFile();
                var xElement = XmlMpSettingsFile.Element(zone);
                var attribute = xElement?.Attribute(attrName);
                if (attribute != null) return attribute.Value;
            }
            catch (Exception)
            {
                return string.Empty;
            }
            return string.Empty;
        }
        /// <summary>
        /// Сохранение значения в файл настроек
        /// </summary>
        /// <param name="zone">Группа</param>
        /// <param name="element">Элемент (узел)</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <param name="value">Значение</param>
        /// <param name="saveFile">Сохранять или нет файл. Это для тех случаев, когда много данных сохраняется подряд - 
        /// дабы не загружать систему вызываем сохранение затем отдельно</param>
        public static void SetValue(string zone, string element, string attrName, string value, bool saveFile)
        {
            /* Создание/заполнение узла
             * Так как узла может не быть, то его надо создать
             * Если узел уже есть, то в него просто добавится пустое значение */
            var xel = XmlMpSettingsFile.Element(zone);
            if (xel == null)
                XmlMpSettingsFile.SetElementValue(zone, string.Empty);
            xel?.SetElementValue(element, string.Empty);
            // Установка значения атрибута
            var xElement = XmlMpSettingsFile.Element(zone)?.Element(element);
            xElement?.SetAttributeValue(attrName, value);
            // Сохранение файла
            if (saveFile)
                SaveFile();
        }
        /// <summary>
        /// Сохранение значения в файл настроек
        /// </summary>
        /// <param name="zone">Группа</param>
        /// <param name="attrName">Имя атрибута</param>
        /// <param name="value">Значение</param>
        /// <param name="saveFile">Сохранять или нет файл. Это для тех случаев, когда много данных сохраняется подряд - 
        /// дабы не загружать систему вызываем сохранение затем отдельно</param>
        public static void SetValue(string zone, string attrName, string value, bool saveFile)
        {
            /* Создание/заполнение узла
             * Так как узла может не быть, то его надо создать
             * Если узел уже есть, то в него просто добавится пустое значение */
            var xel = XmlMpSettingsFile.Element(zone);
            if (xel == null)
                XmlMpSettingsFile.SetElementValue(zone, string.Empty);
            // Установка значения атрибута
            var xElement = XmlMpSettingsFile.Element(zone);
            xElement?.SetAttributeValue(attrName, value);
            // Сохранение файла
            if (saveFile)
                SaveFile();
        }
        /// <summary>
        /// Добавление атрибута в корневой элемент файла
        /// </summary>
        /// <param name="atrName">Имя атрибута</param>
        /// <param name="atrValue">Значение атрибута</param>
        public static void SetMainAttribute(string atrName, string atrValue)
        {
            XmlMpSettingsFile.SetAttributeValue(atrName, atrValue);
            SaveFile();
        }
        /// <summary>
        /// Получение значение атрибута из корневого элемента файла
        /// </summary>
        /// <param name="atrName">Имя атрибута</param>
        /// <returns>Значение атрибута</returns>
        public static string GetMainAttribute(string atrName)
        {
            var attribute = XmlMpSettingsFile.Attribute(atrName);
            return attribute?.Value ?? string.Empty;
        }
 
        public static bool ValidateXml(string file)
        {
            var s = new XmlReaderSettings { CloseInput = true };
            var reader = XmlReader.Create(file, s);
            using (reader)
            {
 
 
                var mSuccess = true;
                try
                {
                    while (reader.Read())
                    {
                    }
 
                    //'Close the reader.
                    reader.Close();
                }
                catch
                {
                    reader.Close();
                    mSuccess = false;
                }
                //'The validationeventhandler is the only thing that would set m_Success to false
                return mSuccess;
            }
        }
    }
}
При инициализации библиотеки вызывается метод LoadFile, который загружает файл настроек в переменную, а также XmlMpSettingsFile и записывает имя файла (полный путь) в переменную FullFileName.
Далее, при работе моей программы происходит неоднократное использование методов GetValue и SetValue. При этом происходит сохранение файла (вызов метода SaveFile) и "перезагрузка" файла в переменную XmlMpSettingsFile.
Библиотеку делал "на заре" написания программы и сейчас уже не могу ее заменить. Просто моя программа "плагинная" и все подключаемые модули используют эту библиотеку. Все методы должны остаться и единственное, что я могу править, так это работу методов.

Так вот, к сути - иногда при работе основной программы (при работе плагинов вроде не замечалось) происходит "порча" xml-файла настроек, что приводит к ошибкам типа "", шестнадцатеричное значение 0х03, является недопустимым знаком. или Присутствует незавершенная строковая константа., строка 3, позиция 41. Т.е. в файле появляются незакрытые скобки и что-то там еще подобное.
Есть ли возможности предусмотреть такие проблемы?
Ответ:
Сообщение от insite2012
Ятд, обработать ошибку и в обработчике пересоздать файл настроек со стандартными (по умолчанию) значениями
Ошибка ловится при попытке чтения уже попорченного файла. Хотелось бы как-то предусмотреть решение проблемы на стадии его сохранения. Хотя, видимо это невозможно, т.к. даже понять где и когда (и почему???) происходит порча, просто невозможно
Я уже начинал издалека - при работе программы создаю копию файла настроек. В принципе, можно пробовать загрузить его, в случае ошибки, НО! Я хочу все это предусмотреть именно в этой библиотеке, чтобы похожие проблемы решить при работе различных частей программы (плагинов).
Значит остается решить - где и когда делать бэкап файла. Если в методе SaveFile, то значит нужно предусмотреть проверку файла на целосостность, прежде чем его бэкапить. В принципе, тем же try{} catch{} с попыткой чтения в вспомогательную переменную
Но есть и другая проблема. Прям сегодня столкнулся (почему и тему создал) - у одного пользователя при первом запуске программы происходил краш файла. Успевал записаться один узел и у которого уже второй атрибут не имел закрывающую кавычку. Т.е. никаких бэкапов нет и в помине. Как и рабочего файла настроек. В итоге я пользователю прислал пустой файл настроек (с основной разметкой, без значений атрибутов) и у него все заработало. Но вот отследить где и почему происходило нарушение файла возможности нет.
Вот я и подумал - может в методе SetValue моего класса при вызове метода xElement?.SetAttributeValue(attrName, value) можно как-то проверять данные, которые должны быть сохранены?
Вопрос: Вычисление по формуле с вводом переменных из файла и выводом результата в файл. Модификация

Добрый вечер. Начал вторую л/р по TASM для DOS: модификация программы для вычисления уравнения.

1) ввести в файл Input.txt несколько переменных;
2) вычислить формулу, подставляя в неё введённые переменные из файла Input.txt;
3) вывести результат в файл Output.txt.
a,b,c,d,e,x - обычные целые числа.

Вычислительная часть есть давно. Разделение вводимых чисел в файле Input.txt делаю через точку с запятой ";"
Для работы используются функции открытия файла (3Dh), создания файла (3Ch), чтения из
файла (3Fh), записи в файл (40h) и закрытия файла (3Eh).
Понятия не имею со вводом и выводом, как сделать так, чтобы ввести в файл именно требуемые числа так, чтобы программа сумела их правильно прочитать и занести. И так же чтобы нормально записать правильный ответ в Output.txt.
Файлы находятся в корневой папке, где и .asm-файл и сам .exe. Заранее благодарен.

Assembler
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
.model small  ;Маленькая модель памяти, код занимает один сегмент, данные и стек объединены в одну группу с именем DGROUP , универсальнее чем tiny
 
.stack 200h  ;определяет стек  размером в 200h (512) байт.
 
.data   ;Начало сегмента данных
 
        msgPressAnyKey  db      0Dh, 0Ah, 'Press any key to exit...', '$'  ;Вывод Нажать клавишу для выхода
        
        file_name db 'Input.txt',0
        file_name_Out db 'Output.txt',0
        Output db "OUTPUT_TEST"
        Gotten db 1,1,1,1,1,1
        handle dw 1
        buffer db 254
 
        x               dw      2    ;Данные X
        a               dw      1    ;Данные A
        b               dw      3    ;Данные B
        c               dw      4    ;Данные C
        d               dw      5    ;Данные D
        e               dw      34   ;Данные E
.data;Конец сегмента данных
        iResult         dw      ?    ;Данные результата
.code   ;Начало сегмента кода
 
main    proc        ;начало процедуры с именем main
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data ; Загрузить регистр DS адресом DGROUP,
        mov     ds,     ax ; в который входят сегменты данных и стека.
        ;открываем файл
        mov ah,3Dh ; Функция DOS 3Dh (открытие файла)
        xor al,al ; Режим открытия - только чтение
        lea dx,file_name ; Имя файла - DS:dx указатель на имя файла
        xor cx,cx ; Нет атрибутов - обычный файл
        int 21h ; Обращение к функции DOS - в ax деcкриптор файла
 
        mov handle,ax ; Сохранение дескриптора файла
        ;читаем файл
        mov bx,ax ; Дескриптор файла - копируем в bx указатель файла
        mov ah,3Fh ; Функция DOS 3Fh (чтение из файла) -  будем читать из файла
        lea dx,buffer ; Адрес буфера для данных -  в память buffer
        mov cx,80 ; Максимальное кол-во читаемых байтов
        int 21h ; Обращение к функции DOS
        
        ;закрываем файл
        mov ah,3Eh ; Функция DOS 3Eh (закрытие файла) - закрываем файл, после чтения
        mov bx,handle ; Дескриптор
        int 21h ; Обращение к функции DOS
        
        lea dx,buffer
        call str_to_udec_word
        
 
        ;ввод исходных данных
        mov     ah,     09h ;номер функции вывода на экран – в АН
        call    ReadInt16   ;Вызов команды считывания числа со знаком    
        mov     [a],    ax   ;занесение a в регистр
 
        mov     ah,     09h ;номер функции вывода на экран – в АН
        call    ReadInt16   ;Вызов команды считывания числа со знаком    
        mov     [b],    ax  ;занесение b в регистр
        
                ;ввод исходных данных
        mov     ah,     09h ;номер функции вывода на экран – в АН
        call    ReadInt16       ;Вызов команды считывания числа со знаком
        mov     [c],    ax  ;занесение c в регистр
 
        mov     ah,     09h ;номер функции вывода на экран – в АН
        call    ReadInt16       ;Вызов команды считывания числа со знаком
        mov     [d],    ax      ;занесение d в регистр  
        
                        ;ввод исходных данных
        mov     ah,     09h ;номер функции вывода на экран – в АН
        call    ReadInt16       ;Вызов команды считывания числа со знаком
        mov     [e],    ax      ;занесение e в регистр      
 
        mov     ah,     09h     ;номер функции вывода на экран – в АН
        call    ReadInt16       ;Вызов команды считывания числа со знаком
        mov     [x],    ax      ;занесение x в регистр
 
        ;вычисления по формуле
        mov     ax,     [x]     ;a*x^4
        imul    ax              ;Возведение в степень со знаком
        imul    ax              ;Возведение в степень со знаком
        imul    [a]             ;умножение на a со знаком
        mov     bx,     ax      ;сохранение промежуточного результата в bx
        mov     ax,     [x]     ;b*x^3
        imul    ax              ;Возведение в степень со знаком
        imul    [x]             ;Умножение на x со знаком
        imul    [b]             ;Умножение на b со знаком
        add     bx,     ax      ;сохранение промежуточного результата в bx
        mov     ax,     [x]     ;c*x^2
        imul    ax              ;Возведение в степень со знаком
        imul    [c]             ;Возведение в степень со знаком
        sub     bx,     ax      ;Вычитание промежуточного результата и сохранение в bx
        mov     ax,     [x]     ;Внесение в регистр ax числа x для перемножения
        imul    [d]             ;Умножение x на d со знаком
        add     ax,     bx      ;dx:ax=числитель
        cwd                     ;Копируются значения старшего бита регистра ax во все биты регистра dx, во избежание переполнения
        idiv    [e]             ;ax=частное,  делим выражение на E
        mov     [iResult],      ax  ;Сохранить результат в регистр ax
        ;вывод результата
        mov     ah,     09h     ;номер функции вывода на экран – в АН
        ;lea     dx,     [msgResult]  ;указатель на команду вывода ответа
        int     21h             ;Вывод Result =  на экран
        mov     ax,     [iResult] ;вывести ответ из регистра ax
        ;ожидание нажатия любой клавиши
        mov     ah,     09h     ;номер функции вывода на экран – в АН
        lea     dx,     [msgPressAnyKey] ;указатель на сообщение Нажать клавишу для выхода
        int     21h     ;Вывод B на экран
        mov     ah,     00h     ;прерывание для чтение кода символа из буфера клавиатуры с ожиданием, пока не нажата клавиша
        int     16h             ;прерывание для вывода ответа в ASC-II
        ;завершение программы
        mov     ax,     4C00h   ; DOS функция выхода из программы
        int     21h     ; Выход из программы
main    endp            ;конец процедуры с именем, аналогичной имени в директиве proc
 
; Процедура преобразования строки в слово без знака
; In: DX - адрес строки.
; Out: Gotten - массив с полученными числами (в случае ошибки AX = 0)
 
str_to_udec_word:
push cx ; Сохранение регистров
push dx
push bx
push si
push di
push bp
mov si,dx ; SI = адрес строки
mov cx,10 ; DI = множитель 10 (Основание системы счисления)
xor ax,ax ; AX = 0
xor bx,bx ; BX = 0
xor di,di
 
studw_lp:
 mov bl,[si] ; BL - следующий символ в строке
cmp bl, ';' ; разделитель = ';'
je incbp
 inc si ; инкремент адреса - приращение адреса
 cmp bl,'0' ; если код символа ниже '0'
 jl studw_error ; тогда ошибка
 cmp bl,'9' ; если код символа больше 9
 jg studw_error ; тогда ошибка
 sub bl, 30h ; преобразование в int
 mul cx ; AX = AX * 10
 jc studw_error ; если результат больше 16 бит - ошибка
 add ax,bx
 jc studw_error ; переполнение - ошибка
mov Gotten[di],al
 jmp studw_lp ; цикл
 
incbp:
xor ax, ax
inc di
inc si
cmp di, 6
jne studw_lp
 
studw_error:
 xor ax,ax ; AX = 0
 
 studw_exit:
 pop di ; Восстановление регистров
 pop si
 pop bx
 pop dx
 pop cx
pop bp
 ret
 
 
 
;Ввод числа со знаком
;на выходе:
;  ax - введённое число
ReadInt16       proc
        xor     bx,     bx      ;признак положительного числа
        xor     cx,     cx      ;введённое число
        @@do:                   ;делать чтение числа
                mov     ah,     00h ;прерывание для чтения символа клавиатуры с ожиданием.
                int     16h     ;прерывание для вывода ответа в ASC-II
                mov     dl,     al          ;перемещение al в dl, регистр ax-слово, ah-байт,al-байт
                cmp     al,     _ENTER_     ;Нажат ли Enter (возврат каретки) ?
                je      @@break             ;да, выход из циклов, переход на следующий оператор
                cmp     al,     '-'         ;Число отрицательное?
                jne     @@endif             ;да, сменить знак
                        mov     bx,     1   ;поместить в bx 1
                        jmp     @@putchar   ;безусловный переход на вывод из массива на экран
                @@endif:                    ;сменить знак
                sub     al,     '0'         ;Использовать ASC-II код, запись '0' заменит символ 0 на его ascii код
                jc      @@do                ;Переход, если бит переноса установлен
                cmp     al,     9+1         ;сравнение вводимого числа на равенство десятичной системе
                jnc     @@do                ;Переход, если бит переноса установлен
                xor     ah,     ah      ;обнулить регистр ah, то же что и  mov ah,0
                shl     cx,     1       ;cx=cx*10
                mov     si,     cx      ;загружаем cx в si
                shl     cx,     1       ;cдвиг cx на одну позицию влево
                shl     cx,     1       ;cдвиг cx на одну позицию влево
                add     cx,     si      ;сложение cx и si
                add     cx,     ax      ;cx=cx+ax
        @@putchar:                      ;вывод из массива на экран
                mov     ah,     02h     ;установить позицию курсора
                int     21h             ;выводим на экран
        jmp     @@do                    ;безусловный переход на вывод из массива на экран
@@break:                                ;выход из циклов
        mov     ax,     cx              ;загрузка введенного в cx числа в ax
        test    bx,     bx              ;сравнение числа/E с 0
        jz      @@exit                  ;переход к завершению программы
        neg     ax                      ;изменение знака числа в ax на противоположный
@@exit:                                 ;выход из программы
        ret ;завершение программы
ReadInt16       endp        ;завершение блока с процедурой ввода числа со знаком
 
end     main ;конец программы
Добавлено через 3 часа 40 минут
Забыл добавить - ничего не надо выводить в консоль, только Press and Key после проведения вычислений, ответ в файле Output.txt. Ну и пример какой-нибудь получше может найдется, как делать ввод в файл 1 и вывод в файл 2?
Ответ: Хм, поменяв цифры в Input.txt под свои, увидел, что программа таки считает и выводит и на экран, и в файл Output.txt. Но результат что-то не равный тому. Значит, бардак таки в вычислениях

Добавлено через 15 минут
Вместо 1 получается почему то аж 65

Добавлено через 2 часа 19 минут
Ошибки исправил, проблемы были в приоритете операций: в индексации переменных в массиве
и перепутывание действий сложения и умножения, тему можно закрывать. Также спасибо товарищу Argogo за оптимизацию исходной формулы в более простую формулу. Если кому-то понадобится - вот код. Возможно, кому-нибудь поможет.
Assembler
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
.model small  ;Маленькая модель памяти, код занимает один сегмент, данные и стек объединены в одну группу с именем DGROUP , универсальнее чем tiny
 
.stack 100h  ;определяет стек  размером в 200h (512) байт.
 
.code   ;Начало сегмента данных
start:
        ;инициализация сегментного регистра ds адресом сегмента данных
        mov     ax,     @data ; Загрузить регистр DS адресом DGROUP,
        mov     ds,     ax ; в который входят сегменты данных и стека.
        
        ;открываем файл
        mov ah,3Dh ; Функция DOS 3Dh (открытие файла)
        xor al,al ; Режим открытия - только чтение
        lea dx,file_name ; Имя файла - DS:dx указатель на имя файла
        xor cx,cx ; Нет атрибутов - обычный файл
        int 21h ; Обращение к функции DOS - в ax деcкриптор файла
        mov handle,ax ; Сохранение дескриптора файла
        
        ;читаем файл
        mov bx,ax ; Дескриптор файла - копируем в bx указатель файла
        mov ah,3Fh ; Функция DOS 3Fh (чтение из файла) -  будем читать из файла
        lea dx,buffer ; Адрес буфера для данных -  в память buffer
        mov cx,80 ; Максимальное кол-во читаемых байтов
        int 21h ; Обращение к функции DOS
        
        ;закрываем файл
        mov ah,3Eh ; Функция DOS 3Eh (закрытие файла) - закрываем файл, после чтения
        mov bx,handle ; Дескриптор
        int 21h ; Обращение к функции DOS
        
        lea dx,buffer   ;Адрес буфера для данных
        call str_to_udec_word   ;Вызов процедуры получения и конвертации значений переменных
        
        ;вывод строки result
        mov ah,9 ;номер функции вывода на экран - в AH
        mov dx, offset message_result ;адрес начала строки - в DX
        int 21h ;вызов системной функции
        
        call calculate ;Вызов процедуры вычисления
        call print  ;Вызов процедуры вывода результата вычисления
        
        mov ah,3Dh ; Функция DOS 3Dh (открытие файла)
        mov al, 1   ; Режим открытия (запись)
        lea dx,file_name_Out    ;Имя файла для записи результата
        xor cx,cx ; Нет атрибутов - обычный файл
        int 21h ; Обращение к функции DOS
        mov handle, ax ;Сохранение дескриптора файла
        mov ah,40h ; Функция записи в файл
        mov bx,handle ;Передаем handle
        lea dx,Output   ;Передаем строку с результатом
        mov cl,10   ;длина строки с результатом
        int 21h     ;Обращение к функции DOS
        mov ah,3Eh ; Функция DOS 3Dh (закрытие файла)
        mov bx,handle ;Передаем handle
        int 21h ; Обращение к функции DOS
        mov ah,8h ; Функция DOS 8h (ввод символа с ожиданием)
        int 21h ; Обращение к функции DOS
        mov ax,4c00h    ;4c - функция завершения программы (00 = return 0)
                        ;mov ah, 4ch - можно записать одной командой, а можно двумя
                        ;mov al,00h
        int 21h ; Обращение к функции DOS
        
        ;Процедура конвертации символа в беззнаковое значение
        ;Входное значение: DX - адрес символа
        ;Выход: Gotten - массив с полученными значениями (При ошибке AX = 0)
        str_to_udec_word:
        push cx ;сохранение значения регистра cx в стеке
        push dx ;сохранение значения регистра dx в стеке
        push bx ;сохранение значения регистра bx в стеке
        push si ;сохранение значения регистра cx в стеке
        push di ;сохранение значения регистра cx в стеке
        push bp ;сохранение значения регистра cx в стеке
        
        mov si,dx   ; SI = указатель символа
        mov cx,10   ; DI = множитель 10 (Основание СС)
        xor ax,ax   ;AX = 0
        xor bx,bx   ;BX = 0
        xor di,di   ;DI = 0
        
        studw_lp:   ;процедура работы с текстом файла
        mov bl,[si] ;BL - cледующий символ строки
        cmp bl, ';' ;разделитель значений = ';'
        je incbp    ;переход к функции обнуления значений при попадании на символ разделителя
        inc si      ;увеличение счетчика
        cmp bl,'0'  ;если значение символа меньше '0'
        jl studw_error  ;переход к процедуре ошибки
        cmp bl, '9'     ;если значение символа меньше '0'
        jg studw_error  ;переход к процедуре ошибки
        sub bl, 30h     ;перевод символа в цифру десятичной системы
        mul cx          ;AX = AX * 10
        jc studw_error  ;если результат больше чем 16 бит - ошибка
        
        error:
        add ax,bx ;сумме регистров bx и ax
        jc studw_error  ;переполнение - переход к ошибке
        mov Gotten[di],ax ;запись значения в массив переменных Gotten
        jmp studw_lp ;переход к началу процедуры (цикл)
        
        incbp:      ;метка процедуры для обнуления значений, предназначенных для работы с текстом файла
        xor ax,ax   ;AX = 0
        inc di  ;увеличение счетчика для массива переменных
        inc di  ;увеличение счетчика для массива переменных
        inc si  ;увеличение счетчика для работы с текстом
        cmp di,12   ;если di не равно 8, то возврат к процедуре работы
        jne studw_lp    ;переход к процедуре работы с текстом файла
        
        studw_error:
        xor ax,ax   ;AX = 0
        
        studw_exit:
        pop di      ;загрузка значения di,si,bx,dx,cx,bp регистра из стека
        pop si      
        pop bx      
        pop dx      
        pop cx      
        pop bp      
        ret         ;завершение процедуры
        
        print:      ;метка процедуры вывода конечного результата с переводом из HEX в ASCII
        push ax     ;сохранение значения регистра ax,bx,cx и dx в стеке
        push bx     
        push cx     
        push dx     
        mov bx, 10  ;делитель (Основание СС)
        mov cx, 0   ;количество выводимых цифр
        xor si,si   ;обнуление счетчика в регистре SI
        @div:       ;начало цикла выделения цифры
        xor dx,dx   ;делим (dx:ax) на bx
        div bx      ;деление с остатком
        add dl,'0'  ;преобразуем остаток деления в символ цифры
        push dx     ;и сохраняем его в стеке
        inc cx      ;увеличиваем счетчик цифр
        test ax, ax ;в числе еще есть цифры?
        jnz @div    ;да - повторить цикл выделения цифры
        @@show:     ;начало цикла отображения цифр
        mov ah,02h  ;функция ah=02h int 21h - вывести символ из dl на экран
        pop dx      ;извлекаем из стека очередную цифру
        int 21h     ;и выводим ее на экран
        mov Output[si],dl ;добавляем цифру в массив
        inc si      ;увеличиваем счетчик в регистре SI
        loop @@show ;выполняем столько раз, сколько нашли цифр в числе (cx)
        pop dx      ;загрузка значения dx,cx,bx и ax регистра из стека
        pop cx      
        pop bx      
        pop ax      
        ret         ;завершение процедуры
            
        calculate:  ;метка процедуры расчета выражения, с использованием массива данных из файла   
        ;a*x+b
        mov si, 0   ;запись значения индеекса массива переменных для последующего извлечения значения A
        mov ax,Gotten[si]   ;запись в AX значения переменной A из массива переменных
        mov si,10           ;запись значения индекса массива переменных для последующего извлечения значения X
        mov bx,Gotten[si]   ;запись в AX значения переменной X из массива переменных
        mul bl              ;умножение AX=AL*BL
        mov bx,ax       ;сохранение промежуточного результата значения (a*x^2)
        mov si, 2   ;запись значения индеекса массива переменных для последующего извлечения значения B
        mov ax,Gotten[si]   ;запись в AX значения переменной B из массива переменных
        add bx,ax       ;(d*x)/e+c*x^2
        mov varm1,ax        ;сохранение промежуточного результата значения (a*x^2)
        
        ;(a*x+b)*x-c
        mov si,10   ;запись значения индеекса массива переменных для последующего извлечения значения X
        mov ax,Gotten[si]   ;запись в AX значения переменной X из массива переменных
        mov bx,varm1        ;запись в BX промежуточного значения переменной (a*x+b)
        mul bl              ;умножение AX=AL*BL
        mov si, 4   ;запись значения индеекса массива переменных для последующего извлечения значения C
        mov bx,Gotten[si]   ;запись в BX значения переменной C из массива переменных
        sub ax,bx       ;Вычитание промежуточного результата и сохранение в ax
        mov varm2,ax        ;сохранение промежуточного результата значения (a*x+b)*x-c
        
        ;(((varm2)*x+d)*x/e         (((a*x+b)*x-c)*x+d)*x/e
        mov si,10   ;запись значения индеекса массива переменных для последующего извлечения значения X
        mov ax,Gotten[si]   ;запись в AX значения переменной X из массива переменных
        mov bx,varm2        ;запись в BX промежуточного значения переменной (a*x+b)*x-c
        mul bl              ;умножение AX=AL*BL
        mov si, 6   ;запись значения индеекса массива переменных для последующего извлечения значения D
        mov bx,Gotten[si]   ;запись в BX значения переменной D из массива переменных
        add ax,bx   ;сложение ((a*x+b)*x-c)*x +d и сохранение в ax
        
        mul bl              ;умножение AX=AL*BL
        
        mov si, 8   ;запись значения индеекса массива переменных для последующего извлечения значения E
        mov bx,Gotten[si]   ;запись в AX значения переменной D из массива переменных
        div bl              ;деление AL = AX/BL, AH - остаток
        xor ah,ah           ;зануление остатка от деления
        mov varres,ax       ;сохранение результата в переменную
        ret                 ;завершение процедуры    
            
 
 
        
        .data
            message_result db "Result: ",0Dh, 0Ah,'$';строка для вывода
            file_name db 'Input.txt',0  ;строка с именем файла, включающего переменные для вычисления
            file_name_Out db 'Output.txt',0 ;строка с именем файла, в который будет записываться результат вычислений
            Output db 11 dup (32) ;массив для записи результата в виде строки
            Gotten dw 1,1,1,1,1,1   ;массив переменных A,B,C,D,E,X для вычислений
            handle dw 1             ;переменная для хранения дескриптора файла (краткое описание доступа к файлу)
            buffer db 254           ;буфер для хранения данных
            varm1 dw 0  ;переменная для хранения результата a*x+b
            varm2 dw 0  ;переменная для хранения результата (a*x+b)*x-c
            varres dw 0 ;переменная для хранения результата вычислений - решения
            end start   ;метка окончания программы