Как доработать программу для нескольких разделителей?

Вводится некоторое количество строк (здесь в примере я показываю 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 шт):

Автор решения: needKVAS

У вас просто «второе слово» находится между первым встреченным разделителем и вторым встреченным разделителем. В случае если второй разделитель двойной «второе слово» будет состоять из 0 символов.

Используйте зависимость от length для счётчика слов:

if (length) {
    word_count++;
}
→ Ссылка