Ошибки в коде (конечный автомат)

Я немного схожу с ума, пытаясь исправить этот код. Я был на этом почти два часа, и я не могу найти, что не так.

Это простая программа, которая должна принимать некоторый текст в качестве входных данных и возвращать один и тот же текст со всеми числами, переключенными с десятичного на шестнадцатеричное основание.

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

int revNumber(int);

typedef enum { STATE_WORD, STATE_BLANK, STATE_NUMBER } state_t;

int main()
{
    int c;
    int readNum = 0;
    int writeNum = 0;
    int digit = 1;
    int sign = 1;

    state_t state = STATE_BLANK;

    while( (c = getchar()) != EOF )
    {
        switch(state)
        {
            case STATE_WORD:
                if( isspace(c) )
                    state = STATE_BLANK;
                putchar(c);
                break;

            case STATE_BLANK:
                if(c == '-')
                {
                    sign = -1;
                    state = STATE_NUMBER;
                }
                else if( isdigit(c) )
                {
                    readNum += (c - '0') * digit;
                    digit *= 10;
                    state = STATE_NUMBER;
                }
                else if( isspace(c) )
                    putchar(c);

                else
                {
                    state = STATE_WORD;
                    putchar(c);
                }
                break;

            case STATE_NUMBER:
                if( isdigit(c) )
                {
                    readNum += (c - '0') * digit;
                    digit   *= 10;
                }
                else
                {
                    writeNum = revNumber(readNum);
                    readNum = 0;

                    if(sign == -1)
                        putchar('-');

                    if(digit > 1)
                    {
                        if( isspace(c) )
                        {
                            printf("%x", writeNum);
                            state = STATE_BLANK;
                        }
                        else
                        {
                            printf("%d", writeNum);
                            state = STATE_WORD;
                        }
                    }
                    digit = 1;
                    sign  = 1;
                    putchar(c);
                }
                break;
        }
    }
}


int revNumber(int n)
{
    int revNum = 0;
    while(n != 0)
    {
        revNum += revNum * 10 + n%10;
        n   /= 10;
    }
    return revNum;
}

Программа, однако, не работает правильно, по какой-то причине я продолжаю неправильно конвертировать в hex. Почему это происходит? Большое спасибо.

3 ответа

Решение

Когда я печатаю 123 в командной строке ваша программа хранит внутренне: 1*1 + 2*10 + 3*100 = 321 который полностью изменен, хорошо. Но тогда ваша функция полностью изменить 321 возвращается 146 вместо 123, Там что-то определенно не так.

Я предлагаю посмотреть на это для начала:

http://www.programmingsimplified.com/c/source-code/c-program-reverse-number

Проблема в том, что эта строка:

revNum += revNum * 10 + n%10;

должно быть:

revNum = revNum * 10 + n%10;

Если вы собираетесь копировать-вставить функцию, вы должны по крайней мере убедиться, что она работает, прежде чем полагаться на нее в своем коде.

Следующий код фактически не дополняет число 2, поскольку шестнадцатеричные значения не имеют знака, только величина.

Тем не менее, это работает как ожидалось (для каждого тестового примера, который я использовал)

Он демонстрирует предпочтительную логику для обработки конечного автомата, включая то, как легко обрабатывать переходы состояний.

следующий код не меняет цифры в номере, вы можете легко добавить эту функцию, которая заменит вызов printf() в inNumber() функция

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

typedef enum { STATE_WORD, STATE_BLANK, STATE_NUMBER } state_t;


state_t inWord  ( char ch );
state_t inBlank ( char ch );
state_t inNumber( char ch );

int  number = 0;
char sign   = ' ';

state_t state = STATE_BLANK;


int main( void )
{
    int c;


    printf( "program will echo sentence with numeric sub strings output in hex format\n");
    printf( "Enter a sentence:");

    while( (c = getchar()) && (c != EOF) )
    {
        switch(state)
        {
            case STATE_WORD:
                state = inWord( c );
                break;

            case STATE_BLANK:
                state = inBlank( c );
                break;

            case STATE_NUMBER:
                state = inNumber( c );
                break;

            default:
                printf( "state machine contains invalid state\n");
                break;
        } // end switch

        if( '\n' == c )
        {
            break;
        }
    } // end while

    putchar( '\n');
    return 0;
} // end function: main


state_t inWord( char ch )
{
    state_t newState = STATE_WORD;

    if( isdigit( ch ) )
    {
        newState = inNumber( ch );
    }

    else
    {
        putchar( ch );
    }

    return newState;
} // end function: inWord


state_t inBlank( char ch )
{
    state_t newState = STATE_BLANK;

    if( isdigit( ch ) )
    {
        newState = inNumber( ch );
    }

    else if( isalpha( ch ) )
    {
        newState = inWord( ch );
    }

    else
    {
        putchar( ch );
    }

    return newState;
} // end function: inBlank


state_t inNumber( char ch )
{
    state_t newState = STATE_NUMBER;

    if( !isdigit( ch ) )
    {
        printf( "%X ", number );
        newState = inBlank( ch );
    }

    else
    {
        number *=10;
        number += ch-'0';
    }

    return newState;
} // end function: inNumber

Ваша функция разворота создает число, отличное от того, что было введено. Измените "+=" на "=", чтобы начать. поместите операторы print для readNum и writeNum после функции, и вы увидите проблемы

Функция также портится, если введенное число кратно 10. Вы можете вычислить эту часть.

Другие вопросы по тегам