Форум программистов, компьютерный форум CyberForum.ru

Форматирование вывода - C++

Восстановить пароль Регистрация
 
Рейтинг: Рейтинг темы: голосов - 10, средняя оценка - 4.70
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
13.03.2012, 18:31     Форматирование вывода #1
Есть простенькая программа анализирующая частоту употребления слов в тексте, результат своей работы она сохраняет в файл таким образом:
C++
1
file << '['<< ++count << "] " << it.second << '\t' << '\t' << it.first << '%' << endl;
И выглядит результат примерно так:
Название: 0da824e2a42d.png
Просмотров: 162

Размер: 5.3 Кб
Нужно отформатировать вывод так, чтобы третий столбец был выровнен, то есть не было "зигзагообразности" как в данном примере.

Существует ли решение для потокового вывода? А для сишного?
Или только костыли с пост обработкой вывода?
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
go
Эксперт C++
3582 / 1362 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
13.03.2012, 19:40     Форматирование вывода #2
Попробуйте три символа табуляции добавить и т.д.
C++
1
"\t\t\t"
Добавлено через 1 минуту
А вообще есть ios_base::width
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
13.03.2012, 21:53  [ТС]     Форматирование вывода #3
Пробовал и так и так, не помогает.
Может есть ещё какие методы?
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
13.03.2012, 23:36  [ТС]     Форматирование вывода #4
Если вдруг кому интересно, то вот весь код:

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
// FrequencyOfWords.cpp : Defines the entry point for the console application.
//
#include <windows.h>
#include <process.h>
#include <algorithm>
#include <iostream>
#include <iomanip>
#include <fstream>
#include <conio.h>
#include <string>
#include <deque>
#include <set>
#include <map>
 
namespace FOW
{
    using namespace std;
 
    // ========================================== //
    // Список используемых переменных и объектов  //
    // ========================================== //
 
    string bad_simbols       = "$?\"\\“”‚„«»‹›\
           §…&%#!{}[],.:;?*№()<>/*+=0123456789";    // Символы, которые не должны содержаться в слове
 
    string delim(59, '-');                           // Строка-разделитель
    string file_in            =         "in.txt";    // Имя анализируемого файла по умолчанию
    string file_of_exceptions = "exceptions.txt";    // Имя файла со списком слов-исключений
    string file_out           =        "out.txt";    // Имя результирующего файла по умолчанию
 
    size_t words_counter(0);                         // Всего слов в тексте(счётчик)
    int min_word_size = 3;                           // Минимальный размер слова по умолчанию
    set<string> exc;                                 // Список слов-исключений (в нижнем регистре)
    map<string, double> words;                       // Список анализируемых слов (в нижнем регистре), слово - ключ к числу повторений
 
    volatile bool ThreadFlag = true;                 // Флаг для управления потоком progress, при false поток завершается
    streamoff all_f_size(1);                         // Размер файла
    streamoff current_f_size(1);                     // На данный момент прочитано из файла
 
    // ========================================== //
    //            Функциональная часть            //
    // ========================================== //
 
    unsigned _stdcall progress(void*)
    {
        setlocale(LC_ALL, "");
        cout << "Прогресс:\n " << flush;
        cout.precision(4);
 
        while(ThreadFlag)
        {
            cout << "        " << '\r' << flush; // Очищаем пред. вывод
            cout << (((100 / (long double)all_f_size) * current_f_size)) << "%" << flush << '\r';
            if (ThreadFlag) Sleep(100);
        }
 
        // Гарантирует отображение "100%", при малых размерах файла и быстрой работе
        cout << "        " << '\r' << flush;
        cout << 100 << "%\r" << flush;
 
        // Возвращаем переменные в исходное состояние для возможного перезапуска программы
        all_f_size     = (1);
        current_f_size = (1);
 
        return 0;
    }
 
    void read_exceptions(string& exc_file)
    {
 
        ifstream file(exc_file);
        if (!file)
        {
            cout << "\nФайл с исключениями не загружен." << endl;
            return;
        }
 
        string buf;
        while (file >> buf)
        {
            for_each(buf.begin(), buf.end(), [] (char& ch) {ch = tolower(ch);});
            exc.insert(buf);
        }
 
        cout << "\nПрочитано исключений: " << exc.size() << endl;
        file.close();
    }
 
