Форум программистов, компьютерный форум, киберфорум
С++ для начинающих
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.80/55: Рейтинг темы: голосов - 55, средняя оценка - 4.80
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76

Запись структуры в файл, чтение из файла и удаление (файловый ввод/вывод)

01.12.2016, 17:00. Показов 12208. Ответов 80
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый вечер! Возникла такая проблема, что при добавлении записи, удаляются уже имеющиеся записи в файле.
Также не помешала бы помощь в вопросе удаления записи, с указанным возрастом. Ну и вывод всего содержимого в файле.
Спасибо, за помощь.
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
#include <iostream>
#include <fstream>
 
enum ChosenOperation { ADD = 1, SHOW, DELETE, EXIT };
 
enum SearchingCriteria { NAME = 1, ADDRESS, PHONE, AGE };
 
struct Human
{
    std::string full_name;  // фамилия имя отчество
    std::string address;    // домашний адрес
    std::string phone;      // телефон
    unsigned int age;       // возраст
};
 
void add_new_entry_to_file( std::string filename )
{
    std::cout << "\n\n\tAdding new student to database.\n\n";
 
    std::cout << "Enter number of entries: ";
    unsigned int number_of_entries;
    std::cin >> number_of_entries;
 
    std::cout << "\n\n\tEnter all nessesary data of each entry.\n\n";
    struct Human* human = new struct Human[number_of_entries];
 
    for ( unsigned int i = 0, nth; i < number_of_entries; ++i )
    {
        nth = i + 1;
        while ( std::cin.get() != '\n' );
 
        std::cout
            << "Enter full name of "
            << nth
            << " student: ";
        std::getline( std::cin, human[i].full_name );
 
        std::cout
            << "Enter address of "
            << nth
            << " student: ";
        std::getline( std::cin, human[i].address );
 
        std::cout
            << "Enter phone number of "
            << nth
            << " student: ";
        std::getline( std::cin, human[i].phone );
 
        std::cout
            << "Enter age of "
            << nth
            << " student: ";
        std::cin >> human[i].age;
        std::cout << "\n";
    }
 
    std::ofstream fout( filename.c_str() );
    for ( unsigned int i = 0; i < number_of_entries; ++i )
    {
        fout
            << human[i].full_name
            << "|"
            << human[i].address
            << "|"
            << human[i].phone
            << "|"
            << human[i].age
            << "\n";
    }
    fout.close();
 
    delete [] human;
}
 
void show_data( std::string filename )
{
    // TODO
}
 
void delete_data_in_file( std::string filename, int searching_criteria )
{
    // TODO
}
 
int main()
{
    int key = 0;
    while ( key != ChosenOperation::EXIT )
    {
        std::cout
            << "MENU:\n\n"
            << "\t1 - ADD\n"
            << "\t2 - SHOW\n"
            << "\t3 - Delete\n"
            << "\t4 - EXIT(Esc)\n\n"
            << "Press any key: ";
 
        std::cin >> key;
 
        switch ( key )
        {
            case ChosenOperation::ADD :
                add_new_entry_to_file( "Person.txt" );
 
            case ChosenOperation::SHOW :
                show_data( "Person.txt" );
 
            case ChosenOperation::SEARCH :
                delete_data_in_file( "Person.txt", SearchingCriteria::NAME );
 
            case ChosenOperation::EXIT :
                key = ChosenOperation::EXIT;
        }
    }
 
    return 0;
}
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
01.12.2016, 17:00
Ответы с готовыми решениями:

Ввод с клавиатуры и запись в файл, чтение из файла и запись в массив, вывод из массива на экран
1.Ввод с клавиатуры и запись в файл, чтение из файла и запись в массив, вывод из массива на экран 2.Ввод с клавиатуры и запись в массив,...

