Как доработать программу для нескольких разделителей?
Вводится некоторое количество строк (здесь в примере я показываю 1 строку), второе и последнее слово в каждой строке должно перевернуться, за последним словом точка. Но есть нюанс, словами в строке считаются только латиница и кириллица, остальные символы считаются за пробел (назовём их разделители). Программа работает не правильно, если написать подряд >1 разделителя. Например. Ввод: "Я;)люблю ананасы". Нужный вывод: "Я;)юлбюл ысанана". Фактический вывод: "Я;)люблю ысанана". Возможно, проблема в функции reverse_stroki. Буду благодарен, если напишете что не так.
С одним разделителем всё работает как нужно.
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
//максимальная длина строки
#define N 255
//отобразить массив
void vyvod_arr(char** str, int length) {
for (int i = 0; i < length; i++) {
printf("%s\n", str[i]);
}
}
//освободить массив и его строки
void free_arr(char** arr, int length) {
for (int i = 0; i < length; i++) {
free(arr[i]);
}
free(arr);
}
//перевернуть строку
void reverse_stroku(char* l, char* r, int length) {
for (int i = 0; i < length / 2; i++) {//проходимся только по половине строки
char temp = *(l + i);//сохраняем временный символ указателя со смещением адресса вправо на i
*(l + i) = *(r - i);//сохраняем левый символ на правый
*(r - i) = temp;//сохраняем правый символ на левый
}
}
//перевернуть все возможные строки массива
void reverse_stroki(char** arr, int length) {
for (int i = 0, word_count = 0; i < length; i++) {
char* r = NULL, * l = NULL;
char* str = arr[i];
for (int j = 0, length = 0; j < strlen(str); j++) {
char symb = tolower(str[j]);
if ((symb >= 'a' && symb <= 'z') || (symb >= 'а' && symb <= 'я') || (symb >= 'А' && symb <= 'Я')) {//ищем слово в строке
if (l == NULL) {//если не null, то значит первый символ слова уже найден
l = &str[j];//сохраняем адресс первого символа в слове
}
r = &str[j];//сохраняем адресс последнего символа в слове
length++;//наращиваем длину слова
}
else {//выполнится, если встретился разделитель в строке
if (word_count == 1 || (r == &str[strlen(str) - 2] && word_count > 0)) {//если второе слово или последнее слово
reverse_stroku(l, r, length);//переворачиваем слово, зная его начало, конец и длину
}
l = NULL;//обнуляем первый символ в слове
word_count++;//наращиваем кол-во слов в строке
length = 0;//обнуляем длину слова
}
}
word_count = 0;
str[strlen(str) - 1] = '.';//вставляем точку в конец слова
}
}
void vvod_stroki() {
char str[N];
char** arr = NULL;
int length = 0;
str[0] = ' ';
while (1) {
fgets(str, N, stdin);
if (str[0] == '\n') {//если вводится только enter
break;
}
arr = (char**)realloc(arr, (length + 1) * sizeof(char*));//увеличиваем память нашего массива строк
arr[length++] = _strdup(str);//создаём копию строки и заносим её адресс в массив
}
reverse_stroki(arr, length);
vyvod_arr(arr, length);
free_arr(arr, length);
}
void main() {
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
printf("Введите строки, чтобы закончить их вводить, нажмите Enter при пустой строке\n");
vvod_stroki();
}
Ответы (1 шт):
У вас просто «второе слово» находится между первым встреченным разделителем и вторым встреченным разделителем. В случае если второй разделитель двойной «второе слово» будет состоять из 0 символов.
Используйте зависимость от length для счётчика слов:
if (length) {
word_count++;
}