Mikuláš je tu! Získaj 90 % extra kreditov ZADARMO s promo kódom CERTIK90 pri nákupe od 1 199 kreditov. Len do nedele 7. 12. 2025! Zisti viac:
NOVINKA: Najžiadanejšie rekvalifikačné kurzy teraz s 50% zľavou + kurz AI ZADARMO. Nečakaj, táto ponuka dlho nevydrží! Zisti viac:

Diskusia – Delcom - Ukážka stavového automatu v C

Späť

Upozorňujeme, že diskusie pod našimi online kurzami sú nemoderované a primárne slúžia na získavanie spätnej väzby pre budúce vylepšenie kurzov. Pre študentov našich rekvalifikačných kurzov ponúkame možnosť priameho kontaktu s lektormi a študijným referentom pre osobné konzultácie a podporu v rámci ich štúdia. Toto je exkluzívna služba, ktorá zaisťuje kvalitnú a cielenú pomoc v prípade akýchkoľvek otázok alebo projektov.

Komentáre
Posledné komentáre sú na spodnej časti poslednej stránky.
Avatar
David Novák
Tvůrce
Avatar
Odpovedá na tomisoka
David Novák:24.2.2015 18:27

Jop.. Právě teď jsem to řešil.. ;)

C89 to bere, C99 a výš to bere jako řádkový komentář..
V článku jsem to opravil, ale zatím to čeká na schválení.

Vlastně jsem to od vydání docela dost upravil, protože jsem tam našel několik nedostatků.
Takže jsem to teď i přepsal, aby to počítalo s C89 vs C99 (nastavíš si argumentem při spuštění).

Práce se souborem je vynechaná úmyslně.. ;) Zkoušel jsem si u toho jak napsat skript v bashi, co projíždí soubory a přesměrovává je..

/******** delcom.c *********
 *
 * Autor: David Novák
 * Verze: 1.2
 * Datum: 23. 2. 2015
 * Pozn.: Program defaultně pracuje se standardem C99.
 *        Pokud chcete standard C89, spusťte ho s argumentem -c89.
 */

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

int main(int argc, char **argv)
{
  int std = 99;   // používaný standard Céčka (kvůli řádkovým komentářům)
  int stav = 0;
  int c;

  if (argc > 1)
    if (strcmp(argv[1], "-c89") == 0 || strcmp(argv[1], "-ansi") == 0)
      std = 89;

  while ((c = getchar()) != EOF)
  {
    switch(stav)
    {
      case 0:   // výchozí stav
        if (c == '/')
          stav = 1;
        else if (c == '"')
        {
          stav = 4;
          putchar('"');
        }
        else if (c == '\'')
        {
          stav = 6;
          putchar('\'');
        }
        else
          putchar(c);
        break;

      case 1:   // lomítko
        if (c == '*')
          stav = 2;
        else if (c == '/')
          if (std != 89)
            stav = 8;
          else
            putchar(c);
        else
        {
          stav = 0;
          putchar('/');
          putchar(c);
        }
        break;

      case 2:   // blokový komentář
        if (c == '*')
          stav = 3;
        break;

      case 3:   // hvězdička
        if (c == '/')
        {
          stav = 0;
          putchar(' ');
        }
        else if (c != '*')
          stav = 2;
        break;

      case 4:   // uvozovky - řetězcový literál
        if (c == '"')
          stav = 0;
        else if (c == '\\')
          stav = 5;
        putchar(c);
        break;

      case 5:   // zpětné lomítko
        putchar(c);
        stav = 4;
        break;

      case 6:   // apostrof
        if (c == '\'')
          stav = 0;
        else if (c == '\\')
          stav = 7;
        putchar(c);
        break;

      case 7:   // zpětné lomítko
        putchar(c);
        stav = 6;
        break;

      case 8:   // řádkový komentář
        if (c == '\n')
        {
          putchar('\n');
          stav = 0;
        }
        break;

    } // end_switch
  } // end_while

  if (stav != 0)
    fprintf(stderr, "Unknown error.\n");

  return 0;
}

Jinak čísla stavů v tomto kódě neodpovídají grafu.. A snad už tam konečně nejsou žádné chyby.. :D

A myslím, že pomocí stavového automatu je to o hodně čitelnější.. Zvlášť pro další osoby :)

Editované
Odpovedať
Chyba je mezi klávesnicí a židlí.
Avatar
David Novák
Tvůrce
Avatar
David Novák:24.2.2015 18:30

Graf pro tuto verzi.

Odpovedať
Chyba je mezi klávesnicí a židlí.
Avatar
David Novák
Tvůrce
Avatar
Odpovedá na tomisoka
David Novák:25.2.2015 15:44

Jinak ještě bych podotknul, že tvoje řešení bude při velkých množstvích textu o dost pomalejší - volání funkce není úplně triviální.. Musí se uložit obsah registrů na zásobník, načíst hodnoty, vykonat funkci a hodnoty ze zásobníku zase obnovit..

A.. V tom kódu se fakt vyznáš? o_O Nemáš to odsazené.. A ani tam nejsou mezery.. Louskal jsem to teda docela dlouho.. Jestli jo, tak klobouk dolů ;)

