NOVINKA - Online rekvalifikační kurz Java programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
NOVINKA – Víkendový online kurz Software tester, který tě posune dál. Zjisti, jak na to!

Diskuze: pomoc s implementaci konečneho automatu v jazyce C

V předchozím kvízu, Online test znalostí C++, jsme si ověřili nabyté zkušenosti z kurzu.

Aktivity
Avatar
Tomas
Člen
Avatar
Tomas:22.11.2015 20:51

Ahoj, jsem začátečník a potřeboval bych pomoct s implementaci konečneho automatu do školy... zadání je takoveto:
Automat implementujte jako program v jazyce C, ktery funguje podle
nasledujícich pravidel:

  • Po spustenı programu je automat v počátečnímım stavu a čeká na vstup

od uživatele.

  • Po zadání vstupu automat přejde do příslušného stavu, název stavu

vypíše na obrazovku a připíše, zda je stav konečný nebo ne.

  • Po zadání vstupu, ktery je mimo abecedu automatu, se program

ukončí
Zadání
Navrhnete, minimalizujte a implementujte v jazyce C konečny automat nad
abecedou {’a’,’b’,’c’}. Automat přijímá slova, ktera splnujı nasledující podmínky:

  1. obsahují maximálně 3 znaky ’c’,
  2. obsahují minimalně 1 znak ’b’,
  3. po každem znaku ’b’ nasleduje znak ’a’..

už jsem to nějak častečně vytvořil a mužu to klidně poslat ke korekci ( ale nevim jestli z toho spíš nevstanou vlasy na hlavě :))
Předem děkuji moc za pomoc

 
Odpovědět
22.11.2015 20:51
Avatar
MrPabloz
Člen
Avatar
Odpovídá na Tomas
MrPabloz:22.11.2015 21:29

Tak tu pošli, jak ten tvůj automat vypadá. Jako nakreslené stavy a přechody pro jaké znaky. Nebo nevíš ani to?

Nahoru Odpovědět
22.11.2015 21:29
Harmonie těla a duše, to je to, oč se snažím! :)
Avatar
David Novák
Tvůrce
Avatar
Odpovídá na Tomas
David Novák:22.11.2015 21:32

A co konkrétně ti nefunguje..? Ve škole vám to nevysvětlili?

Nahoru Odpovědět
22.11.2015 21:32
Chyba je mezi klávesnicí a židlí.
Avatar
Tomas
Člen
Avatar
Odpovídá na MrPabloz
Tomas:22.11.2015 21:37

No ja ani nevim jestli jsem ho nakreslil zpravně a myslim ze je to ten modrej nebo zelenej a poslu sem este jak jsem to napsal
A díky moc

 
Nahoru Odpovědět
22.11.2015 21:37
Avatar
Tomas
Člen
Avatar
Tomas:22.11.2015 21:39

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
char a, b, c;

int stav = 0;

char volba;

printf("cekam na zadani\n");

while (true) // problem s podminkou
{
scanf("%c", &volba);

switch (stav)
{
case 0: //zacatek

if(volba == 'a')
{ printf("zustavate v pocatecnim stavu ktery neni konecny");
stav = 0;}

else if(volba == 'b')
{
stav = 1;

}
else if(volba == 'c'){

stav=2;

}

break;

case 1: // nejak to poresit aby i kdyz prijde b tak to slo do erroru

if(volba == 'a') {
stav = 5;

}
else if(volba == 'c','b'){
stav =6;
}

break;

case 2: //stav c1 napsat sem nejaky cyklus by nebylo spatne
printf("ste ve stavu c1 ktery neni konecny");

if(volba == 'c')
{
stav = 3;}
else if(volba == 'a'){

stav = 2;
} else if(volba == 'b'){

stav = 1;
}

break;
case 3: // stav c2

printf("ste ve stavu c2 ktery neni konecny");

if(volba == 'a')
{
stav = 3;

}else if(volba == 'b')
{
stav = 1;

}
else if(volba == 'c'){

stav = 4;
}
break;

case 4: //ctav c3
printf("ste ve stavu c3 ktery neni konecny");
if(volba == 'a'){

stav = 4;
}else if(volba == 'b'){

stav = 1;
}
else if(volba == 'c'){

stav = 6;
}
break;

case 5: //stav a

printf("zustavate ve stavu a ktery je konecny");

if(volba == 'a'){

stav = 5;}
else if(volba == 'b'){

stav =1;
} else if(volba == 'c'){

stav = 2;

}
break;

case 6: //stav error

printf("error");

}}

}

 
Nahoru Odpovědět
22.11.2015 21:39
Avatar
Tomas
Člen
Avatar
Odpovídá na David Novák
Tomas:22.11.2015 21:42

