Информатика и технология программирования

         

Форматирование строки


Форматирование строки -размещение ее в выходном массиве заданной размерности таким образом, чтобы интервалы между соседними словами отличались не более, чем на 1.

Шаг 1: Исходные данные и результат. Входная строка произвольной длины в массиве IN[], отформатированная строка длины n в массиве OUT[]. Выходная строка отвечает следующим требованиям:



-слово -любая последовательность символов, кроме пробела ;



-после форматирования число пробелов между словами различается не более чем на 1; -первое и последнее слово расположены по краям строки. Шаг 2: Форматирование включает в себя последовательность из трех действий:


void format(char IN[], char OUT[], int n)
{
// Собрать исходные данные по строке,


// необходимые для форматирования;


// Проверить возможность форматирования;


// Разместить слова в выходной строке.


}

Шаг 3: Данные по строке, необходимые для форматирования: -количество слов в строке -nw; -общее количество символов во всех словах -ns; -стандартное количество пробелов между словами при форматировании -np; -оставшееся количество пробелов, добавляемых по одному между словами -nr. На этом шаге детализируется проверка возможности форматирования и определяются взаимосвязанные параметры.


void format(char IN[], char OUT[], int n)
{ int nw, ns, np, nr;
// Определение nw, ns ...


OUT[0] = '\0';
if (nw &#60 2) return; // Мало слов в строке


np = (n - ns) / (nw - 1);
if (np &#60= 0) return; // Много символов в словах


nr = (n - ns) % (nw - 1); // Остаточное число пробелов


// Размещение слов в выходной строке


}

Шаг 4: Просмотр строки при определении параметров и форматировании можно выполнить, используя:



-цикл в цикле: цикл просмотра всех слов, в который включен цикл посимвольного просмотра интервала между словами и самого слова;



-цикл посимвольного просмотра строки, с использованием признака нахождения внутри слова или вне его - inword.

Выберем второй вариант. При этом необходимо учесть, что символ конца строки может рассматриваться как конец слова (разделитель), поэтому проверку на выход из цикла нужно делать после выполнения тела цикла.


Шаг 5: Определение ns,nw:

for (i=0,ns=0,nw=0,inword =0; ; i++)
{
// Анализ символа IN[i] и подсчет параметров;

if (IN[i] =='\0') break;
}

Шаг 6: Размещение слов в выходной строке:

{
for (i=0,j=0,inword =0; ; i++)
{
// Анализ символа IN[i] и форматирование

// (перенос в OUT[j]);

}
if (IN[i] =='\0') break;
} }

Шаг 7: Анализ символа состоит в выделении 4 вариантов по двум сравнениям -признака inword и типа символа IN[i] - разделителя или символа слова:

{
if (IN[i]==' ' || IN[i]=='\0')
if (inword)
{ nw++; inword =0; } // Конец слова

else
{} // Продолжение разделителя

else
{ ns++;
if (inword)
{} // Продолжение слова

else
{ inword =1; } // Начало слова

} }

Шаг 8: Анализ символа IN[i] и форматирование:

{
if (IN[i]==' ' || IN[i]=='\0')
if (inword)
{ // Конец слова

for (k=0; k&#60np; k++) // Включение "np"

OUT[j++]=' '; // пробелов

if (nr-- &#62 0) // Включение

OUT[j++]=' '; // дополнительного пробела

}
else
{} // Продолжение разделителя

else
if (inword)
OUT[j++]=IN[i]; // Продолжение слова

else
{ // Начало слова

OUT[j++]=IN[i];
inword =1;
} }

Окончательный вариант с оптимизацией (исключение лишних ветвей):



//------------------------------------------------------bk34-12.cpp

//-----Форматирование строки

void format(char IN[], char OUT[], int n)
{
int nw, ns, np, nr, i, j, k, inword;
for (i=0,ns=0,nw=0,inword =0; ; i++)
{
if (IN[i]==' ' || IN[i]=='\0')
{ if (inword) { nw++; inword =0; } }
else
{ ns++; inword=1; }
if (IN[i] =='\0') break;
}
OUT[0] = '\0';
if (nw &#60 2) return;
np = (n - ns) / (nw - 1);
if (np &#60= 0) return;
nr = (n - ns) % (nw - 1);
for (i=0,j=0,inword=0; ; i++)
{
if (IN[i]==' ' || IN[i]=='\0')
{ if (inword)
{
for (k=0; k&#60np; k++) OUT[j++]=' ';
if (nr-- &#62 0) OUT[j++]=' ';
}
}
else
{ OUT[j++]=IN[i]; inword =1; }
if (IN[i] =='\0') break;
}
}


Содержание раздела