Geek tričko zdarma Geek tričko zdarma
Tričko zdarma! Stačí před dobitím bodů použít kód TRIKO15. Více informací zde

Diskuze: Enumerátory

Aktivity (2)
Avatar
Elix Novel
Člen
Avatar
Elix Novel:13.10.2018 17:11

Ahoj, píšu program, který analyzuje slova z textu a řadí je do jednotlivých sekcí. Takže když zjistí, že je to klíčové slovo napíše: keyword "jméne klíčového slova", když zjistí, že je to oddělovač, identifikátor cokoliv - stejný princip.
Ale chtěl bych, aby program dokázal zjistit, že toto číslo je v hexadeximální soustavě a vypsal: number_hex "požadové číslo" a nejlépe rovnou v decimální soustavě.

Zkusil jsem: Načítám soubor přes StringBuilder čtu řádek po řádku a pomocí enumerátorů zjišťuji kam dané slovo patří.

KEYWORD_RETURN("return"),
SEPARATOR_ROVNITKO("="),
NUMBER_DEC("\\d+(\\.\\d+)?"),
NUMBER_HEX("0x"),

Potom ho vypisuji do konzole. Vše mi funguje jen to nedokáže identifikovat, že číslo je v hexadecimální soustavě.

Chci docílit: Výsledek by měl být takový, že program přes prefix "0x" v enumerátoru zjistí, že je číslo v hexadecimální soustavě a na obrazovku vypíše: number_hex"číslo převedené do dec".

 
Odpovědět 13.10.2018 17:11
Avatar
Jirka
Člen
Avatar
Odpovídá na Elix Novel
Jirka:13.10.2018 17:27

Ahoj,
co zkusit regulární výraz, jako "\b[0-9A-F]+\b".

Nahoru Odpovědět  +1 13.10.2018 17:27
Kdo nic nedělá, nic nezkazí.
Avatar
Samuel Kodytek
Šéfredaktor
Avatar
Samuel Kodytek:13.10.2018 17:28

Ahoj,

Nevím jestli jsem pochopil přesně čeho chceš docílit, ale pokud chceš zjistit jestli řádek obsahuje 0x a k tomu nějaké číslo a to následně převést z hexadecimální soustavy do decimální, použil bych regex . Pokud ve tvém souboru, víš že všechny tvé hexadecimální čísla budou začínat na 0x tak tvůj regex by mohl vypadat nějak tak to:

0x([0-9A-Fa-f]+)

V Javě s tím pak můžeš pracovat nějak tak to:

String mujRadek = "0x1F";

String hexRegex = "0x([0-9A-Fa-f]+)";
Pattern r = Pattern.compile(hexRegex);
Matcher m = r.matcher(mujRadek);

if(m.find()) {
     String hex = m.group().substring(2);
     System.out.println("HEX: " + hex);
     System.out.println("DEC: " + Integer.parseInt(hex, 16));
}
Nahoru Odpovědět  +1 13.10.2018 17:28
There is more than one way to screw it
Avatar
Jirka
Člen
Avatar
Odpovídá na Elix Novel
Jirka:13.10.2018 19:05

Nebo co třeba něco jako:

package itn.forum;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

public class Hex {
public static void main(String[] args) {
        List<String> los = new ArrayList<>();
        los.add(" 0x10 ");
        los.add(" 0x1f 0x16");
        los.add(" 0xzf ");
        los.add(" 0x0cblabla ");
        los.add(" 0x0c ");
        Pattern r = Pattern.compile("\\b0x([0-9A-Fa-f]{2,2})\\b");
        for(String s : los) {
                if(r.matcher(s).find()) { System.out.println(s + " => souhlasi"); }
        }
}
}
Nahoru Odpovědět  +1 13.10.2018 19:05
Kdo nic nedělá, nic nezkazí.
Avatar
Elix Novel
Člen
Avatar
Elix Novel:16.10.2018 11:05

Děkuji všem za pomoc, ale stále to není přesně to co hledám. Zkusím upřesnit svůj dotaz. Mám zadání naprogramovat lexikální analyzátor, kteýr bude zpracovávat text a pomocí tokenů vypisovat na obrazovku text.

  1. Musí rozeznávat klíčová slova (end,begin,if,whi­le,...)

2 ) Musí rozeznávat identifikátory (jakékoliv slovo)

  1. Musí rozeznávat DEC číslo
  2. Musí rozeznávat HEX číslo (s prefixem 0x) a převést ho ve výpisu do DEC
  3. Musí umět přeskakovat mezery (pokud jich je víc po sobě) - vždy zobrazí jen jednu
  4. Musí načítat jen slova s malým písmenem
  5. Délka klíčových slov a identifikátorů nesmí přesáhnout 32 znaků

Pustil jsem se do programování a myslím, že mi funguje vše kromě bodů: 4), 6), 7)..
Matlám se s tím strašně dlouho a pořád nic, tak jsem doufal, že tady mě to zachrání.

Main

    public static void main(String[] args) {
        try {
            Analyzator analyzator = new Analyzator("testFile.txt");
            while (!analyzator.jeVycerpano()) {
                System.out.printf("%s   %s\n", analyzator.currentToken(), analyzator.currentEnum());
                analyzator.cteniZnaku();
            }
        } catch (Exception e) {

        }
    }
}

Analyzator

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Stream;

/**
 *
 * @author Radek
 */
public final class Analyzator {

    private final int MAXIMALNI_DELKA = 32;
    private Token token;
    private String enumy;
    private StringBuilder stringBuilder = new StringBuilder();
    private static final Set<Character> prazdnaMista = new HashSet<Character>();
    private boolean vycerpano = false;

    public Analyzator(String file) {
        try (Stream<String> stream = Files.lines(Paths.get(file))) {

            stream.forEach(stringBuilder::append);

        } catch (IOException e) {
        }

        cteniZnaku();
    }

    static {
        prazdnaMista.add((char) 8);
        prazdnaMista.add((char) 9);
        prazdnaMista.add((char) 11);
        prazdnaMista.add((char) 12);
        prazdnaMista.add((char) 32);
    }

    private void preskakujMezery() {
        int mezery = 0;

        while (prazdnaMista.contains(stringBuilder.charAt(mezery))) {
            mezery++;
        }

        if (mezery > 0) {
            stringBuilder.delete(1, mezery);
        }
    }

    public void cteniZnaku() {
        if (stringBuilder.length() == 0) {
            vycerpano = true;
            return;
        }
        preskakujMezery();
        dalsiZnak();

    }

    private boolean dalsiZnak() {
        for (Token t : Token.values()) {
            int end = t.konecCteni(stringBuilder.toString());

            if (end != 0) {
                {
                    token = t;
                    enumy = stringBuilder.substring(0, end);
                    stringBuilder.delete(0, end);
                    return true;
                }
            }
        }

        return false;
    }

    public Token currentToken() {
        return token;
    }

    public String currentEnum() {
        return enumy;
    }

    public boolean jeVycerpano() {
        return vycerpano;
    }

}

Tokeny

import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 *
 * @author Radek
 */
public enum Token {
    KEYWORD_BEGIN("begin{0,33}"),
    KEYWORD_END("end{0,33}"),
    KEYWORD_FOR("for{0,33}"),
    KEYWORD_IF("if{0,33}"),
    KEYWORD_THEN("then{0,33}"),
    KEYWORD_ELSE("else{0,33}"),
    KEYWORD_WHILE("while{0,33}"),
    KEYWORD_RETURN("return{0,33}"),
    SEPARATOR_ROVNITKO("="),
    SEPARATOR_CARKA(","),
    SEPARATOR_DVOJTECKA(":"),
    SEPARATOR_STREDNIK(";"),
    NUMBER_DEC("\\d+"),
    NUMBER_HEX("\\b0x[0-9A-F]"),
    BLANK("\\s"),
    IDENTIFIER("\\w{0,33}");

    private final Pattern pattern;

    Token(String regex) {
        pattern = Pattern.compile("^" + regex);
    }

    int konecCteni(String string) {
        Matcher matcher = pattern.matcher(string);

        if (matcher.find()) {
            return matcher.end();
        }

        return 0;
    }
}

A ještě přiložím soubor se kterým pracuji:
testFile.txt

begin;

a,b=100;

c=0x10;

end;

Tak pokud by byl někdo ochotný mi poradit a pomoc to dotáhnout do konce, byl bych vděčný.

 
Nahoru Odpovědět 16.10.2018 11:05
Avatar
Unda
Člen
Avatar
Odpovídá na Elix Novel
Unda:16.10.2018 17:47

V druháku jsem to vyřešil tím, že jsem to načítal po znaku, nikoliv řádku a zjišťoval co je za 0. :))

 
Nahoru Odpovědět 16.10.2018 17:47
Avatar
patrik.valkovic
Šéfredaktor
Avatar
Odpovídá na Elix Novel
patrik.valkovic:16.10.2018 18:25

Pokud máš napsat lexikální analyzátor, tak bych řekl že tě s regulárními výrazy pošlou někam. Lexikální analyzátor využívá zpravidla regulárních jazyků a tedy stavových automatů. I když lze každý regulární výraz převést na stavový automat, jejich použití je v lexikálním analyzátoru nevhodné, protože jsou příliš pomalé. Pouvažuj nad tím, jestli to nechceš napsat pořádně :D

Nahoru Odpovědět 16.10.2018 18:25
Nikdy neumíme dost na to, abychom se nemohli něco nového naučit.
Avatar
Elix Novel
Člen
Avatar
Elix Novel:18.10.2018 10:25

Ale ve výsledku to vše funguje přesně podle zadání moc nerozumím jak bych to vlastně měl jinak přepsat. Koukám do toho každý den, ale bohužel jsem se moc neposunul..

 
Nahoru Odpovědět 18.10.2018 10:25
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 8 zpráv z 8.