Чтение из файла STL (файловый ввод/вывод)
В чем проблема? map.ccp void Map::ReadFromFile(fstream&amp; F) { string s,key; int k, value, counter; map &lt;string, Pr&gt; ob; map...

Открыть текстовый файл, дозаписать в него данные, вывести содержимое файла (файловый ввод/вывод)
Открыть текстовый файл 1.txt, имя файла указывается в командной строке. Дозаписать в него данные. Вывести содержимое файла 1.txt построчно.

80
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
04.12.2016, 00:04
Лучший ответ Сообщение было отмечено georgiisav988 как решение

Решение

Студворк — интернет-сервис помощи студентам
Вот работающий готовый код для MS Visual Studio 2015:
main.cpp

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
#include "stdafx.h"
#include "Person.h"
#include "my_functions.h"
 
int main()
{
    std::vector<Person> pdata;
 
    int key = 0;
    while (key != EXIT)
    {
        key = promt_user_choose_menu_operation();
        switch (key)
        {
        case ADD:
            std::cout << "\n\tAdding new student to database.\n";
            add_new_entries_to_array(pdata);
            copy_data_to_file(pdata, "Person.txt");
            break;
 
        case SHOW:
            if (!pdata.empty())
            {
                // show( pdata );
                for (const auto & elem : pdata)
                    elem.show();
                std::cout << "\n\n";
            }
            else
                std::cout << "\n\tNo entries were found!\n";
            break;
 
        case DELETE:
            if (!pdata.empty())
            {
                delete_chosen_data_from_array(pdata);
                copy_data_to_file(pdata, "Person.txt");
            }
 
            else
                std::cout << "\n\tNo entries were found!\n";
            break;
 
        case EXIT:
            key = EXIT;
            break;
 
        default:
            std::cout << "\nIt seems like wrong number. Try again.\n";
            break;
 
        } // end switch ( key )
 
    } // end while ( key != EXIT )
 
    return 0;
}

Person.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#ifndef PERSON_H
#define PERSON_H
 
#include <string>
 
struct Person
{
    std::string full_name = "Default name";
    std::string address = "Default address";
    std::string phone = "Default phone number";
    unsigned int age = 0;
 
    void show() const;
};
 
#endif // PERSON_H

Person.cpp

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include "stdafx.h"
#include "Person.h"
 
void Person::show() const
{
    std::cout
        << "\n"
        << full_name
        << "\n"
        << address
        << "\n"
        << phone
        << "\n"
        << age
        << "\n";
}

my_functions.h

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
#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H
 
#include "stdafx.h"
#include "Person.h"
 
enum ChosenOperation { ADD = 1, SHOW, DELETE, EXIT };
enum SearchingCriteria { NAME = 1, ADDRESS, PHONE, AGE };
 
int promt_user_choose_menu_operation()
{
    int key = 0;
    std::cout
        << "\nMENU:\n\n"
        << "\t1 - ADD\n"
        << "\t2 - SHOW\n"
        << "\t3 - DELETE\n"
        << "\t4 - EXIT\n"
        << "\nMake your choice (press any key): ";
    std::cin >> key;
    return key;
}
 
void get_data_from_user(std::string & str)
{
    std::getline(std::cin, str);
}
 
void get_data_from_user(unsigned int & uint)
{
    std::cin >> uint;
    while (std::cin.get() != '\n') {}
}
 
size_t promt_user_input_number_of_entries()
{
    size_t number_of_entries = 0;
    std::cout << "Enter number of entries: ";
    std::cin >> number_of_entries;
    while (std::cin.get() != '\n') {}
 
    return number_of_entries;
}
 
template <typename T>
void promt_user_input_data_of_selected_field
(
    const std::string message,
    size_t number_of_entry,
    T & selected_field
)
{
    std::cout << message << " number #" << number_of_entry << ": ";
    get_data_from_user(selected_field);
}
 
template <typename T>
void promt_user_choose_deleting_criteria(T & deleting_criteria)
{
    std::cout << "\n\nSelect deleting criteria: ";
    get_data_from_user(deleting_criteria);
}
 
int promt_user_choose_searching_criteria()
{
    unsigned int searching_criteria = 0;
    std::cout
        << "\n\nSelect searching criteria:\n\n"
        << "\t1 - SEEK ENTRY BY NAME\n"
        << "\t2 - SEEK ENTRY BY ADDRESS\n"
        << "\t3 - SEEK ENTRY BY PHONE\n"
        << "\t4 - SEEK ENTRY BY AGE\n"
        << "\nMake your choice (press any key): ";
    get_data_from_user(searching_criteria);
    return searching_criteria;
}
 
void add_new_entries_to_array(std::vector<Person> & pers)
{
    auto number_of_entries = promt_user_input_number_of_entries();
 
    std::cout << "\n\tEnter all nessesary data of each entry.\n";
    Person p;
    for (unsigned int nth = 1; nth <= number_of_entries; ++nth)
    {
        promt_user_input_data_of_selected_field("Enter full name of student", nth, p.full_name);
        promt_user_input_data_of_selected_field("Enter address of student", nth, p.address);
        promt_user_input_data_of_selected_field("Enter phone number of student", nth, p.phone);
        promt_user_input_data_of_selected_field("Enter age of student", nth, p.age);
        pers.push_back(p);
        std::cout << "\n";
    }
}
 
void copy_data_to_file(const std::vector<Person> & pers, const std::string & filename)
{
    std::ofstream fout(filename.c_str());
    for (size_t i = 0; i < pers.size(); ++i)
    {
        fout
            << pers[i].full_name
            << "|"
            << pers[i].address
            << "|"
            << pers[i].phone
            << "|"
            << pers[i].age
            << "\n";
    }
    fout.close();
}
 
void delete_chosen_data_from_array(std::vector<Person> & pdata)
{
    std::string str_deleting_criteria;
    size_t int_deleting_criteria;
 
    std::cout << "\nNow you can mark entries to deleting.";
    int key = promt_user_choose_searching_criteria();
    std::cout << "\nNow you can delete selected entries.";
 
    if (key == NAME || key == ADDRESS || key == PHONE)
        promt_user_choose_deleting_criteria(str_deleting_criteria);
    else
        promt_user_choose_deleting_criteria(int_deleting_criteria);
 
    std::vector<Person>::iterator it;
    int counter;
    switch (key)
    {
    case NAME:
        counter = std::count_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.full_name == str_deleting_criteria; });
        for (int i = 0; i < counter; ++i)
        {
            it = std::find_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.full_name == str_deleting_criteria; });
            pdata.erase(it);
            std::vector<Person>(pdata).swap(pdata);
        }
        break;
 
    case ADDRESS:
        counter = std::count_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.address == str_deleting_criteria; });
        for (int i = 0; i < counter; ++i)
        {
            it = std::find_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.address == str_deleting_criteria; });
            pdata.erase(it);
            std::vector<Person>(pdata).swap(pdata);
        }
        break;
 
    case PHONE:
        counter = std::count_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.phone == str_deleting_criteria; });
        for (int i = 0; i < counter; ++i)
        {
            it = std::find_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.phone == str_deleting_criteria; });
            pdata.erase(it);
            std::vector<Person>(pdata).swap(pdata);
        }
        break;
 
    case AGE:
        counter = std::count_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.age == int_deleting_criteria; });
        for (int i = 0; i < counter; ++i)
        {
            it = std::find_if(pdata.begin(), pdata.end(), [&](const Person & p) { return p.age == int_deleting_criteria; });
            pdata.erase(it);
            std::vector<Person>(pdata).swap(pdata);
        }
        break;
 
    default:
        std::cout << "\nIt seems like wrong number. Try again.\n";
        break;
    } // end switch ( button )
 
    std::cout << "\nSelected data has been erased.\n";
}
#endif // MY_FUNCTIONS_H