Tu implementaci nam nikdo nevysvětlil, a já jsem začal programovat v říjnu tohoto roku, takže vtom nejsem eště tak zběhlý.... bohužel...

 
Nahoru Odpovědět
22.11.2015 21:42
Avatar
MrPabloz
Člen
Avatar
Odpovídá na Tomas
MrPabloz:22.11.2015 21:50

No nevím, nějak se v tom nákresu nevyznám (toho automatu), nechceš to překreslit lépe, protože takhle mi to příjde že to máš špatně :) skus tam jasně zadat startovní stav (míří do něj z nikde šipka) a pak konečný stav (dvojitý kruh). Poté ke každé šipce jasně napsat jaký znak, protože u toho zeleneho mi to příjde že z c1 de na c2 znakem b, i když to tak není asi myšleno :)
Ohledně kodu, každý stav si představ jako jednu funkci. ta poté volá další podle vstupu. takže např.

void stav1()
{
    char z = ctiDalsiZnak();
    if(z == 'a')
        stav2();
    else if(z == 'b')
        stav3();
    else if(z == 'c')
        stav4();
    else
        stavError();
}

a tak to bude podobné všude :)

Nahoru Odpovědět
22.11.2015 21:50
Harmonie těla a duše, to je to, oč se snažím! :)
Avatar
Tomas
Člen
Avatar
Odpovídá na MrPabloz
Tomas:22.11.2015 22:29

za chvíly to pošlu a ja nevim jestli je zpravně.... a to co jsi napsal mam napsat do toho svyho kodu?

 
Nahoru Odpovědět
22.11.2015 22:29
Avatar
Tomas
Člen
Avatar
Tomas:22.11.2015 22:38

Tady to je ale nevim ktery je zpravne, ani jestli je jeden z nich zpravně....

 
Nahoru Odpovědět
22.11.2015 22:38
Avatar
David Novák
Tvůrce
Avatar
Odpovídá na MrPabloz
David Novák:23.11.2015 0:23

Takhle určitě není dobré v C realizovat konečný automat..

To, co má Tomas je správný postup - case v cyklu načítání znaků a obsluha jednotlivých stavů.. Akorát bych doporučil udělat si enum se stavy pro lepší přehlednost :)

Nemám čas se koukat na tvé zadání, ale pro inspiraci se můžeš podívat na jednoduchý automat, co jsem zde zveřejnil já před nějakou dobou: http://www.itnetwork.cz/…linux-delcom

Nahoru Odpovědět
23.11.2015 0:23
Chyba je mezi klávesnicí a židlí.
Avatar
Odpovídá na Tomas
Libor Šimo (libcosenior):23.11.2015 7:37

Našiel som niečo jednoduchšie na pochopenie:
http://www.matematika.cz/konecny-automat

Nahoru Odpovědět
23.11.2015 7:37
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Tomas
Člen
Avatar
Odpovídá na David Novák
Tomas:23.11.2015 9:47

děkuju moc, ale popravdě už o tom članku vím, hodně jsem se jím inspiroval..... akorát ten muj automat ma ukazovat jenom stav ve kterym konci, (ale ukazuje všechny kterjma prochází) a potom kdyz zadáme sekvenci třeba cbacbacbac tak tam mam 4 c a stejně mi to nejde do erroru.... tak moc nevim co stim mam dělat, a eště jak tam zakomponovat aby se program vypnul když přijde jiný znak....

 
Nahoru Odpovědět
23.11.2015 9:47
Avatar
Tomas
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Tomas:23.11.2015 9:51

děkuju moc, ale není tam jak se to ma implementovat do cecka.... a můžete se mi někdo prosím podívat i na ten automat prosím, když budete mít naladu jestli ho mám dobře? děkuji moc...

 
Nahoru Odpovědět
23.11.2015 9:51
Avatar
Tomas
Člen
Avatar
Odpovídá na David Novák
Tomas:23.11.2015 9:54

A taky nevím co je to ,,enum,, promiň za mojí nezkušenost ale jsem fakt začátečník...

 
Nahoru Odpovědět
23.11.2015 9:54
Avatar
Tomas
Člen
Avatar
Tomas:23.11.2015 12:13

A chtel bych se zeptat jestli sem ten svuj program nahrat znova a jak mam udělat aby to bylo prehlednejsi, jako kdyz sem vsichni pisi programy, dekuju moc....

 
Nahoru Odpovědět
23.11.2015 12:13
Avatar
Odpovídá na Tomas
Libor Šimo (libcosenior):23.11.2015 12:36

kód uzatvoríš do:

Nahoru Odpovědět
23.11.2015 12:36
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Odpovídá na Tomas
Libor Šimo (libcosenior):23.11.2015 13:50
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char buffer[128];
    int stav;
    char c, pokracovat;
    int i, j, pom_b, pom_c, velkost;

    for (;;) {
        stav = 0;
        pom_b = 0;
        pom_c = 0;
        printf("Zadajte slovo na kontrolu: ");
        fflush(stdin);
        scanf("%s", buffer);
        velkost = strlen(buffer);
        for (i = 0; i < velkost; i++) {
            c = buffer[i];
            switch(stav) {
                case 0:
                    if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 1: // a
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (c == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 2: // b
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'b' || buffer[i] == 'c')
                        stav = 5;
                    else if (buffer[i] == 'a')
                        stav = 1;
                    break;
                case 3: // c
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 2) {
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }
                    else if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
            }
        }
        if (stav == 4)
            printf("\nSlovo preslo, b = %d, c = %d, tav = %d\n", pom_b, pom_c, stav);
        else
            printf("\nSlovo nepreslo, b = %d, c = %d, stav = %d\n", pom_b, pom_c, stav);
        printf("\nPre nove zadanie stlacte y: ");
        fflush(stdin);
        pokracovat = getch();
        if (pokracovat == 'y') {
            system("cls");
        }
        else {
            putchar('\n');
            break;
        }
    }

    return 0;
}
Nahoru Odpovědět
23.11.2015 13:50
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Tomas
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Tomas:23.11.2015 15:07

Dekuju moc a k cemu je ten prikaz flush(stdin);? A poslu jsem ten Tvuj program kterej sem trochu upravil aby vic vyhovoval zadani a prosím kam ma dopsat ze kdyz prijde jiny znak nez a,b,c tak se program ukonci... diky moc

 
Nahoru Odpovědět
23.11.2015 15:07
Avatar
Odpovídá na Tomas
Libor Šimo (libcosenior):23.11.2015 15:33

Vyprázdni buffer, aby ti tam neostal visieť znak '\n' - teda enter.
"kdyz prijde jiny znak nez a,b,c" to zvládneš aj sám. Všade sú tam len podmienky.

Nahoru Odpovědět
23.11.2015 15:33
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Tomas
Člen
Avatar
Tomas:23.11.2015 16:00
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char buffer[128];
    int stav;
    char c;
    int i, j, pom_b, pom_c, velkost;
printf("Zadajte slovo na kontrolu: ");

    for (;;) {
        stav = 0;
        pom_b = 0;
        pom_c = 0;

        fflush(stdin);
        scanf("%s", buffer);
        velkost = strlen(buffer);
        for (i = 0; i < velkost; i++) {
            c = buffer[i];
            switch(stav) {
                case 0:
                    if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 1: // a
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (c == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 2: // b
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'b' || buffer[i] == 'c')
                        stav = 5;
                    else if (buffer[i] == 'a')
                        stav = 1;
                    break;
                case 3: // c
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 2) {
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }

                    else if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
            }
        }
        if (stav == 4)
            printf("\jste ve stavu, %d\n ktery je konecny", stav);
        else if(stav==5){printf("error");}
        else
            printf("\njste ve stavu, stav = %d\n ktery neni konecny",  stav);

        fflush(stdin);


    }

    return 0;
}

