Visualizzazione dei risultati da 1 a 7 su 7
  1. #1
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475

    [C++] Leggere stringa che rappresenta comandi

    Sto provando un nuovo problema di UVA, il 337.

    In sostanza, al programma viene passato sullo standard input un file che rappresenta un misto di comandi e di testo che deve essere inserito su una specie di terminale. I comandi sono introdotti dal carattere ^. Sono tutti lunghi 2 caratteri (^ seguito da una lettera che da il comando), a parte uno che è lungo 3 caratteri (^ seguito da 2 cifre).

    Il file è costituito da un numero che indica il numero di linee di input che seguono.

    Il mio è un problema di design, sulla lettura dell'input. Come dovrei leggerlo? E' possibile che l'input contenga degli spazi, quindi dovrò usare gets immagino.

    Non sapendo la lunghezza delle stringhe, come dovrei leggerlo? Pensavo di dichiarare un array di 3 caratteri e riempirlo leggendo un carattere alla volta da cin, non sapendo quanto può essere lunga ogni riga di input.

    Avete per caso qualche consiglio? Grazie...
    "Let him who has understanding reckon the number of the beast, for it is a human number.
    Its number is rw-rw-rw-."

  2. #2
    Utente bannato
    Registrato dal
    Feb 2004
    Messaggi
    2,803
    codice:
    #include<stdio.h>
    #include<string.h>
    #include<stdlib.h>
    #define isInteger(a) ((a>47&&a<57) ? (1) : (0))
    int getCommand(char com, char opz='.'){
        printf("%c\n\n",com);
        
        if(com=='b');
        if(com=='c');
        if(com=='d');
                            
        if(opz!='.'){} 
        }
    
    
    int main (){
        char a[128],c,num;
        int i;
    // la variabile a contiene la riga (fgets())
        while(scanf("%s",&a)!=0){
                                num=sprintf(NULL,"%s",a); 
                                i=0;
                                for(c=a[i];i<num;i++){
                                          if(a[i]=='^'){
                                                        if(isInteger(a[i+1]))
                                                        getCommand(a[i+1],a[i+2]);
                                                        else
                                                        getCommand(a[i+1]);            
                                                        }
                                                      }
                                
                                 }
              
        }
    ti ho fatto la parte che intercetta i comandi, è un pò macchinosa ma semplice da capire anche se sei alle prime armi
    sinceramente molti comandi parlano di spostare il cursore di righe o colonne, non mi viene in mente niente..quindi il programma è in pieno cantiere

  3. #3
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Sarà molto imbarazzante per me confessare che non ho capito il tuo codice xD

    In compenso il mio codice funzionare a parte che per un solo comando, quello che sposta il cursore alle coordinate (^##).

    codice:
    void ExecCommand()
    {
        //Una volta letto il ^ che introduce il comando
        //leggo il carattere che rappresenta il comando
        cin.get(ch);
    
        if (isdigit(ch))
        {
            //Se il carattere trovato è un numero, allora
            //il comando è ^##, perciò leggo un altro carattere
            //che rappresenta la seconda coordinata
    
            char ch2;
            cin.get(ch2);
    
            //Sposto il cursore alle coordinate lette
            MoveCursor(ch, ch2);
        }
        else { //altri comandi semplici }
    }
    Questo comando viene eseguito senza problemi, MA: qualsiasi (qualsiasi) cosa venga scritta dopo questo comando causa un segmentation fault. Tutti i comandi funzionano alla perfezione. Notare che se eseguo questo comando non ricevo il sigsev.

    Esempio:
    codice:
    ^11
    funziona, ma
    codice:
    ^11helloworld
    va in segmentation fault.

    Sotto c'è il codice completo:

    codice:
    #include <iostream>
    #include <ctype.h>
    
    using namespace std;
    
    void ExecCommand();
    void Output(char c);
    void outIns(char c);
    void outOW(char c);
    void MoveCursor(int x, int y);
    void ClampCursor();
    void cls();
    void EraseLine();
    void PrintTerminal();
    
    typedef enum OutputMode { insert, overWrite } OutputMode;
    
    char scrBoxPart[] = "+----------+";
    
    const int screenHeigth = 10;
    const int screenWidth = 10;
    
    int testCase = 0;
    
    int cursorX;
    int cursorY;
    
    char** screen;
    char ch;
    
    OutputMode outMode;
    
    int main()
    {
        int lnNumber, lnCount;
    
        //Creates screen
        screen = new char*[screenHeigth];
        for (int i = 0; i < screenHeigth; i++)
            screen[i] = new char[screenWidth];
    
        //and clears it.
        cls();
    
        //Keeps running until the end of the file
        while (true)
        {
            //resets the terminal.
            testCase++;
            lnNumber = lnCount = 0;
            cursorX = cursorY = 0;
            outMode = overWrite;
            cls();
    
            //Reads the number of input lines
            //and exits if there is no data to process
            cin >> lnNumber;
            if (!lnNumber) return 0;
            cin.get(ch);
    
            //Keeps processing data until all
            //the lines have been processed.
            while (lnCount < lnNumber)
            {
    
                //Reads a char
                cin.get(ch);
    
                switch (ch)
                {
                    case '^':
                        //it's a command
                        ExecCommand();
                        break;
                    case '\n':
                        //end of line
                        lnCount++;
                        break;
                    default:
                        //ch has to be output
                        Output(ch);
                        break;
                }
            }
    
            PrintTerminal();
        }
    
        return 0;
    }
    
    //Executes the commands
    void ExecCommand()
    {
        cin.get(ch);
    
        /*If the command is a digit, the command
        is in the form ^##, so you have to read the
        second digit to have the full command*/
        if (isdigit(ch))
        {
            char ch2;
            cin.get(ch2);
    
            //Moves the cursor
            MoveCursor(ch, ch2);
        }
        else
        {
            //Runs the proper command.
            switch (ch)
            {
                case 'b':
                    //move to line beginning
                    MoveCursor(0, cursorY);
                    break;
                case 'c':
                    cls();
                    break;
                case 'd':
                    //move down
                    MoveCursor(cursorX, (cursorY + 1));
                    break;
                case 'e':
                    //erase everything at the right of the cursor
                    EraseLine();
                    break;
                case 'h':
                    //move to the top left corner
                    MoveCursor(0, 0);
                    break;
                case 'i':
                    //enters insert mode
                    outMode = insert;
                    break;
                case 'l':
                    //move left
                    MoveCursor((cursorX - 1), cursorY);
                    break;
                case 'o':
                    //enters overwrite mode
                    outMode = overWrite;
                    break;
                case 'r':
                    //move right
                    MoveCursor((cursorX + 1), cursorY);
                    break;
                case 'u':
                    //move up
                    MoveCursor(cursorX, (cursorY - 1));
                    break;
                case '^':
                    //print a ^
                    Output('^');
                    break;
            }
        }
    }
    
    //Prints a character to the screen
    void Output(char c)
    {
        switch (outMode)
        {
            case insert:
                outIns(c);
                break;
            case overWrite:
                outOW(c);
                break;
        }
    }
    
    void MoveCursor(int x, int y)
    {
        cursorX = x;
        cursorY = y;
    
        ClampCursor();
    }
    
    //Clamps the cursor to the screen
    void ClampCursor()
    {
        if (cursorX < 0) cursorX = 0;
        if (cursorX > (screenWidth - 1)) cursorX = (screenWidth - 1);
        if (cursorY < 0) cursorY = 0;
        if (cursorY > (screenHeigth - 1)) cursorX = (screenHeigth - 1);
    }
    
    void cls()
    {
        for (int y = 0; y < screenHeigth; y++)
            for (int x = 0; x < screenWidth; x++)
                screen[y][x] = ' ';
    }
    
    void EraseLine()
    {
        for (int x = cursorX; x < screenWidth; x++)
            screen[cursorY][x] = ' ';
    }
    
    void outIns(char c)
    {
        for (int x = screenWidth - 1; x > cursorX; x--)
        {
            screen[cursorY][x] = screen[cursorY][x - 1];
        }
    
        screen[cursorY][cursorX] = c;
    
        MoveCursor((cursorX + 1), cursorY);
    }
    
    void outOW(char c)
    {
        screen[cursorY][cursorX] = c;
        MoveCursor((cursorX + 1), cursorY);
    }
    
    void PrintTerminal()
    {
        cout << "Case " << testCase << endl;
        cout << scrBoxPart << endl;
    
        for (int y = 0; y < screenHeigth; y++)
        {
            cout << '|' << screen[y] << '|' << endl;
        }
    
        cout << scrBoxPart << endl;
    }
    "Let him who has understanding reckon the number of the beast, for it is a human number.
    Its number is rw-rw-rw-."

  4. #4
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    [Magari non interessa a nessuno]

    Era come al solito una stupidata (degna di un programmatore stupido xD):

    codice:
    if (isdigit(ch))
        {
            char ch2 = 0;
            cin.get(ch2);
    
            //Moves the cursor
            MoveCursor(ch, ch2);
        }
    se sul terminale mi scrivono ^12, ad esempio, viene letto il codice ascii di 1 e di 2, e non 1 e 2 stessi. Quindi il programma cerca di muovere il cursore a 48 e a 49, non 1 e 2. La correzione è:

    codice:
    MoveCursor( (ch - 48), (ch2 - 48) );
    Mettiamo che serva a qualcuno :P
    "Let him who has understanding reckon the number of the beast, for it is a human number.
    Its number is rw-rw-rw-."

  5. #5
    Utente bannato
    Registrato dal
    Feb 2004
    Messaggi
    2,803
    il 99% dei segmentation fault di tutto il mondo sono accessi illegali

    l'hai mandato?
    a me per altri problemi dà sempre responso negativo, anche quando i programmi sono super-testati...

  6. #6
    Consiglio: sempre provare i programmi con valgrind per vedere se ci sono problemi (anche non evidenti) legati ad accessi alla memoria. Vi assicuro che fa miracoli.
    Amaro C++, il gusto pieno dell'undefined behavior.

  7. #7
    Utente di HTML.it
    Registrato dal
    May 2008
    Messaggi
    475
    Non l'ho ancora inviato perchè ha ancora dei piccoli bug (il file di input che c'è nella pagina non viene eseguito correttamente, e finchè non riesco a far andare almeno quello non invio).

    Quando torno do un'occhiata a valgrind, in questi giorni ero un po' preso. Ho il mio primo esame universitario tra 40 minuti :S
    "Let him who has understanding reckon the number of the beast, for it is a human number.
    Its number is rw-rw-rw-."

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.