Помогите, пожалуйста, со строками.

Задание: копирование прилагательных в новой строке:
было: _obichnaya_istoria
задание:_obichnaya_obichnaya_istoria.
В условии цикла-окончание -ая (prostaya, peredovaya и т.д.). Но что-то пошло не так...

  #include <stdio.h>
    #include <conio.h>
    #include <iostream>

using namespace std;
void main()
{ 
char str[100], s;
int  k=0, b=0, j;
cout<< "Vvedite stroku ";
while ((str[k]=getchar())!='\n')
{
k++;
}
str[k]='\0';
int n=100;
// Вывод строки
cout << str << endl;
for(k=0; k<n;k++)
if(str[k]=='a' && str[k+1]=='y' && str[k+2]=='a' && str[k+3]=='_')
{ 
    b=k-b+3;
for(j=n;j>k;j--)
str[j+1]=str[j];
n=n+b;
for(int c=k+1;c<k+b;c++)
    str[c]=str[c-b];
k++;
}
cout<<str<<endl;
}

Сильно через задницу, на скорую руку, ненадёжно, но работает:

#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string.h>

using namespace std;

int main()
{ 
    char str[100], *token, *pos;
    char strout[200];
    int  k=0;
    cout<< "Vvedite stroku ";
    while ((str[k]=getchar())!='\n')
    {
        k++;
    }
    str[k]='\0';

    // Вывод строки
    cout << str << endl;

    char sep[] = "_";
    char aya[] = "aya";
    size_t aya_len = strlen(aya);
    *strout = '\0';
    token = strtok(str, sep);
    while(token != NULL) {
        strcat(strout, sep);
        strcat(strout, token);
        pos = strstr(token, aya);
        if (pos != NULL && pos - token + aya_len == strlen(token)) {
            strcat(strout, sep);
            strcat(strout, token);
        }
        token = strtok(NULL, sep);
    }

    cout << strout << endl;
    getch();
    return 0;
}

Вообще-то задание странное. Если такое делать по нормальному, без подчерков между словами, без начального подчерка, с контролем выхода за границы массивов, то кода будет наверное раза в 2-3 больше.

Кстати, я не понял зачем тут вводить строку посимвольно. Можно было бы использовать gets() — всё равно нет контроля границ массива (или gets_s() — с контролем).

Огромное спасибо). Не могли бы Вы объяснить вот этот фрагмент:

 char sep[] = "_";
    char aya[] = "aya";
    size_t aya_len = strlen(aya);
    *strout = '\0';
    token = strtok(str, sep);
    while(token != NULL) {
        strcat(strout, sep);
        strcat(strout, token);
        pos = strstr(token, aya);
        if (pos != NULL && pos - token + aya_len == strlen(token)) {
            strcat(strout, sep);
            strcat(strout, token);
        }
        token = strtok(NULL, sep);

Что тут вообще происходит? Как описать это в построении блок-схемы?

Описание функции strtok() см. здесь
Описание функции strstr() см. здесь

char sep[] = "_";  // строка-набор символов-разделителей для strtok() - один символ подчерка
char aya[] = "aya";  // окончание прилагательного для strstr()
size_t aya_len = strlen(aya); // вычисление длины строки окончания прилагательного
*strout = '\0';  // в выходную строку забиваем первым символом 0, что бы строка была явно пустая
token = strtok(str, sep);  // взять первую лексему
while (token != NULL) {  // пока есть лексемы
    strcat(strout, sep);  // добавить к выходной строке разделитель
    strcat(strout, token);  // добавить к выходной строке текущую лексему
    pos = strstr(token, aya);  // попытаться найти в текущей лексеме подстроку-окончание прилагательного
    if (pos != NULL && pos - token + aya_len == strlen(token)) {
        // если подстрока найдена И эта подстрока находится в конце лексемы (т.е. найдено прилагательное), то к выходной строке ещё раз добавляем
        strcat(strout, sep);  // разделитель и
        strcat(strout, token);  // текущую лексему-прилагательное
    }
    token = strtok(NULL, sep);  // берём следующую лексему
}

Единственно, что можно рассмотреть подробнее, это выражение pos - token + aya_len == strlen(token).

 obichnaya\0istoria
 ^     ^
 |     pos
 token

posадрес начала совпадения окончания прилагательного; значение pos можно использовать, поскольку первая проверка pos != NULL дала истину.
tokenадрес начала лексемы; значение token можно использовать, поскольку проверка token != NULL в операторе while дала истину.
pos - token — количество символов от начала лексемы до начала окончания.
aya_len — длина окончания (количество символов в окончании).

Следовательно, выражение (pos - token) + aya_len должно быть равно полной длине лескмы, т.е. strlen(token). Если сочетание символов «aya» находится не в конце лексемы (т.е. это не окончание прилагательного), то равенство выполняться не будет.

Правда можно сконструировать случай, когда и эту проверку можно обмануть, например _kayakerskaya_istoria. Т.е., по хорошему, ещё надо потребовать, что бы проверяемое в if «aya» было последним вхождением в лексеме.

А вот с рисованием блок-схем у меня всегда была напряжёнка. Так что это без меня ))

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.