    int  read_text_file(string& inp_file)
    {
        ifstream file(inp_file, ios::binary);
        if (!file)
        {
            cout << "\nФайл с текстом для анализа не загружен." << endl;
            return 1;
        }
 
        // Узнаём размер файла
        file.seekg (0, std::ios_base::end);
        all_f_size = file.tellg();
        file.seekg (0, std::ios_base::beg);
 
        string buf;
        while(file >> buf)
        {
            current_f_size = file.tellg();
 
            for_each(buf.begin(), buf.end(), [] (char& it) {it = tolower(it);});
 
            // Удаление паразитных знаков из кандитата на слово
            for (string::size_type pos = buf.find_first_of(bad_simbols); pos != string::npos;)
            {
                buf.erase(pos);
                pos = buf.find_first_of(bad_simbols);
            }
            // Если слово начинается с "'" или "—" или "-" - обрабатываем эту ситуацию
            if ((buf.begin() != buf.end()) && ((*buf.begin() == '\'') || (*buf.begin() == '—') || (*buf.begin() == '-'))) buf.erase(buf.begin());
            // То же самое, если оканчивается на "'" или "—" или "-"
            if ((buf.begin() != buf.end()) && ((*(--buf.end()) == '\'') || (*(--buf.end()) == '—') || (*(--buf.end()) == '-'))) buf.erase((--buf.end()));
 
            // Конец удаления паразитных знаков
 
            // Если слово не найдено в списке исключений и длиннее min_word_size
            if (!exc.count(buf) && (buf.size() >= (unsigned)min_word_size))
            {
                if (words.count(buf)) ++words[buf];
                words.insert(make_pair(buf, 1));
                ++words_counter;
            }
        }
        cout << "Найдено слов: " << words_counter << endl;
        file.close();
        return 0;
    }
 
    void write_results(string& outp_file)
    {
        ofstream file(outp_file);
 
        // Подготавливаем для вывода, высчитываем для каждого слова процент его употребления в тексте
        for (map<string, double>::iterator it = words.begin(); it != words.end(); ++it)
        {
            it->second = it->second / (double)words_counter;
        }
 
        // Собираем очередь и сортируем в порядке убывания процента повторения
        deque<pair<double, string>> buf;
        for (map<string, double>::iterator i = words.begin(); i != words.end(); ++i)
        {
            buf.insert(buf.begin(), make_pair(i->second, i->first));
        }
        sort(buf.rbegin(), buf.rend());
 
        // Сохраняем
        for_each(buf.begin(), buf.end(), [&file] (pair<double, string> it) 
        {
            static size_t count(0);
            file << '['<< ++count << "] " << it.second << '\t' << '\t' << '\t' << it.first << '%' << endl;
                
        });
 
        file.close();
 
    }
 
    void input_name()
    {
        bool fl = false;
        do
        {
            if (fl) cout << "\nИмя анализируемого файла некорректно, повторите ввод:" << ends;
            else cout << "\nИмя анализируемого файла:" << ends;
            cin >> file_in;
            fl = true;
        }
        while (!ifstream(file_in));
    }
    
    int _main()
    {
        system("cls");
        cout << " Программа анализирует частоту употребления слов в тексте." << endl << delim << endl;
 
        bool inp_err(false);
        do
        {
            if (inp_err) cout << "n должно быть > 0" << ends;
            cout << "\nСчитать словом буквенную последовательность от n символов, где n =" << ends;
            cin >> min_word_size;
            inp_err = true;
        }
        while (min_word_size < 1);
        inp_err = (false);
 
        char ch;
        do
        {
            if (inp_err) cout << " - (Выбор - y/n!)" << ends;
            cout << "\nЗадать имена используемых файлов вручную?(y/n)" << endl;
            ch = tolower(_getche());
            inp_err = true;
        }
        while (ch != 'y' && ch != 'n');
 
        inp_err = (false);
 
        if (ch == 'y')
        {
            input_name();
            cout << "Имя файла содержащего слова-исключения:" << ends; cin >> file_of_exceptions;
            cout << "Имя файла для вывода:" << ends; cin >> file_out;
        }
 
        read_exceptions(file_of_exceptions);
 
        HANDLE hThread = (HANDLE)_beginthreadex(NULL, NULL, progress, NULL, NULL, NULL);
 
        read_text_file(file_in);
 
        write_results(file_out);
 
        ThreadFlag = false;
        WaitForSingleObject(hThread, 120); // Даём время потоку завершиться
 
        ch = 'e';
        do
        {
            if (inp_err) cout << " - (Выбор - y/n!)" << ends;
            cout << "\nРасчёт завершён, проанализировать новый файл?(y/n)" << endl;
            ch = tolower(_getche());
            inp_err = true;
        }
        while (ch != 'y' && ch != 'n');
        inp_err = (false);
 
        int ret(0); // Возвращаемое значение
 
        if (ch == 'y') ret = true;
        else cout << "\n\n" << delim << endl;
 
        // Сбрасываем всё что рассчитывали, для возможного перезапуска с новыми данными
        ThreadFlag = true;
        exc.clear();
        words.clear();
        words_counter = 0;
        return ret;
    }
}
 