Akorat este nevim jak to udelat, ze kdyz mi prijdou 3 c aby to slo do erroru diky moc

 
Nahoru Odpovědět
23.11.2015 16:00
Avatar
Tomas
Člen
Avatar
Tomas:23.11.2015 17:04

To s tema trema c se mi podařilo vyřešit, ale ta podminka aby to bralo jenom znaky abc se mi prod nedari.... a zda se mi to, nebo ten stav 1 (a) je tam uplne zbytecne?

 
Nahoru Odpovědět
23.11.2015 17:04
Avatar
Tomas
Člen
Avatar
Tomas:23.11.2015 17:07
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char buffer[128];
    int stav;
    char c;
    int i, j, pom_b, pom_c, velkost;
printf("Zadajte slovo na kontrolu: ");


    for (;;) {
        stav = 0;
        pom_b = 0;
        pom_c = 0;

        fflush(stdin);
        scanf("%s", buffer);
        velkost = strlen(buffer);
        for (i = 0; i < velkost; i++) {
            c = buffer[i];
            switch(stav) {
                case 0:
                    if (buffer[i] == 'a')
                        stav = 0;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 1: // a
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'a')
                        stav = 1;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (c == 'c') {
                        pom_c++;
                        stav = 3;
                    }
                    break;
                case 2: // b
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 1) {
                        stav = 4;
                    }
                    else if (buffer[i] == 'b' || buffer[i] == 'c')
                        stav = 5;

                    break;
                case 3: // c
                    if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'a' && i == velkost - 2) {
                        stav = 4;
                    }
                    else if (pom_b >= 1 && pom_c <= 3 && buffer[i] == 'c' && i == velkost - 2) {
                        pom_c++;
                        stav = 4;
                    }

                    else if (buffer[i] == 'a')
                        stav = 3;
                    else if (buffer[i] == 'b') {
                        pom_b++;
                        stav = 2;
                    }
                    else if (buffer[i] == 'c') {
                        pom_c++;
                        stav = 3;
                    }

                    break;
                }
                if(pom_c>3){stav=5;}


        }
        if (stav == 4)
            printf("\jste ve stavu, %d\n ktery je konecny", stav);
        else if(stav==5){printf("error");}

        else
            printf("\njste ve stavu %d\n ktery neni konecny",  stav);

        fflush(stdin);


    }

    return 0;
}

Ze ten stav 1 myslim ze je zbytecny v tom co jsem upravil jako posledni a to je tenhle

 
Nahoru Odpovědět
23.11.2015 17:07
Avatar
Tomas
Člen
Avatar
Tomas:23.11.2015 17:08

A myslel jsem case 1 :)

 
Nahoru Odpovědět
23.11.2015 17:08
Avatar
Odpovídá na Tomas
Libor Šimo (libcosenior):23.11.2015 17:31

Robil som to popri svojej práci, teraz to už je na tebe. Uprav si to, ako potrebuješ.
Najlepší spôsob je nechať si vypisovať čo sa priebežne deje.
Napríklad:
vypisoval by som výsledky po každom písmene. To ti môže ukázať cestu, ako to upraviť.
V každom case by som pre break; dal asi toto:

printf("znak = %c, b = %d, c = %c, stav = %d\n", buffer[i], pom_b, pom_c, stav);

Vyskúšaj to.

Nahoru Odpovědět
23.11.2015 17:31
Aj tisícmíľová cesta musí začať jednoduchým krokom.
Avatar
Tomas
Člen
Avatar
Odpovídá na Libor Šimo (libcosenior)
Tomas:23.11.2015 17:36

Me to prijde taky lepsi, ale nas ucitel je hodne pedant na to aby to vypadalo jako v zadani.... a kam ma dat tu podminku, aby to prijimalo jenom znaky abc? a kdyz budou jiny tak se ukonci program... ja totis ani nevim jaky je prikaz k ukonceni programu...

 
Nahoru Odpovědět
23.11.2015 17:36
Děláme co je v našich silách, aby byly zdejší diskuze co nejkvalitnější. Proto do nich také mohou přispívat pouze registrovaní členové. Pro zapojení do diskuze se přihlas. Pokud ještě nemáš účet, zaregistruj se, je to zdarma.

Zobrazeno 25 zpráv z 25.