NOVINKA - Online rekvalifikační kurz Python programátor. Oblíbená a studenty ověřená rekvalifikace - nyní i online.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Diskuze – Delcom - Ukázka stavového automatu v C

Zpět

Upozorňujeme, že diskuze pod našimi online kurzy jsou nemoderované a primárně slouží k získávání zpětné vazby pro budoucí vylepšení kurzů. Pro studenty našich rekvalifikačních kurzů nabízíme možnost přímého kontaktu s lektory a studijním referentem pro osobní konzultace a podporu v rámci jejich studia. Toto je exkluzivní služba, která zajišťuje kvalitní a cílenou pomoc v případě jakýchkoli dotazů nebo projektů.

Komentáře
Avatar
David Novák
Tvůrce
Avatar
Odpovídá 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 :)

Editováno 24.2.2015 18:28
Odpovědět
24.2.2015 18:27
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.

Odpovědět
24.2.2015 18:30
Chyba je mezi klávesnicí a židlí.
Avatar
David Novák
Tvůrce
Avatar
Odpovídá 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ů ;)

Odpovědět
25.2.2015 15:44
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovídá 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.

 
Odpovědět
26.2.2015 18:56
Avatar
David Novák
Tvůrce
Avatar
Odpovídá 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..

Odpovědět
26.2.2015 20:48
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovídá 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.

 
Odpovědět
26.2.2015 21:14
Avatar
David Novák
Tvůrce
Avatar
Odpovídá 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

Odpovědět
26.2.2015 21:36
Chyba je mezi klávesnicí a židlí.
Avatar
tomisoka
Tvůrce
Avatar
Odpovídá 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.

 
Odpovědět
26.2.2015 22:01
Avatar
David Novák
Tvůrce
Avatar
Odpovídá 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í.. ;)

Odpovědět
26.2.2015 22:32
Chyba je mezi klávesnicí a židlí.
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 9 zpráv z 19.