int main()
{
    setlocale(LC_ALL, "");
    while (FOW::_main());
    system("pause");
    return 0;
}
Проблема та же, нужно отформатировать вывод без костылей с пост обработкой файла результатов, возможно ли?
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
13.03.2012, 23:48     Форматирование вывода #5
C++
1
2
3
file << '[' << setw(3) << ++count << "] " 
     << setw(15) << it.second 
     << setw(10) << it.first << '%' << endl;
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
13.03.2012, 23:59  [ТС]     Форматирование вывода #6
Лучше не стало:
Миниатюры
Форматирование вывода  
go
Эксперт C++
3582 / 1362 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
14.03.2012, 00:06     Форматирование вывода #7
C++
1
file << '['<< ++count << ']' << it.second << "\t\t\t" << "\t\t\t" << it.first << '%' << endl;
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
14.03.2012, 00:13  [ТС]     Форматирование вывода #8
По прежнему:
Миниатюры
Форматирование вывода  
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
14.03.2012, 00:14  [ТС]     Форматирование вывода #9
Тут не '\t' забивать надо, а как-то по другому делать...
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
14.03.2012, 00:17     Форматирование вывода #10
C++
1
file << '['<< ++count << "] " << std::setw( 5 ) << std::right << it.second <<  std::setw( 15 ) << std::left << it.first << '%' << endl;
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.03.2012, 00:19     Форматирование вывода #11
Цитата Сообщение от Whiteha Посмотреть сообщение
Лучше не стало
Попробуйте перед выводом добавить
C++
1
file.fill(' ');
Toshkarik
 Аватар для Toshkarik
1139 / 856 / 50
Регистрация: 03.08.2011
Сообщений: 2,381
Завершенные тесты: 1
14.03.2012, 00:20     Форматирование вывода #12
Ой наоборот
C++
1
file << '['<< ++count << "] " << std::setw( 10 ) << std::left << it.second <<  std::setw( 15 ) << std::right  << it.first << '%' << endl;
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
14.03.2012, 00:28  [ТС]     Форматирование вывода #13
Эх, ребят, понимаю что бред но и так не получается(
В любом случае спасибо что пытаетесь помочь.
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.03.2012, 05:42     Форматирование вывода #14
Эксперимет с блокнотом показывает, что внешний вид сильно зависит от шрифта. Если выбрать шрифт Courier New, Lucida Console, Terminal и подобные им, то вывод будет ровным, другие шрифты будут разьезжаться.
go
Эксперт C++
3582 / 1362 / 128
Регистрация: 16.04.2009
Сообщений: 4,528
14.03.2012, 09:29     Форматирование вывода #15
Whiteha, почитайте про манипуляторы. И разберитесь в моем примере
C++
1
2
3
4
5
6
7
8
9
10
#include <iostream>
#include <iomanip>
 
int main()
{
   std::cout << std::setw(5) 
             << "[12]" << std::setw(20) << "fdfsfdsfdsfdgdfg" << std::setw(20) << "dfs" << std::endl;
   std::cout << std::setw(5)
             << "[123]" << std::setw(20) << "fdf" << std::setw(20) << "dfs" << std::endl;
}
http://liveworkspace.org/code/e685c3...1f9f47cce7d43a
Код
 [12]    fdfsfdsfdsfdgdfg                 dfs
[123]                 fdf                 dfs
Whiteha
Программист
33 / 33 / 4
Регистрация: 08.07.2011
Сообщений: 190
Записей в блоге: 1
14.03.2012, 10:56  [ТС]     Форматирование вывода #16
Да, всем спасибо, проблема действительно была в шрифте... Каким-то образом Times new roman гадит вывод - Courier New, Lucida Console, Terminal спасают.
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
14.03.2012, 11:13     Форматирование вывода
Еще ссылки по теме:

C++ Форматирование строк. cout
C++ Форматирование текста
Форматирование ячеек в Excel C++

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

Или воспользуйтесь поиском по форуму:
kazak
 Аватар для kazak
3029 / 2350 / 155
Регистрация: 11.03.2009
Сообщений: 5,401
14.03.2012, 11:13     Форматирование вывода #17
Цитата Сообщение от Whiteha Посмотреть сообщение
Каким-то образом Times new roman гадит вывод
довольно таки известным образом. Все дело в начертании букв.
Первые две строки Courier New, вторые - Times New Roman. Каждая строка содержит ровно 5 символов.
Форматирование вывода
Yandex
Объявления
14.03.2012, 11:13     Форматирование вывода
Ответ Создать тему
Опции темы

Текущее время: 06:29. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru