41 Востаннє редагувалося wander (21.12.2020 11:33:22)

Re: Обробка текстів, символьні рядки

Lata написав:

В усіх колись не виходить.

Це вірно, всі з чогось починали, але ваш метод простого рандомного вставлення у ваш код strtok, вказівників чи інших виразів - не є ефективним. Вірніше він точно не ефективний у вашому випадку. Як я розумію ви щось вроді читали про strtok, але нічого не зрозуміли, я правий? Просто всі ваші невдачі спіткаються у те, що ви не розібралися, як працює strtok, впевнений якби ви розібралися, то луснули б себе по чолі і посміялися з ситуації.

Lata написав:

Тут я спробувала пройтися по токенах.

Схоже ви таки вирішили скористатися моєю порадою з попереднього повідомлення до того, як я його змінив :)
Але знову ж таки, ви дуже неуважні:

Lata написав:
while (token) { // невірна умова
char* p = token;
while (p) {
    if (p = "a") { // що це за присвоєння? порівняння це '==' і чому різко з 'a' стало "a"?
        p++;
        if (p = "t") { // те саме
            p++;
            if (p = "y") { // те саме
                p++;
                if (p = "\0") { // нащо це?
                    printf("%s", token);
                }
            }
        }
    }
}

Ну, вже тепліше.

Подякували: Lata1

42

Re: Обробка текстів, символьні рядки

#include <stdio.h>
#include <string.h>
int main()
{
char text[]=" pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly ";
char *token=strtok(text," ");
int n=0;
char* p=token;
printf("pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly");
printf("\nСлова, які закінчуються буквосполученням 'aty':");
while(*p){
    while(*token){
       if(*p=='a'){
       p++;
       if(*p=='t'){
           p++;
              if(*p=='y'){
                   p++;
                   n++;
                   token = strtok(NULL, " ");
                   printf("%s\n", token);
           }
       }
    }
      token++;
    }
     p++;
    }


printf("\nЇх кількість: %i",n);
    
return 0;
}

Тут спробувала врахувати зауваження.

pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly                                                   
Слова, які закінчуються буквосполученням 'aty':                                                                               
Їх кількість: 0 

Я читала про функцію, але бачила лише простіші приклади. Тобто дано geeks-geeks, розділити на geeks і geeks.
Ну а в мене умова значно складніша.

43

Re: Обробка текстів, символьні рядки

Це недопрацьований код. вже бачу кілька помилок

44

Re: Обробка текстів, символьні рядки

#include <stdio.h>
#include <string.h>
int main()
{
char text[]=" pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly ";
char *token=strtok(text," ");
int n=0;
char* p=token;
printf("pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly");
printf("\nСлова, які закінчуються буквосполученням 'aty':");
while(*token){
    char* p=token;
    while(*p){
       if(*p=='a'){
       p++;
       if(*p=='t'){
           p++;
              if(*p=='y'){
                   p++;
                   n++;
                   token = strtok(NULL, " ");
                   printf("%s\n", token);
           }
       }
    }
      token++;
    }
     p++;
    }


printf("\nЇх кількість: %i",n);
    
return 0;
}

Тут я думала так, але не виводить нічого.

45

Re: Обробка текстів, символьні рядки

Lata написав:

Тут я думала так, але не виводить нічого.

І не виведе, давайте так: на вашу думку, що робить token = strtok(NULL, " ") цей рядок?

Подякували: Lata, koala2

46 Востаннє редагувалося koala (21.12.2020 12:22:09)

Re: Обробка текстів, символьні рядки

Цікаво - скільки вже разів ur_nazу казали, щоб не лишав неконструктивних коментарів - так ні, бере і робе.

       if(*p=='a'){
       p++;
       if(*p=='t'){
           p++;
              if(*p=='y'){
                   p++;

Оці ваші ланцюжки if-ів можна спокійно замінити на strncmp:

if( strncmp(p,"aty",3)==0 ) { 
    p+=3; //одразу на 3
    n++;
}
Подякували: Lata1

47

Re: Обробка текстів, символьні рядки

І не виведе, давайте так: на вашу думку, що робить token = strtok(NULL, " ") цей рядок?

Повертає вказівник на Null.

#include <stdio.h>
#include <string.h>
int main()
{
char text[]=" pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly ";
char *token=strtok(text," ");
int n=0;
char* p=token;
printf("pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly");
printf("\nСлова, які закінчуються буквосполученням 'aty':");
while(*token){
    char* p=token;
    while(*p){
          if(strncmp(p,"aty",3)==0){ 
           p+=3;
           n++;
           printf("%s\n", token);
          token=strtok(NULL," ");
            }
          token++;
    }
     p++;
    }


printf("\nЇх кількість: %i",n);
    
return 0;
}

Замінила купу іфів. Далі нічого не видає.

48 Востаннє редагувалося wander (21.12.2020 13:33:42)

Re: Обробка текстів, символьні рядки

Lata написав:

Повертає вказівник на Null.

Ні :)
Отже ще раз, функція strtok виконує пошук токенів (лексем) у деякому рядку string. Послідовність викликів цієї функції розбивають рядок на лексеми, які являють собою послідовності символів, розділених символами роздільниками, ці роздільники ви задаєте другим параметром (у вашому випадку це пробіл).

На перший виклик, функція приймає рядок в якості аргументу, який використовується в якості початкової точки для пошуку лексем. У наступні виклики, функція очікує нульовий вказівник (він же NULL) і використовує позицію відразу після закінчення останньої лексеми як нове місцезнаходження для сканування.

В якості результату своєї роботи strtok повертає:
Вказівник на останню знайдену лексему в рядку або повертає нульовий вказівник (він же NULL), якщо немає знайдених лексем.

Таким чином, при першому виклику strtok, якщо все добре ви отримуєте токен, який вказуватиме на перше слово вашого тексту. Проте лише першого слова недостатньо, потрібно отримати і всі інші, аж поки не закінчиться ваш текст, вірно? Саме тому використовують strtok передаючи першим аргументом NULL, адже тоді ф-я продовжить своє виконання з того ж місця де вона завершила і поверне наступне слово і т.д. Тобто це можна використовувати в циклі, як ітератор.

#include <stdio.h>
#include <string.h>
int main() {
    char  text[] = "pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly";
    char* token  = strtok(text, " ");
    printf("%s\n", token); // виведе "pryvitaty"
    token  = strtok(NULL, " "); // передали NULL
    printf("%s\n", token); // виведе "z"
}

Роботу функції strtok можна також уявити, що вона ніби ділить суцільний масив char'ів на масив вказівників на char'и

char  text[] = "pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly";
// перетворює в:
char* tokens[] = {"pryvitaty", "z", "novym", "rokom", /* і т.д. */};
// тоді їх можна вивести, як:
printf("%s\n", tokens[0]); // виведе "pryvitaty"
printf("%s\n", tokens[1]); // виведе "z"
printf("%s\n", tokens[2]); // виведе "novym"
// ...

І от strtok повертає одразу tokens[0], tokens[1], tokens[2], etc

49

Re: Обробка текстів, символьні рядки

for(char* token = strtok(text, " "); token != NULL; token = strtok(NULL, " "))
{
    if(/*token закінчується на "aty"*/){
        /*вивести, полічити, зробити те, що треба*/
    }
}
Подякували: leofun011

Re: Обробка текстів, символьні рядки

Чому б не написати свою функцію? Так буде цікавіше Вам і, можливо, навчитесь більше.

51 Востаннє редагувалося wander (21.12.2020 13:40:36)

Re: Обробка текстів, символьні рядки

koala написав:
for(char* token = strtok(text, " "); token != NULL; token = strtok(NULL, " "))
{
    if(/*token закінчується на "aty"*/){
        /*вивести, полічити, зробити те, що треба*/
    }
}

Ну от, вся моя писанина зійшла нанівець.

Львовский сырник в мульти написав:

Чому б не написати свою функцію? Так буде цікавіше Вам і, можливо, навчитесь більше.

Якщо ви говорите саме про написання своєї версії функції strtok, то це насправді нетривіальна задача, тобто не все так просто, особливо для початківця.

52 Востаннє редагувалося koala (21.12.2020 13:57:12)

Re: Обробка текстів, символьні рядки

Це просто другий крок декомпозиції. Перший був

for(/*слово серед слів у реченні*/)
{
    if(/*слово закінчується на "aty"*/){
        /*вивести, полічити, зробити те, що треба*/
    }
}

53

Re: Обробка текстів, символьні рядки

Ну от, вся моя писанина зійшла нанівець.

Не нанівець. Пояснення більш-менш доступні.

Чому б не написати свою функцію? Так буде цікавіше Вам і, можливо, навчитесь більше.

Чому б не утримуватися від беззмістовних повідомлень? Можливо, Ви б мали більше часу для чогось корисного.

#include <stdio.h>
#include <string.h>
int main()
{
char text[]=" pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysiki baly ";
char *token=strtok(text," ");
int n=0;
char* p=token;
printf("pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly");
printf("\nСлова, які закінчуються буквосполученням 'aty':");
for(char* token=strtok(text, " ");token!=NULL;token = strtok(NULL, " "))
{
    if(strncmp(p,"aty",3)==0){
           p+=3;
           n++;
           printf("%s\n", token);
    }
}


printf("\nЇх кількість: %i",n);
    
return 0;
}

Я спробувала врахувати всі зауваження і пропозиції.

pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly                                                     
Слова, які закінчуються буквосполученням 'aty':                                                                                 
Їх кількість: 0                                                                                                                 
                                                                                                                                
...Program finished with exit code 0                                                                                            
Press ENTER to exit console.      

54

Re: Обробка текстів, символьні рядки

Якщо ви говорите саме про написання своєї версії функції strtok, то це насправді нетривіальна задача, тобто не все так просто, особливо для початківця.

Я ж казала ;)

55

Re: Обробка текстів, символьні рядки

Lata написав:

Не нанівець. Пояснення більш-менш доступні.

Але все ще нічого незрозуміло?

Lata написав:

Я спробувала врахувати всі зауваження і пропозиції.

Ну от, token це ваше слово, так? Тепер вам потрібно пройтися по цьому слову посимвольно і подивитися чи у нього закінчення "ати", а для цього потрібен ще один вкладений цикл.

Подякували: Lata1

56 Востаннє редагувалося Lata (21.12.2020 15:31:39)

Re: Обробка текстів, символьні рядки

Зробила іншим способом, ніж починала. Вже краще розумію.

Подякували: wander1

57

Re: Обробка текстів, символьні рядки

А тепер декомпозиція (майже) без стандартних функцій.

for(/*слово серед слів у реченні*/)
{
    if(/*слово закінчується на "aty"*/){
        /*вивести, полічити, зробити те, що треба*/
    }
}

Ми не можемо працювати зі словами, цикл має бути по символах. Але серед символів нам потрібні саме слова.

for(/*символ у реченні*/)
{
    if(/*ще не кінець слова*/) {
        /*якось обробити символ слова*/
    }
    else {  
        if(/*слово закінчується на "aty"*/){
            /*вивести, полічити, зробити те, що треба*/
        }
    }
}

Якось так. Кінець слова ми як визначаємо? Це або пробіл, або нуль (останнє слово може закінчуватися '\0'). Значить, треба на один крок більше. Далі - кудись треба збирати слово (насправді ні, але це пізніше). Поїхали:

char *text = ...;
char word[20] = ""; //не дуже хороша ідея, але поки що хай буде
char *word_p = word;
char *p = text;
do {// do-while обробить '\0' в кінці
    if(*p!=' ' && *p!='\0') {
        *word_p++ = *p;
        *word_p = '\0'; //одразу закриваємо слово, щоб воно завжди було коректним; word_p вказує на '\0' в кінці слова
    } else {
        if(word_p-word>3 && *(word_p-3) == 'a' && *(word_p-2)=='t' && *(word_p-1)=='y'){
            printf("%s\n", word);
            counter++;
        }
        //слово закінчилося, треба його почистити, щоб нове збирати
        word_p = word;
        *word_p = '\0';
    }
} while(*p++!='\0'); 

Ура! Вже працює! Щоб ви не думали, що я такий розумний - я спершу word-word_p>3 написав і не міг зрозуміти, чого ж це нічого не ловиться.

Подякували: Arete, Lata2

58

Re: Обробка текстів, символьні рядки

Не знаю правда чи ще ця гілка актуальна, але тут більш менш хоч якісь думки можна прочитати...

Львовский сырник в мульти написав:

Чому б не написати свою функцію? Так буде цікавіше Вам і, можливо, навчитесь більше.

Ви мене порадували)))
Як по мені краще використовувати стандартний набір інструментів. Вони налагоджені та оптимізовані по швидкості.
А якщо взагалі без них ось тримайте, так би мовити у навчальних цілях:

#include <stdio.h>
int main()
{
    char str[] = " pryvitaty z novym rokom i pobazhaty zdaty vsi roboty i otrymaty vysoki baly ";
    char sub[] = "aty";

    char *p = str, *pwd = str; // покажчики котрі ходитимуть у межах рядка утворюючи підрядок
    size_t i, word = 0;

    while (*p)
    {
        if (*p == ' ')
            pwd = p;

        // Ну а тут перевіряємо на ATY підрядок, якщо проходить всі умови ...
        if (*sub == *p)
        {
            for (i = 0; i < 3; ++i)
                if (sub[i] != *(p + i))
                    goto l1;
            if (*(p + i) == ' ' || *(p + i) == '\0')
            {

                // ... то виводимо на екран та інструментуємо лічильник

                printf("%.*s\n", ((p + i) - pwd), (*pwd == ' ' ? (pwd + 1) : pwd)), word++;
                if (*(p + i))
                    p = ((p + i) + 1), pwd = p;
            }
        }
    l1:
        p++;
    }

    printf("Words \"ATY\": %zu\n", word);
    return 0;
}

З Вашого дозволу використаю тільки PRINTF

На виході отримуємо

pryvitaty 
pobazhaty 
zdaty
otrymaty 
Words "ATY": 4

Ось тримайте початковий код. Щоб не вигадувати велосипед заново.
https://code.woboq.org/userspace/glibc/ … k_r.c.html
https://opensource.apple.com/source/Lib … .auto.html

Подякували: Lata1