Консультация № 189621
27.06.2016, 11:35
0.00 руб.
0 1 1
Уважаемые эксперты! Пожалуйста, ответьте на вопрос:

не могли бы вы объяснить принцип работы данной функции выравнивания текста по ширине?

Приложение:
//выравнивание по ширине
void printAligned(char* str, int width)
{
if (strlen(str) == 0)
{
cout << endl;
return;
}

int wordBegin = 0;
char** words = (char**) malloc(sizeof(char*));
int wordsSize = 0;

while (wordBegin < strlen(str))
{
if (str[wordBegin] == ' ')
{
wordBegin++;
continue;
}

int wordLen = 1;
while (wordBegin + wordLen < strlen(str) && str[wordBegin + wordLen] != ' ')
{
wordLen++;
}

words = (char**) realloc(words, sizeof(char*) * (wordsSize + 1));
words[wordsSize] = strncpy((char*)malloc(sizeof(char)*(wordLen + 1)),str + wordBegin, wordLen);
words[wordsSize++][wordLen] = '\0';
wordBegin += wordLen;
}

if (wordsSize == 0)
{
cout << endl;
return;
}


for (int front = 0; front < wordsSize; )
{
while (strlen(words[front]) > width)
{
char * toOut = strncpy((char*) malloc(sizeof(char) * (width + 1)),words[front], width);
char * rest = strcpy((char*) malloc(sizeof(char) * (strlen(words[front]) - width + 1)),words[front] + width);
toOut[width] = '\0';
rest[strlen(words[front]) - width + 1] = '\0';
/*cout << toOut << endl;*/
free(words[front]);
free(toOut);
words[front] = rest;
}


int toPrint = 0;
int toPrintW = 0;
for (int i = front; i != wordsSize; ++i) {
if (toPrintW + strlen(words[i]) + toPrint <= width)
{
toPrintW += strlen(words[i]);
toPrint++;
} else
{
break;
}
}

if (toPrint > 1) {
int spaces = (width - toPrintW) / (toPrint - 1);
int spaces2 = (width - toPrintW) % (toPrint - 1);
for (int j = 0; j < toPrint; ++j) {
cout << words[front++];


if (j != toPrint - 1)
{
for (int s = 0; s < spaces; ++s) cout << ' ';
if (j < spaces2) cout << ' ';
}
}
}
else
{
cout << words[front++];
}
cout << endl;
}
}

Обсуждение

давно
Посетитель
7438
7205
29.06.2016, 11:49
общий
это ответ
Здравствуйте, Александр!
Смотрите комментарии...
[code h=200]#include <iostream>

using namespace std;

//выравнивание по ширине
void printAligned(char* str, int width)
{
if (strlen(str) == 0)
{
cout << endl; //если строка нулевой длины, то ничего не делаем
return;
}

//создадим массив слов
int wordBegin = 0; //начало очередного слова в строке
char** words = (char**) malloc(sizeof(char*)); //массив указателей на слова
int wordsSize = 0; //количество слов

while (wordBegin < strlen(str)) //пока не кончилась строка
{
if (str[wordBegin] == ' ') //ищем начало слова
{
wordBegin++;
continue;
}

int wordLen = 1; //найдем длину слова, имеем первый не пробел, т.е. длина = 1
//пока не конец строки,и пока не пробел
while (wordBegin + wordLen < strlen(str) && str[wordBegin + wordLen] != ' ')
{
wordLen++; //считаем
}
//расширим массив слов на 1
words = (char**) realloc(words, sizeof(char*) * (wordsSize + 1));
//копируем в массив слово
words[wordsSize] = strncpy((char*)malloc(sizeof(char)*(wordLen + 1)),str + wordBegin, wordLen);
//с нулем
words[wordsSize++][wordLen] = '\0';
wordBegin += wordLen; //перемещаем указатель в строке на слово
}

//массив создан. Если нет ни одного слова - выходим
if (wordsSize == 0)
{
cout << endl;
return;
}


//начинаем анализ на заполнение строки для вывода
for (int front = 0; front < wordsSize; ) //по всем словам, front - индекс текущего слова
{
while (strlen(words[front]) > width) //если текущее слово больше длины выводимой строки!
{ //то выведем его по кускам

//скопируем часть слова, равную длине выводной строки
char * toOut = strncpy((char*) malloc(sizeof(char) * (width + 1)),words[front], width);
//остаток до конца слова
char * rest = strcpy((char*) malloc(sizeof(char) * (strlen(words[front]) - width + 1)),words[front] + width);
toOut[width] = '\0'; //закроем строки нулем
rest[strlen(words[front]) - width + 1] = '\0';
cout << toOut << endl; //выведем начало слова (равную длине выводной строки!)
free(words[front]); //удалим длинное слово!
free(toOut); //удалим выведенное начало
words[front] = rest; //словом теперь будет остаток слова
} //и на повтор проверки длины строки!


//текущее слово помещается в выводимую строку, считаем слова, сколько их поместится в длину выводной строки
int toPrint = 0; //количество слов
int toPrintW = 0; //их общая длина
for (int i = front; i != wordsSize; ++i)//от текущего слова и до конца
{ //добавление очередного слова (и пробела!) помещается в строку?
if (toPrintW + strlen(words[i]) + toPrint <= width)
{
toPrintW += strlen(words[i]); //считаем общую длину
toPrint++; //и слова
}
else
{
break; //очередное слово уже не помещается в чтроку
}
}

//выводим найденные слова
if (toPrint > 1) //больше одного слова?
{
//слова выравниваем по ширине, поэтому
//посчитаем одинаковое количество пробелов между всеми слова
// и количество промежутков, куда вставим дополнительно по одному пробелу
int spaces = (width - toPrintW) / (toPrint - 1); //одинаковое количество между всеми словами
int spaces2 = (width - toPrintW) % (toPrint - 1);//дополнительные пробелы, чтобы было выравнивание по ширине
for (int j = 0; j < toPrint; ++j) //по всем найденным словам
{
cout << words[front++]; //выводим слово


if (j != toPrint - 1) //кроме последнего
{
for (int s = 0; s < spaces; ++s) //выводим разделяющие пробелы
cout << ' ';
if (j < spaces2) //и один дополнительный, если есть таковой
cout << ' ';
}
}
}
else
{
cout << words[front++]; //одно слово просто выводим
}
cout << endl; //конец строки
}
}

char *text = "11111 2 33333 44444 5555 6666 777777777777777777777 8888888888 9999999999999999999999999999999 0000 a sa d f g\r\n";

int main()
{
printAligned(text, 20);
return 0;
}
[/code]
Об авторе:
"Если вы заметили, что вы на стороне большинства, —
это верный признак того, что пора меняться." Марк Твен
Форма ответа