
Представление текста
Текст является упорядоченным множеством строк, и для работы с ним необходимо использовать двумерный массив символов:
char A[20][80];
char B[][40] = { "Строка","Еще строка","0000","abcdef"};
Первый индекс двумерного массива соответствует номеру строки, второй - номеру символа в нем:
int i, k;
for (k=0; A[i][k] !='\0'; k++) ... // Работа с i-й строкой
Упорядоченные строки
При работе со строками часто возникает необходимость их сравнения в алфавитном порядке. Простейший способ состоит в сравнении кодов символов, что при наличии последовательного кодирования латинских букв и цифр дает гарантию их алфавитного упорядочения (цифры, прописные латинские, строчные латинские).
// Функция сравнивает две строки по значениям кодов
// (гарантированный алфавитный порядок для латинских букв).
// Результат сравнения:
// 0 - строки одинаковы,
// -1 - первая строка "меньше" по алфавиту, либо
// строки равны, но первая короче
// 1 - то же самое, но для второй строки
int Compare(unsigned char s1[],unsigned char s2[])
{
int n;
for (n=0; s1[n]!='\0' && s2[n]!='\0'; n++)
if (s1[n] != s2[n]) break;
if (s1[n] == s2[n]) return(0);
if (s1[n] < s2[n]) return(-1);
return (1);
}
В данном примере массивы символов указаны как беззнаковые. В противном случае коды с весом более 0x80 (символы кириллицы) будут иметь отрицательные значения, и располагаться в алфавите "раньше" латинских, имеющих положительные значения кодов (кроме того, еще и в обратном порядке, от Я к А). Чтобы устранить этот и другие недостатки, необходимо установить свой порядок следования символов в алфавите и использовать порядковый номер символа в последовательности (индекс в массиве) в качестве его "веса":
// Сравнение строк с заданными "весами" символов
char Arr[] = "АаБбВвГгДдЕе1234567890";
int Carry(char c)
{
int n;
if (c=='\0') return(0);
for (n=0; Arr[n]!='\0'; n++)
if (Arr[n]==c) break;
return(n+1);
}
int Compare(char s1[],char s2[])
{
int n;
char c1,c2;
for (n=0; (c1=Carry(s1[n]))!='\0' && (c2=Carry(s2[n]))!='\0'; n++)
if (c1 != c2) break;
if (c1 == c2) return(0);
if (c1 < c2) return(-1);
return(1);
}
Контекстная замена
Контекстная замена - поиск и замена в строке фрагментов, заданных одной строкой (контекста) на фрагмент, заданный другой, например:
Исходная строка: "abc234pe4234e"
Заменяемая строка: "234"
Заменяющая строка: "000"
Результат: "abc0000pe40000e"
1. Исходные данные и результат. Строки заданы массивами символов s, s1,s2. Результирующая строка размещается в том же массиве, что и исходная. Контроль размерности не производится:
void Context(char s[], char s1[], char s2[])
{...}
2. Основной цикл программы состоит в посимвольной проверке строки на вхождение в нее подстроки, начиная с текущего символа. В случае вхождения производится замена:
void Context(char s[], char s1[], char s2[])
{
int n;
for (n=0; s[n] !='\0'; n++)
{
Если начиная с n-го символа расположена
подстрока s1, заменить ее на s2 в строке
}
}
3. Проверка утверждения, что начиная с n-го символа в строке s расположена подстрока s2:
int i;
for (i=0; s[n+i] !='\0' && s1[i] !='\0'; i++)
if (s[n+i] != s1[i]) break;
if (s1[n+i]=='\0')
{
заменить s1 на s2 в строке, начиная с s[n]
}
4. Замена подстроки s1 на s2, начиная с n-го символа строки s, заключается перемещении "хвоста" строки s вправо или влево в зависимости от знака разности длин строк и в переписывании строки s2 на место строки s1. Для получения длины строки воспользуемся стандартной функцией strlen:
int l2,dd,k;
l2 = strlen(s2)
dd = l2 - strlen(s1);
if (dd != 0)
{
сдвинуть "хвост" строки s на dd символов
}
for (k = 0; k < l2; k++)
s[n+k] = s2[k];
5. Для сдвига всего "хвоста" (для простоты, начиная с n-го символа) влево (dd < 0) необходимо все символы, начиная с n+dd перенести на dd позиций влево. Для перемещения вправо нужно сначала найти конец строки, чтобы от него производить перемещения символов с убывающим индексом
if (dd < 0)
{
for (k=n; s[k+dd]!='\0'; k++)
s[k] = s[k+dd];
s[k]='\0';
}
else
{
for (к=n; s[к]!='\0'; к++);
for (; k != n; к--)
s[к+dd] = s[к];
}