#include <stdio.h>
#include <stdlib.h>
#define MAX_LEN 512
// сравнивает две sz строки: результат
// -1: str1 < str2
// 0: str == str2
// 1: str > str2
int cmp(char *str1, char *str2) {
int i, res = 0;
i = 0;
while (1) {
if (str1[i] == '\0') {
if (str2[i] == '\0') {
res = 0;
}
else {
res = -1;
}
break;
}
else if (str2[i] == '\0') {
res = 1;
break;
}
else if (str1[i] != str2[i]) {
res = str1[i] < str2[i] ? -1 : 1;
break;
}
else {
// str1[i] == str2[i]
i++;
}
}
return res;
}
// тут я не понял, конечно, как вводить строку, статично
// или же gets()/scanf()/...
// короче, функция заполняет нашу строку)
int getString(char *buf) {
printf("Vvedite predlozhenie: ");
gets(buf);
return 0;
}
// аналог библиотечной функции
// даем символ, если это буква латинского алфавита возвращает 1, в противном случае 0
int isAlpha(char ch) {
if ( (ch >= 'a') && (ch <= 'z') ) return 1;
if ( (ch >= 'A') && (ch <= 'Z') ) return 1;
return 0;
}
// на вход - строка. на выходе "0",
// если строка не является "предложением",
// если строка является "предложением", то "1"
int checkSyntax(char *buf) {
// перечитал задание) вообще говоря, предложение может быть и "пустым"
// поэтому просто пробегаемся по строке, если встречаем
// "левые символы", то матюгаемся
int i;
int nSymbolPoint = 0; // это счетчик символов '.' который должен быть только один)
for (i = 0; buf[i] != '\0'; i++) {
if (isAlpha(buf[i])) {
continue;
}
switch (buf[i]) {
case '.':
nSymbolPoint++;
case ' ':
case ',':
break;
default:
// вот тут у нас "левый символ"
return 0;
}
if (nSymbolPoint > 1) {
// многовато точек для одного предложения
return 0;
}
}
// цикл кончился, проверим последний символ - точка это или нет?
return (buf[i-1] == '.') ? 1 : 0;
}
// обрабатывает "простое" предложение - сортирует слова
int processSimpleSentence(char *buf, int len) {
// тут надо взять, да посортировать слова...
int i, j, k, p, q, nWords;
char **words;
char *str;
i = 0;
nWords = 0;
while (i < len) {
// находим начало следующего слова;
for (j = i; (!isAlpha(buf[j])) && (j < len); j++);
if (j >= len) break;
// "пробегаем" по слову...
while (isAlpha(buf[j])) j++;
nWords++;
i = j;
}
// посчитали количество слов.
// захватываем память
words = (char**)malloc(sizeof(char*) * nWords);
for (i = 0; i < nWords; i++) {
words[i] = NULL;
}
// теперь выхватываем слова из предложения и заносим в массив
for (i = 0, p = 0; i < nWords; i++) {
// ищем начало следующего слова
for (j = p; !isAlpha(buf[j]); j++);
// конец слова...
for (k = j; isAlpha(buf[k]); k++);
// захватить памяти
str = (char*)malloc(sizeof(char) * (k - j + 1));
// ну и потом закопировать
for (q = 0; j < k; j++, q++) {
str[q] = buf[j];
}
str[q] = '\0';
p = k;
words[i] = str;
}
// sort words
for (i = 0; i < nWords - 1; i++) {
for (j = i + 1; j < nWords; j++) {
// порядок обратный алфавитному!
if (cmp(words[i], words[j]) < 0) {
str = words[i];
words[i] = words[j];
words[j] = str;
}
}
}
// запихиваем слова обратно
k = 0;
for (i = 0; i < nWords; i++) {
// копируем слово
for (j = 0; words[i][j] != '\0'; j++) {
buf[k] = words[i][j];
k++;
}
// ставим разделитель
if (i == (nWords - 1)) {
// после последнего слова разделитель не ставим
}
else {
buf[k++] = ' ';
}
}
// теперь до конца предложения заполним пробелами
while (k < len) {
buf[k++] = ' ';
}
for (i = 0; i < nWords; i++) {
free(words[i]);
}
free(words);
return 0;
}
// вообще говоря, ищет в строке следующую запятую (либо точку),
// возвращает её индекс
// - длина "предложения" в символах
int findNextSentence(char *buf) {
int i = 0;
// полагается, что нам дается "корректное предложение"
while (1) {
if (buf[i] == ',') break;
if (buf[i] == '.') break;
i++;
}
return i;
}
// структурка для следующей за ней функции, сортироваться будут
// , собственно, эти структуры
typedef struct tSentenceDescriptor {
int startPosition;
int lenght;
} tSentenceDescriptor;
// находит в buf nSentences простых предложений и сортирует
// их по длине. Полагается, что каждое простое предложения
// заканчивается запятой
void sortSentences(char *buf, int nSentences) {
tSentenceDescriptor *sentences;
int i, j, k;
char *str; // строчка, куда будем складывать предложения по порядку)
sentences = (tSentenceDescriptor*)malloc(sizeof(tSentenceDescriptor) * nSentences);
j = 0;
// j это начало предложения, k - конец
// заполняем sentences
for (i = 0; i < nSentences; i++) {
k = j + findNextSentence(&buf[j]);
sentences[i].startPosition = j;
sentences[i].lenght = (k - j + 1);
j = k + 1;
}
// захватим памяти для str.
// длина buf == j
str = (char*)malloc(sizeof(char) * j);
// сортируем sentences
for (i = 0; i < nSentences - 1; i++) {
for (j = i + 1; j < nSentences; j++) {
if (sentences[j].lenght < sentences[i].lenght) {
k = sentences[i].lenght;
sentences[i].lenght = sentences[j].lenght;
sentences[j].lenght = k;
k = sentences[i].startPosition;
sentences[i].startPosition = sentences[j].startPosition;
sentences[j].startPosition = k;
}
}
}
// складываем отсортированные предложения в str)
// "k" бегает по str...
k = 0;
for (i = 0; i < nSentences; i++) {
for (j = 0; j < sentences[i].lenght; j++, k++) {
str[k] = buf[sentences[i].startPosition + j];
}
}
// теперь из str сливаем обратно в buf
// k == strlen(str);
for (i = 0; i < k; i++) {
buf[i] = str[i];
}
free(str);
free(sentences);
return;
}
// собственно, выполняет все задание. Меняет местами соседние предложения
int processSentence(char *buf) {
int i = 0, j;
int nSentences = 0;
if (buf[i] == '.') {
// пустое предложение? - на выход
return 0;
}
// индексы i, j, k в следующем цикле указывают на начала простых предложений
while (1) {
// ищем конец простого предложения
j = i + findNextSentence(&buf[i]) + 1;
// обработаем его (sort words)
processSimpleSentence(&buf[i], j - i - 1); // передаем без запятой..
nSentences++;
// это предложение было последним?
if (buf[j - 1] == '.') {
break;
}
i = j; // next iteration...))
}
// тут короче во всех простых предложения слова отсортированы
// и nSentences > 0
// заменяем точку на запятую и передаем в функцию сортировки
// простых предложений по длине
buf[j - 1] = ',';
sortSentences(buf, nSentences);
// восстанавливаем точку
buf[j - 1] = '.';
}
// "Бессмыслы слова, и не нужны..."
// короче, поехали)
int main() {
char buf[MAX_LEN + 1];
getString(buf);
printf("input : %s\n", buf);
if (!checkSyntax(buf)) {
printf("Incorrect syntax\n");
return 0;
}
processSentence(buf);
printf("output: %s\n", buf);
return 0;
}
// "А теперь по кладбищу несут гроб на руках..."
|