Odpovedať
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovedá na David Novák
tomisoka:26.2.2015 18:56

No tak jsem to ještě zkrátil a zbavil se funkcí ( to zpomalení mě nějak nenapadlo):

#include <stdio.h>
#include <stdint.h>

void delcom(FILE *inF, FILE*outF, uint32_t std){
  int in, ctrlC;
  uint32_t maxC, i;

  while((in=fgetc(inF))!=EOF){
    while(in=='/'){//while kvuli -c89 //komentare
      if((in=fgetc(inF))==EOF)break;
      if(in=='*'){
        while(in && (in=fgetc(inF))!=EOF){
          while(in=='*'){
            if((in=fgetc(inF))==EOF)break;
            if(in=='/')in=0;
          }
          if(in=='\n')fputc('\n', outF);
        }
      }else if(in=='/' && std!=89){
          while((in=fgetc(inF))!=EOF)if(in=='\n')break;
      }else
        fputc('/', outF);
    }

    if(in){
      fputc(in, outF);

      if(in == '\"' || in == '\''){// string/char
        i=0;
        ctrlC=in;
        maxC=ctrlC=='\''?1:-1;

        while((in=fgetc(inF))!=EOF && i<=maxC){
          fputc(in,outF);
          if(in==ctrlC)break;
          if(in=='\\'){
            if((in=fgetc(inF))==EOF)break;
            fputc(in,outF);
          }++i;
        }
      }
    }
  }
}

int main(int argc, char **argv){
  FILE *inF, *outF;
  uint32_t std=99;

  if(!(inF = fopen(argv[1], "r")))fprintf(stderr, "Input file cannot be open!\n");
  if(!(outF = fopen(argv[2], "w")))fprintf(stderr, "Output file cannot be open!\n");

  if (argc >= 4 && (strcmp(argv[3], "-c89") == 0 || strcmp(argv[3], "-ansi")) == 0)std = 89;

  delcom(inF, outF, std);

  fclose(inF);
  fclose(outF);

  return 0;
}

V tom tvém novém kódu je ještě chyba,
nechce odkomentovat "int i = 0/'a'/**/;".

A ano v tom mém kódu se vyznám, mezery dávám jen na oddělení nějakých odlišných částí, které nejsou už odděleny do bloků ({} nebo odsazení).
Tím "nemáš to odsazené" myslíš třeba toto?

if((in=fgetc(inF))==EOF)break;

pokud po if/while/for následuje jen 1 řádek tak to zkracuji do jednoho řádku.

Avatar
David Novák
Tvůrce
Avatar
Odpovedá na tomisoka
David Novák:26.2.2015 20:48

Pěkné :)
V tomhle už se dá i trochu snáze vyznat.. Ale i tak máš velmi zajámavý styl.. Ještě jsem se s nikým takovým nesetkal ;)
Nepsaný standard je za if psát mezeru a vykonávaný kód na další řádek + odsazení..

Každopádně klobouk dolů, že ti přijde takový komprimovaný kód přehledný.. ;) Otázka je, jestli by ses tak vyznal i v takovém cizím kódu.. ale jestli jo, tak respekt..

To s tou chybou.. To nechce odkomentovat tohle?

int i = 0/'a'/**/;

Nebo včetně uvozovek? Jestli je to v uvozovkách, tak by to tak mělo zůstat, jestli tohle, tak by to snad mělo vypsat:

int i = 0/'a';

Ale je dost možné, že tam mám chybu :D Jak bude čas, tak na to mrknu..

Odpovedať
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovedá na David Novák
tomisoka:26.2.2015 21:14

Bez těch uvozovek, v case 1 ti chybí ověření, jestli tam začíná string/char.

Avatar
David Novák
Tvůrce
Avatar
Odpovedá na tomisoka
David Novák:26.2.2015 21:36

Aha.. Jo už to vidím.. ;)

Jo.. ale to je tím, že to totiž není validní (pokud teda vím).. Překladač hodí error.. Proto jsem to neřešil a neošetřoval.. :) Takže taky hážu error :P

Odpovedať
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovedá na David Novák
tomisoka:26.2.2015 22:01

Proč by měl překladač házet error? Vždyť je to dělení čísla číslem.

Avatar
David Novák
Tvůrce
Avatar
Odpovedá na tomisoka
David Novák:26.2.2015 22:32

Hmm.. Zvláštní.. :D

Code::Blocks to nepustí, gcc z terminálu normálně jo.. Jinak jo.. máš pravdu ;) jsem už dneska nějaký odvařený a nedošlo mi hned, že 'a' je vlastně taky číslo.. :[

Jinak jsem teda ale ještě v praxi neviděl dělení znakem :D Takže zas tak zásadní to není.. ;)

Odpovedať
Chyba je mezi klávesnicí a židlí.
Posledné komentáre sú na spodnej časti poslednej stránky.
Robíme čo je v našich silách, aby bola tunajšia diskusia čo najkvalitnejšia. Preto do nej tiež môžu prispievať len registrovaní členovia. Pre zapojenie sa do diskusie sa zaloguj. Ak ešte nemáš účet, zaregistruj sa, je to zadarmo.

Zobrazené 9 správy z 19.