Программа для форматирования текста!

18.10.2010
4
0
#1
Помогите написать программу или хотя бы нарисуйте алгоритм работы программы:

Имеется текстовый файл. Написать программу, которая перефор¬матирует каждую его страницу в три колонки. Все колонки должны быть выровнены по ширине. Параметры форматирования:
- ширина колонок выходного файла;
- расстояние между колонками.

Заранее спасибо!
 

DarkKnight

Well-known member
01.08.2010
653
0
#2
Слова разрывать нельзя?
И выравнивание по ширине пробелами между слов?
 

DarkKnight

Well-known member
01.08.2010
653
0
#4
По заданию сначало показалось, что алгоритм тривиальный, по-ходу выполнения он все растягивался и растягивался ;-))
Хорошая задачка... Мне лично понравилась....

C++:
#include <iostream>
#include <ctype.h>

using namespace std;
/*АЛГОРИТМ ПОКАЖУ НА СТРОКЕ (ВПРИНЦИПИ) с файлом все тоже самое только считывать файл лучше постранично, размер страницы уже сами решайте какой*/

char *S = "Подразделения компании также производят семейство игровых консолей XBOX, портативные медиаплееры Zune, а также аксессуары для персональных компьютеров (клавиатуры, мыши и т. д.). Продукция Microsoft продаётся более чем в 80 странах мира, программы переведены более чем на 45 языков. Штаб-квартира компании находится в городе Редмонд. Штат сотрудников корпорации составляет порядка 90 тысяч человек. На территории России с ноября 1992 года действует представительство Microsoft (с июля 2004 года — ООО «Майкрософт Рус»). Microsoft находится под надзором суда в результате мирового соглашения 2002 года.... (c) Вырезка с какого то сайта";
char *Sl[10000]; //Массив слов /*для файла лучше использовать динамику к примеру char *Sl = new char[кол-во байт файла]/или страницы
char *SlW[10000]; //Массив строк колонки (идущие подряд слова которые в мещаются в длину колонки /*для файла тоже лучшеь динамика к примеру char *Sl = new char[кол-во байт файла]/или страницы
int sl=0; //Счетчик слов
int slw=0; //Счетчик колонок

//Главная функция программы
void main(void)
{
setlocale(LC_ALL,"Russian"); //Локаль

int width = 20; //Ширина колонки
int Column =2; //Кол-во колонок

char buffer[128]; //Буферная переменная для слова
memset(buffer,0,128); //Обнулим память buffer
char *ptr=buffer; //Указатель на буфер

//Получение всех слов
for (int i=0; i<=strlen(S);i++) //Обойдем всю строку
{
if (isspace((unsigned char)S[i])) //Если символ - разделитель пространства 
{
cout<<"Слово "<<sl<<"> "<<buffer<<endl; //Для отладки : Выведим слово на экран
Sl[sl] = new char[strlen(buffer)]; //Динамически выделим память для слова
strncpy(Sl[sl],buffer,strlen(buffer)+1); //Запишим слово и завершающий (0-символ)
memset(buffer,0,128); //Обнулим буфер будем писать заново
ptr = buffer; //Указатель на нулевую память тоже заново поставим
sl++; //Увеличим счетчик слов
continue; //Продолжим цикл
}
*ptr++ = S[i]; //Запишим в буфер символ и сдвиним указатель на байт
}
if (strlen(buffer) !=0)
{
Sl[sl] = new char[strlen(buffer)]; //Динамически выделим память для слова
strncpy(Sl[sl],buffer,strlen(buffer)+1); //Запишим слово и завершающий (0-символ)
cout<<"Слово "<<sl<<"> "<<buffer<<endl; //Для отладки : Выведим слово на экран
}

SlW[slw] = new char[width+1]; //Выделим память под строку размером ширина-колонки +1
memset(SlW[slw],0,width+1); //Обнулим выделеную память
//Получение строк заданной ширины (из слов)
for (int i=0, size = 0; i<=sl; i++) //Обойдем весь массив слов
{
if (strlen(SlW[slw]) + strlen(Sl[i]) <= width) //Если сумма текущей строки + длина сл. слова <= ширины колонки, значит мы можем включить еще слово
{
strcat(SlW[slw],Sl[i]); //Объеденим текущую строку и слово
strcat(SlW[slw]," "); //Поставим пробел в конец
}
else //Если же слово уже не вместить
{		
SlW[slw][strlen(SlW[slw])-1] = 0;//Уберем последний пробел
int dt = width - strlen(SlW[slw]); //Найдем отклонение сколько пробелов для выравнивания нам нужно добавить

char *temp = new char[width+1]; //Заведем динамическую строку (можно кстати buffer использовать, но так нагляднее)
memset(temp,0,width+1); //Обнулим ее память

char *ptemp = SlW[slw]; //Заведем указатель на строку-колонку
char *ptemp2 = NULL; //И еще один указатель пригодится позже

//Щас бы нам не плохо бы найти величину на сколько пунктов нам требуется увеличить пробелы(разрыв между слов)
//что бы за один обход строки-колонки заполнить этим и займемся
int cnt = 0; //Заведем счетчик
while (strstr(ptemp," ")) //Пока в строке на которую указывает указатель ptemp есть пробел, то
{
ptemp = strstr(ptemp," ")+1; //Сместим указатель на символ идущий за первым пробелом
cnt++; //увеличим счетчик
}
int NomSpace; //кол-во пунктов
if (cnt !=0) //Сдесь сделаем проверку, если в строке-колонке у нас одно слово, то cnt Будет равен 0, а делить на нуль нелья
{
NomSpace = (int)(dt/cnt)+1; //Тут найдем как раз требуемое кол-во пунктов +1 - т.к. округление идет в мин (отбрасывание дробной части)
}
else //Если же слово всего одно
{
NomSpace = 0; //То сразу докидаем его пробелами
for (int m=0; m<dt;m++)
{
strcat(SlW[slw]," ");
}				
dt = 0; 
}
//
ptemp = SlW[slw];//Сделаем что бы указатель указывал на строку-колонку
ptemp2 = temp; //А второй указатель на динамическую строку temp
while (*ptemp) //Пока указатель указывает на не нулевой символ строки
{
if (*ptemp == ' ') // Если указатель на строку-колонку указывает на пробел
{
for (int j=0; j < NomSpace && dt>0; j++) //Поставим наши разрывы, но с проверкой на отклонение
{
*ptemp2 = ' '; //Запишим в буфер
ptemp2++; //Сместим указатель который указывает на буфер //Тут бы список задачу упростил, но ладно, уже выбран массив
dt--; //Уменьшим отклонение на 1 пунке
}
}
*ptemp2 = *ptemp; //Пишим посимвольно в Буфер из строки-колонки
ptemp++; //Сместим указатель
ptemp2++; // И этот тоже
}
strcpy(SlW[slw],temp); //Скопируем из темпа в строку-колонку (тоесть заменим на уже выравненую строку-колонку)
delete[] temp; //Почистим темп

cout<<"Строка-колонка "<<slw<<" >"<<SlW[slw]<<endl; //Для отладки (!)
slw++; //Увеличим счетчик строк

//Приступим к новой строке
SlW[slw] = new char[width+1]; //Выделим память для новой строки
memset(SlW[slw],0,width+1); //Обнулим эту память
strcat(SlW[slw],Sl[i]); //Запишим
strcat(SlW[slw]," "); //Поставим проблел
}
}

cout<<"Строка-колонка "<<slw<<" >"<<SlW[slw]<<endl; //Для отладки (!)

system("pause");
//Ну и самый конец вывод колонок в удобочитаемом виде (ни с лева на право), а с верху вниз + переход на право
cout<<endl<<"\t\tИТОГОВЫЙ ВЫВОД:"<<endl;
//Сначало нам нужно найти некую точку, по отношение к которой мы можем ориентироваться в массиве 
//Я посчитал, что отношение кол-ва слов к к кол-ву колонок то что нужно
int st = st=((int)slw/Column)+1;
for (int i =0; i<st; i++) // Обойдем слова кол-во слов +
{
for (int j=0; j<Column;j++)
{
if ((i+j*st)<=slw)
cout<<SlW[i+j*st];
if (j+1 != Column) cout<<"\t";
}
cout<<endl;
}


}
 
18.10.2010
4
0
#5
Я пробую на RAD Studio 2010 C++ Builder 2010 запустить и мне пишут ошибки:

[ILINK32 Error] Error: Unresolved external '__InitVCL' referenced from C:\PROGRAM FILES\EMBARCADERO\RAD STUDIO\7.0\LIB\CP32MTI.LIB|crtlvcl
[ILINK32 Error] Error: Unresolved external '__ExitVCL' referenced from C:\PROGRAM FILES\EMBARCADERO\RAD STUDIO\7.0\LIB\CP32MTI.LIB|crtlvcl
[ILINK32 Error] Error: Unable to perform link

Помогите разобраться...
 

lazybiz

Well-known member
03.11.2010
1 339
0
#6
[ILINK32 Error] Error: Unresolved external '__InitVCL' referenced from C:\PROGRAM FILES\EMBARCADERO\RAD STUDIO\7.0\LIB\CP32MTI.LIB|crtlvcl
[ILINK32 Error] Error: Unresolved external '__ExitVCL' referenced from C:\PROGRAM FILES\EMBARCADERO\RAD STUDIO\7.0\LIB\CP32MTI.LIB|crtlvcl
[ILINK32 Error] Error: Unable to perform link
Зайди в: File -> New -> Other -> Console Wizard. Убери галку с "Использовать VCL" (Use VCL). Галка на "Console Application" стоять должна. На "Multi Threaded" и "Use CLX" галка должна быть снята.