stdafx.h

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// stdafx.h: включаемый файл для стандартных системных включаемых файлов
// или включаемых файлов для конкретного проекта, которые часто используются, но
// не часто изменяются
//
 
#pragma once
 
#include "targetver.h"
 
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <algorithm>
 
 
// TODO: Установите здесь ссылки на дополнительные заголовки, требующиеся для программы
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
04.12.2016, 15:41  [ТС]
Спасибо большое, за оказанную помощь.
Все же хотелось спросить, как осуществляется удаление записи?
Я вижу, что все работает, но понять, как мне пока не удается.....

И за гайд создания также отдельное, Спасибо!
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
04.12.2016, 22:09
georgiisav988, алгоритм таков.

Шаг 1-ый.
Сначала выводится самое первое меню:
1 - ADD (добавить записи)
2 - SHOW (отобразить имеющиеся записи)
3 - DELETE (удалить имеющиеся записи)
4 - EXIT (выйти из программы)
Если на этом этапе Вы выберете 2 или 3 пункты, программа выведет предупреждение: No entries were found!, то есть, Ни одной записи не найдено!. И действительно, Вы ведь ещё не ввели ни одной записи. Так сделайте это! Выберите цифру 1 (ADD - добавить записи).

Шаг 2-ой.
Выберите количество записей. Ну, например, 3.
Теперь последовательно введите данные для первого студента: ФИО, адрес, телефон, возраст.
Потом для второго студента так же: ФИО, адрес, телефон, возраст.
Потом для третьего студента точно так же: ФИО, адрес, телефон, возраст.
Допустим, Вы ввели такие строчки:
Igor Sokolov
San Francisco, Kennedy st. 23, 12B apt.
8905-123-12-12
23

Oleg Volkov
Los Angeles, Hamilton st. 45, 14C apt.
8909-234-34-34
25

Vlad Medvedev
New York, Church st. 45, 14C apt.
8906-456-56-56
23
Шаг 3-ий.
Выведите сохранённые данные на экран. Для этого выберите в меню 2 (SHOW - отобразить записи).

Шаг 4-ый.
Выберите в меню 3 (DELETE - удалить записи).

Шаг 5-ый.
Выберите критерий поиска:
1 - SEEK ENTRY BY NAME (искать записи по совпадению ФИО)
2 - SEEK ENTRY BY ADDRESS (искать записи по совпадению адреса)
3 - SEEK ENTRY BY PHONE (искать записи по совпадению телефона)
4 - SEEK ENTRY BY AGE (искать записи по совпадению возраста)

Шаг 6-ой.
Например, Вы выбрали цифру 4. То, есть искать записи по возрасту. Теперь надо ввести сам возраст. Давайте скажем программе, чтобы она искала всех студентов, возраст которых равен 23.

Шаг 7-ой.
Выведите оставшиеся записи на экран, то есть нажмите 2 (SHOW - отобразить записи).
Вы должны увидеть только такую запись:
Oleg Volkov
Los Angeles, Hamilton st. 45, 14C apt.
8909-234-34-34
25
Оно и понятно - Вы же сами на предыдущем шаге велели программе удалить все записи о студентах, возраст которых равен 23.

Шаг 8-ой.
Поробуйте ещё поэкспериментировать с программой - удаляйте, добавляйте, отображайте записи.

Шаг 9-ый.
Когда Вам наконец это надоест - выберите 4 (EXIT - выйти из программы).

Шаг 10-ый.
Откройте для себя гугл-переводчик. И начните учить английский. Программист без английского - это как безрукий снайпер. Ну или как безногий бегун.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
04.12.2016, 22:20  [ТС]
Видимо, я не понятно объяснил, что именно спросил.
Я понял алгоритм программы и действия каждого пункта.
Вопрос был насчет, для чего используется вектор, как осуществляется удаление, т.е. программно как происходит.
Да и я понял, что там на английском написано.
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 10:18
Цитата Сообщение от georgiisav988 Посмотреть сообщение
как осуществляется удаление, т.е. программно как происходит
georgiisav988, это завтра всё подробно распишу. Сейчас уже спать иду, час ночи почти, а завтра на работу.
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 10:20
georgiisav988, вот версия с подробными комментариями:
main.cpp

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
#include "stdafx.h" // подключаем предкомпилированные заголовки
#include "Person.h" // подключаем объявление нашего класса (структуры)
#include "my_functions.h" // подключаем файл с нашими функциями
 
int main()
{
    // создаём динамический массив по имени pdata, в котором будут храниться объекты типа Person
    std::vector<Person> pdata; // в качестве массива используем контейнер типа std::vector
 
    int key = 0; // объявляем переменную key и инициализируем её нулём
    
    // до тех пор, пока key не равна EXIT (то есть, 4)
    while ( key != EXIT ) // то есть, пока пользователь не выбрал выход из программы
    {   // выполнять следующее:
        
        // присвоить переменной key результат работы функции promt_user_choose_menu_operation,
        // которая (функция) предлагает пользователю выбрать один из пунктов меню
        key = promt_user_choose_menu_operation();
        
        switch ( key ) // проверить значение, лежащее в переменной key
        {
        case ADD: // в случае, если key равна ADD (то есть, 1)  
            std::cout << "\n\tAdding new student to database.\n"; // вывести на консоль эту фразу
            add_new_entries_to_array( pdata ); // добавить записи в массив pdata
            copy_data_to_file( pdata, "Person.txt" ); // копировать данные (массив) в файл по имени "Person.txt"
            break; // прервать цикл while
 
        case SHOW: // в случае, если key равна SHOW (то есть, 2) 
            if ( !pdata.empty() ) // если массив pdata не пуст
            {
                for ( const auto & elem : pdata ) // для каждого элемента массива pdata выполнить
                    elem.show(); // вывод массива на консоль (экран монитора) с помощью функции-члена show
 
                std::cout << "\n\n"; // после завершения цикла for вывести на консоль две пустые строки
            }
            else // в противном случае ( то есть, если массив pdata пуст)
                std::cout << "\n\tNo entries were found!\n"; // вывести на консоль эту фразу
            break; // прервать цикл while
 
        case DELETE: // в случае, если key равна DELETE (то есть, 3) 
            if ( !pdata.empty() ) // если массив pdata не пуст
            {
                delete_chosen_data_from_array( pdata ); // удалить выбранные данные из массива pdata
                copy_data_to_file( pdata, "Person.txt" ); // копировать данные (массив) в файл по имени "Person.txt"
            }
 
            else // в противном случае ( то есть, если массив pdata пуст)
                std::cout << "\n\tNo entries were found!\n"; // вывести на консоль эту фразу
            break;
 
        case EXIT: // в случае, если key равна EXIT (то есть, 4)
            key = EXIT; // присвоить переменной key значение 4
            break; // прервать цикл while
 
        default: // вариант по умолчанию (если пользователь ввёл неправильное число)
            std::cout << "\nIt seems like wrong number. Try again.\n"; // вывести на консоль эту фразу
            break; // прервать цикл while
 
        } // end switch ( key )
 
    } // end while ( key != EXIT )
 
    return 0;
}
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 11:23
georgiisav988, сейчас ещё для файла с функциями допишу. Я так понимаю, именно он у Вас вызвал наибольшие затруднения.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 12:06  [ТС]
Т.е. данные берутся из файла и помещаются в массив(контейнер), работает с ним и потом записывает обратно в файл?
Да буду рад!
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 12:26
georgiisav988, вот:
my_functions.h

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
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
#ifndef MY_FUNCTIONS_H
#define MY_FUNCTIONS_H
 
#include "stdafx.h" // подключаем предкомпилированные заголовки
#include "Person.h" // подключаем объявление нашего класса (структуры)
 
// создаём перечисление (enum) по имени ChosenOperation (выбранная операция),
// в котором задаём четыре константных целочисленных элемента:
enum ChosenOperation { ADD = 1, SHOW, DELETE, EXIT };
// теперь вместо "магического числа" (то есть, числа обозначающего
// не понятно что) 1 можно использовать элемент ADD (добавить записи),
// вместо 2 - SHOW (отобразить записи), вместо 3 - DELETE (удалить записи),
// а вместо 4 - EXIT (выйти из программы)
 
// создаём перечисление (enum) по имени SearchingCriteria (критерий поиска),
// в котором задаём четыре константных целочисленных элемента:
enum SearchingCriteria { NAME = 1, ADDRESS, PHONE, AGE };
// теперь вместо "магического числа" 1 можно использовать элемент NAME (имя),
// вместо 2 - ADDRESS (адрес), вместо 3 - PHONE (телефон),
// а вместо 4 - AGE (возраст)
 
// предложить пользователю выбрать пункт меню:
int promt_user_choose_menu_operation()
{
    int key = 0;
    std::cout
        << "\nMENU:\n\n"
        << "\t1 - ADD\n"
        << "\t2 - SHOW\n"
        << "\t3 - DELETE\n"
        << "\t4 - EXIT\n"
        << "\nMake your choice (press any key): ";
    std::cin >> key; // ввод с клавиатуры целочисленного значения
 
    return key;
}
 
// получить данные от пользователя (перегруженная функция)
void get_data_from_user( std::string & str ) // передача аргумента по ссылке
{
    // получить от пользователя строку типа std::string
    std::getline( std::cin, str ); // и сохранить её в переменную str
    // для получения строки с пробельными символами обычного std::cin
    // не достаточно, поэтому используем библиотечную функцию std::getline
}
 
// получить данные от пользователя (перегруженная функция)
void get_data_from_user( unsigned int & uint ) // передача uint по ссылке
{
    std::cin >> uint; // для получения базовых типов (например, int, unsiged int,
                      // double, float, char, bool) достаточно обычного std::cin
 
    while ( std::cin.get() != '\n' ) {} // избавляемся от лишних'\n' в потоке
}
 
// предложить пользователю ввести количество записей
size_t promt_user_input_number_of_entries()
{
    size_t number_of_entries = 0;
    std::cout << "Enter number of entries: ";
    std::cin >> number_of_entries;
 
    while ( std::cin.get() != '\n' ) {} // избавляемся от лишних '\n' в потоке
 
    return number_of_entries;
}
 
// шаблонная функция применяется, когда неизвестно заранее, какого типа будут
// какого типа будут аргументы;
// предложить пользователю ввести данные выбранного поля структуры Person:
template <typename T> // шаблонная функция
void promt_user_input_data_of_selected_field
(   // тут список аргументов функции приведён в столбик, так удобнее делать,
    // когда аргументов много (более двух) и у них длинные имена типов и/или
    // собственные названия
    const std::string message,  // сообщение пользователю
    size_t number_of_entry,     // количество записей
    T & selected_field          // выбранное поле
)
 
{
    std::cout << message << " number #" << number_of_entry << ": ";
    get_data_from_user( selected_field ); // вызов перегруженной функции
    // если пользователь вводит строку, будет вызвана та версия функции
    // get_data_from_user, в которой задействована функция std::getline,
    // позволяющая получать строку с пробелами; если пользователь вводит
    // возраст (беззнаковый целочисленный тип), то будет вызвана та версия
    // функции get_data_from_user, которая использует обычный std::cin;
}
 
// предложить пользователю выбрать критерий удаления записи
template <typename T> // шаблонная функция
void promt_user_choose_deleting_criteria(T & del_criteria) // передача по ссылке
{
    std::cout
        << "\n\nSelect deleting criteria: "; // вывод на консоль этой фразы
        
    get_data_from_user( del_criteria ); //вызов перегруженной функции
}
 
// предложить пользователю выбрать критерий поиска записи
int promt_user_choose_searching_criteria()
{
    unsigned int searching_criteria = 0;
    std::cout
        << "\n\nSelect searching criteria:\n\n"
        << "\t1 - SEEK ENTRY BY NAME\n"
        << "\t2 - SEEK ENTRY BY ADDRESS\n"
        << "\t3 - SEEK ENTRY BY PHONE\n"
        << "\t4 - SEEK ENTRY BY AGE\n"
        << "\nMake your choice (press any key): ";
 
    get_data_from_user( searching_criteria ); //вызов перегруженной функции
 
    return searching_criteria;
}
 
// добавить новые записи в массив (аргумента pers передаётся в функицю по ссылке)
void add_new_entries_to_array( std::vector<Person> & pers )
{
// стандарт C++11 позволяет по-новому использовать ключевое слово auto
// теперь не надо расписывать какого типа будет переменная number_of_entries -
// компилятор сам это определит, выведя тип из возвращаемого значения функции
// promt_user_input_number_of_entries (то есть, тип переменной number_of_entries
// будет size_t (беззнаковый целочисленный тип)
    auto number_of_entries
        = promt_user_input_number_of_entries(); // присвоить переменной
// number_of_entries результат работы функции promt_user_input_number_of_entries
 
    std::cout // вывести на консоль эту строку:
        << "\n\tEnter all nessesary data of each entry.\n";
 
    Person p; // создать экземляр класса Person (объект типа Person)
 
// счётчик в цикле for назван именем nth - от формы окончаний английских
// числительных: fourth, fifth, sixth, seventh, eighth, ninth, tenth
    for ( unsigned int nth = 1; nth <= number_of_entries; ++nth )
    {
// последовательно одно за другим заполняем поля для объекта
// по имени p (объект типа Person)
        promt_user_input_data_of_selected_field
            (
                "Enter full name of student",
                nth,
                p.full_name
            );
            
        promt_user_input_data_of_selected_field
            (
                "Enter address of student",
                nth,
                p.address
            );
            
        promt_user_input_data_of_selected_field
            (
                 "Enter phone number of student",
                 nth,
                 p.phone
            );
         
        promt_user_input_data_of_selected_field
        (
            "Enter age of student",
            nth,
            p.age
        );
 
        pers.push_back( p ); // добавить в конец вектора pers значение объекта p
        std::cout << "\n"; // вывести на экран пустую строку
    }
}
 
// скопировать данные в файл
void copy_data_to_file
    (
        const std::vector<Person> & pers,
        const std::string & filename
    )
{
 
    // открыть файл для записи:
    std::ofstream fout( filename.c_str() ); // создаем объект типа std::ofstream
    // по имени fout для записи данных в файл с именем, переданным в строковой
    // переменной filename; поскольку объект fout может принимать в качестве
    // аргумента либо сишные строки (массивы типа const char), либо литералы вида
    // "some text", конвертируем строку std::string (а именно такого типа наша
    // переменная filename) в обычную сишную строку с помощью функции-члена c_str
 
    // размер вектора всегда можно узнать с помощью функции-члена size:
    for ( size_t i = 0; i < pers.size(); ++i )  
    {
        fout // записать в файл
            << pers[i].full_name // имя
            << "|" // символ-разделитель |
            << pers[i].address // адрес
            << "|" // символ-разделитель |
            << pers[i].phone // номер телефона
            << "|" // символ-разделитель |
            << pers[i].age // возраст
            << "\n"; // символ новой строки
    }
    fout.close(); // закрыть файл для записи
}
 
// удалить выбранные данные из массива:
void delete_chosen_data_from_array( std::vector<Person> & pdata )
{
    std::string str_deleting_criteria;
    size_t int_deleting_criteria;
 
    std::cout << "\nNow you can mark entries to deleting.";
    int key = promt_user_choose_searching_criteria();
    std::cout << "\nNow you can delete selected entries.";
 
    if ( key == NAME || key == ADDRESS || key == PHONE )
    {   // вызов шаблонной функции с аргументом типа std::string:
        promt_user_choose_deleting_criteria( str_deleting_criteria ); 
    }
    else
    {   // вызов шаблонной функции с аргументом типа size_t
        promt_user_choose_deleting_criteria( int_deleting_criteria ); 
    }
// итератор - специальный класс, реализующий функции умного указателя
// для заданного контейнера (в нашем случае - для вектора):
    std::vector<Person>::iterator it;   
 
    int counter; // счётчик
    switch ( key ) // проверка значения лежащего в переменной key
    {
    case NAME: // если key равна NAME (то есть, равна 1)
 
// присвоить переменной counter значение, возвращаемое библиотечной
// функцией std::count_if
        counter = std::count_if
            (
                pdata.begin(),
                pdata.end(),
             
// лябмда функция (применение [&] предоставляет доступ ко всем
// автоматическим переменным по ссылке):
                [&]
                    ( const Person & p )
                {
                    return p.full_name == str_deleting_criteria;
                } // конец лямбды                
            );
         
// Библиотечная функция std::count_if (подсчитать, если) - это стандартный
// алгоритм для подсчёта в контейнере значений, удовлетворяющих заданному
// условию. Эта функция объявлена в заголовочном файле algorithm. Она
// принимает три аргумента - итератор, обозначающий начало исследуемого
// диапазона заданной последовательности (в нашем случае, это начало вектора,
// заданное функцией-членом begin), итератор, обозначающий конец исследуемого
// диапазона заданной последовательности (в нашем случае, это конец вектора,
// заданный функцией-членом end) и,наконец, третий аргумент - так называемый
// предикат. Предикат - это функция, функциональный объект (функтор), либо,
// как в нашем случае - лямбда-функция (про лямбды, функторы и т.п. читать у
// Стивена Праты в 18 глава, стр. 1077). Предикат возвращает значение типа
// bool - либо истину, либо ложь. Именно предикат определяет соответствие условия
// - в нашем случае, равно ли full_name (имя) каждого элемента вектора значению
// переменной str_deleting_criteria. С помощью такой заковыристой конструкции мы
// посчитаем сколько элементов в нашем векторе соответствуют заданному критерию
// (например, сколько в нашем векторе записей студентов, которых зовут, скажем,
// Олег Волков).
  
        for ( int i = 0; i < counter; ++i )
        {
// Ещё одна функция из стандартной библиотеки, из того же заголовочного файла
// algorithm. Функция std::find_if (найти, если) - это стандартный алгоритм для
// поиска в контейнере значений, удовлетворяющих заданному условию. Возвращаемое
// значение - итератор (специальный класс-указатель) на первый найденный элемент,
// удовлетворяющих заданному условию. Но нам-то надо не только первый, а все,
// правда? Вот для этого мы и считали выше с помощью std::count_if сколько у нас
// таких элементов в векторе имеется, а вот теперь ко всем к ним в цикле применим
// алгоритм std::find_if
            it = std::find_if
                (
                    pdata.begin(),
                    pdata.end(),
                    [&]
                        ( const Person & p )
                    {
                        return p.full_name == str_deleting_criteria;
                    } // лямбда
                );
 
// Хитрая конструкция, использующая ещё две функции-члена класса
// вектор - функцию-член erase и функцию-член swap:
            pdata.erase(it);
            std::vector<Person>( pdata ).swap( pdata );
// Смысл этой операции подробно объяснён вот тут:
// [url]https://www.cyberforum.ru/cpp-beginners/thread552720.html#post2930756[/url]
// Ну и идея так стирать элементы из вектора тоже честно стырена оттуда
// же (большое спасибо форумчанам PointsEqual и Nick Alte).
        }
        break;
 
    case ADDRESS:
        counter = std::count_if
            (
                pdata.begin(),
                pdata.end(),
                [&]
                    ( const Person & p )
                {
                    return p.address == str_deleting_criteria;
                }
            );
            
        for ( int i = 0; i < counter; ++i )
        {
            it = std::find_if
                (
                    pdata.begin(),
                    pdata.end(),
                    [&]
                        ( const Person & p )
                    {
                        return p.address == str_deleting_criteria;
                    }
                );
                
            pdata.erase( it );
            std::vector<Person>(pdata).swap( pdata );
        }
        break;
 
    case PHONE:
        counter = std::count_if
            (
                pdata.begin(),
                pdata.end(),
                [&]
                    ( const Person & p )
                {
                    return p.phone == str_deleting_criteria;
                }
            );
        for ( int i = 0; i < counter; ++i )
        {
            it = std::find_if
                (
                    pdata.begin(),
                    pdata.end(),
                    [&]
                        ( const Person & p )
                    {
                        return p.phone == str_deleting_criteria;
                    }
                );
                
            pdata.erase( it );
            std::vector<Person>( pdata ).swap( pdata );
        }
        break;
 
    case AGE:
        counter = std::count_if
            (
                pdata.begin(),
                pdata.end(),
                [&]
                    ( const Person & p )
                {
                    return p.age == int_deleting_criteria;
                }
            );
            
        for (int i = 0; i < counter; ++i)
        {
            it = std::find_if
                (
                    pdata.begin(),
                    pdata.end(),
                    [&]
                        (const Person & p)
                    {
                        return p.age == int_deleting_criteria;
                    }
                );
                
            pdata.erase( it );
            std::vector<Person>( pdata ).swap( pdata );
        }
        break;
 
    default:
        std::cout << "\nIt seems like wrong number. Try again.\n";
        break;
    } // end switch ( button )
 
    std::cout << "\nSelected data has been erased.\n";
}
#endif // MY_FUNCTIONS_H
1
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 17:45
Цитата Сообщение от georgiisav988 Посмотреть сообщение
Т.е. данные берутся из файла и помещаются в массив(контейнер), работает с ним и потом записывает обратно в файл?
Данные берутся у пользователя, помещаются в массив, а потом копируются в файл. Потом данные добавляются в массив, удаляются из массива и каждый раз, когда массив изменяется, данные в файле переписываются.

Добавлено через 1 час 39 минут
georgiisav988, что-то прояснилось или код по-прежнему вызывает священный ужас? )))

Добавлено через 3 часа 28 минут
georgiisav988, про предикаты вот тут коллега rikimaru2013 хорошо написал.
2
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 17:51  [ТС]
Вот например. Я добавил три записи, закрыл программу, потом заново включил и выбрал пункт Delete.
Тогда все содержимое помещается в массив(vector) и там удаляется, и потом переписывается в файле, так или как-то по другому идет?
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 18:07
Цитата Сообщение от georgiisav988 Посмотреть сообщение
закрыл программу
Чтения из файла я не стал делать. Только запись в файл. Поэтому после закрытия программы и нового её запуска всё начинается как бы с чистого листа.

Добавлено через 14 минут
Цитата Сообщение от georgiisav988 Посмотреть сообщение
Тогда все содержимое помещается в массив(vector) и там удаляется, и потом переписывается в файле, так или как-то по другому идет?
Тогда массив пуст, а манипуляции идут именно с ним. И там уже всё равно, что в файле (наличие или отсутствие там какой-либо информации просто игнорируется). Но можно сделать и чтение из файла тоже. Я просто пока заморачиваться не стал.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 18:27  [ТС]
Если при повторном запуске программы, массив пуст. То я вообще не понимаю, как все происходит!
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 18:50
Цитата Сообщение от georgiisav988 Посмотреть сообщение
при повторном запуске программы, массив пуст
Массив пуст, потому что он уничтожается при закрытии программы. Не пуст может быть файл, но этот факт игнорируется.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 19:22  [ТС]
Можешь объяснить, последовательно, как происходит удаление, при повторном запуске программы?!
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 19:24
Цитата Сообщение от georgiisav988 Посмотреть сообщение
как происходит удаление, при повторном запуске программы
Допустим, в файле остались записи с прошлого раза. И вот ты заново запустил прогу. В файле есть записи. А в массиве - нет. Массив только что был создан при новом запуске проги и он нулевого размера. В нём нет элементов. И вот как только ты добавишь в массив элементы, инфа в файле тут же будет затёрта новой инфой из массива.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 23:37  [ТС]
А как в массив добавляется записи?
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
05.12.2016, 23:38
Цитата Сообщение от georgiisav988 Посмотреть сообщение
А как в массив добавляется записи?
Ты их добавляешь. Сам. Ручками. Пользователь добавляет, то есть. После выбора пункта меню ADD.
1
0 / 0 / 1
Регистрация: 01.04.2016
Сообщений: 76
05.12.2016, 23:43  [ТС]
Так, смотри. В первый раз я добавил 3 записи.
Потом закрыл.
Потом заново открыл.
И просто выбрал пункт 3-Delete. В это случаи, как происходит?!
0
Модератор
Эксперт CЭксперт С++
 Аватар для sourcerer
5288 / 2376 / 342
Регистрация: 20.02.2013
Сообщений: 5,773
Записей в блоге: 20
06.12.2016, 00:11
Цитата Сообщение от georgiisav988 Посмотреть сообщение
Так, смотри. В первый раз я добавил 3 записи.
Потом закрыл.
Потом заново открыл.
И просто выбрал пункт 3-Delete. В это случаи, как происходит?!
В этом случае:
Цитата Сообщение от gru74ik Посмотреть сообщение
программа выведет предупреждение: No entries were found!, то есть, Ни одной записи не найдено!. И действительно, Вы ведь ещё не ввели ни одной записи.
В массиве нет ни одной записи. Работа идёт с массивом. А раз массив ещё пока пуст, то и программа не сможет удалить пустоту.
В файл идёт копирование из массива только после того, как ты с клавиатуры в этот самый массив внесёшь данные. Внесёшь именно вот в этот конкретный раз, в этот сеанс работы с прогой.
Записи, находящиеся в файле с прошлого сеанса работы с программой игнорируются. Программа при новом сеансе ничего о них не знает.

Добавлено через 15 минут
georgiisav988, я уже понял, что тебе надо не только писать в файл, но и читать из файла. Это можно сделать, но уже не сегодня. У меня уже третий час ночи. Я спать.
1
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
06.12.2016, 00:11

Считать данные из текстового файла по условию и записать их в другой текстовый файл (файловый ввод/вывод)
Здравствуйте! Очень прошу о помощи! Суть задания - дан текстовый файл, нужно считать его и записать в другой файл слова состоящие только из...

Структуры.Файловый ввод вывод в С++
Никак не могу разобраться с заданием. Помогиииите!! Структурный тип данных: Текущий курс иностранной валюты (course) Элементы...

Структуры, Файловый ввод-вывод. С++
Привет, помогите пожалуйста. Задание: В программе собраны сведения об успеваемости студентов одной группы по некоторой дисциплине....

структуры. файловый ввод-вывод.
не могу понять, чего от меня хотят???? Сформировать двоичный файл из элементов, заданной структуры, распечатать его содержимое,...

Для каждой строки файла удалить среднее слово; результат записать в файл (файловый ввод/вывод)
для каждой строки файла удалить среднее слово. результат записать в файл


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
60
Ответ Создать тему
Новые блоги и статьи
Из невошедшего на форум (диалог с ИИ-гугла)
zorxor 29.07.2026
А вот, что интересно, сказал мне ИИ-гугла: Этот текст — эмоциональный пост пользователя под ником zorxor на интернет-форуме (вероятно, посвященном мистике, непознанному или альтернативной науке). . . .
Был праздник вчера, а я и не знал.
kumehtar 28.07.2026
27. 07. 2026г. Intel Core 2 Duo исполнилось 20 лет Новости компьютерного мира и их обсуждение (4) Салют, шампанское, овации! :drink:
Нейтральные знания, чистый код - бла-бла-бла-бла, на самом деле кликбейт и самореклама, плагиат, и вот почему
Hrethgir 27.07.2026
То-есть отклонение такой публикации говорит само за себя, и пусть только возьмут на вооружение после отклонения публикации - это будет чистейшим актом плагиата. Отклонял Хабр. Дословно, отклонённая. . .
тв 16 бой ии
anaschu 27.07.2026
Великий Перелом ИИ: Как уравнения ОДУ Radau дожали цензурные фильтры Алисы Фиксируем в мемофонде Теории Всего беспрецедентный факт в истории ИИ-зондирования. В затяжном многораундовом. . .
мв 15. непроверенное, возможно, глюк
anaschu 27.07.2026
НАУЧНО-АНАЛИТИЧЕСКИЙ ОТЧЕТ. РАЗДЕЛ 1. 1: «НАУКА» (РАСШИРЕННАЯ СТЕХИОМЕТРИЧЕСКАЯ И ГЕНЕТИЧЕСКАЯ ВЕРСИЯ)Тема: Теоретическое обоснование инвариантности 19-мерного тензорного ядра непрерывных ОДУ и. . .
Очистка реквизитов и табличных частей документа при копировании (вариант 2)
Maks 26.07.2026
Алгоритм из решения ниже разработан на примере нетипового документа "ЗаявкаНаРаботу", разработанного в КА2. Задача: Заменить алгоритм запрета копирования документов для сотрудников с ролью "Стажер",. . .
Доктрина интенционального знания - Доктрина для портала "Срез".
Hrethgir 25.07.2026
Может найдётся кто захочет оценить доктрину. . . Написания правил участия для меня роскошь, требующая лимита времени, поэтому все сообщения не прошедшие модерацию будут видны только участникам портала,. . .
сукцессия 44. Решил подать на припринт в межународные сервисы препринтов. Но нужно одобрение от ученых
anaschu 25.07.2026
Английский вариант. Пока кто то не одобрит мою личность, мне не получиться это опубликовать на препринте. Но заявку на публикацию статьи я сегодня подам.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru