Как мне добавить «(если)», который позволяет только буквы между af ||AF? - PullRequest
0 голосов
/ 27 апреля 2019

Я написал программу, которая выполняет преобразование из шестнадцатеричного в десятичное. все, что мне осталось, это проверить, находится ли char между a - f или A - F, может быть, 0 - 9. если между ними нет, будет напечатано "Illegal input".

Мой код:

int n, i;
char currentDigit;
unsigned long int sum, currentDigitInt;

printf("Enter the number of digits in the Hexadecimal number:");
scanf_s("%d", &n);
sum = 0;

printf("Enter the Hexadecimal number:\n");
for (i = n - 1; i >= 0; i--) {
    scanf_s(" %c", &currentDigit);

    if (currentDigit >= 'a') {
        currentDigitInt = (currentDigit - 'a') + 10;
    }
    else if (currentDigit >= 'A') {
        currentDigitInt = (currentDigit - 'A') + 10;
    }
    else
        currentDigitInt = currentDigit - '0';
    sum += currentDigitInt * pow(16, i);
}

printf("The decimal number is: %u", sum);

Вывод мне нужен:

Enter the number of digits in the Hexadecimal number: 2
Enter the Hexadecimal number: QQ
Illegal input

Ответы [ 4 ]

2 голосов
/ 27 апреля 2019

Есть несколько проблем с кодом.

Для начала функция scanf_s должна включать в качестве параметра размер буфера для спецификатора формата c.

Для вывода объекта типа unsigned long необходимо использовать спецификатор формата ul.

В этих операторах if вы не проверяете верхний предел действительных буквенно-шестнадцатеричных цифр.

if (currentDigit >= 'a') {
    currentDigitInt = (currentDigit - 'a') + 10;
}
else if (currentDigit >= 'A') {
    currentDigitInt = (currentDigit - 'A') + 10;
}

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

Вот демонстрационная программа, которая показывает, как это можно сделать.

//Microsoft (R) C/C++ Optimizing Compiler Version 19.00.23506 for x64

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

int hex_digit( char c )
{
    const char *alpha = "ABCDEF";

    unsigned char c1 = toupper( ( unsigned char )c );
    const char *p;

    int result = -1;

    if ( '0' <= c1 && c1 <= '9' )
    {
        result = c1 - '0';
    }
    else if ( c1 != '\0' && ( p = strchr( alpha, c1 ) ) != NULL )
    {
        result = *p - alpha[0] + 10;
    }
    return result;
}

int main(void)
{
    const unsigned long HEX_BASE = 16;
    unsigned int n;

    printf( "Enter the number of digits in the Hexadecimal number: " );
    scanf_s("%u", &n); 

    unsigned long sum = 0;

    if ( n )
    {            
        printf( "Enter the Hexadecimal number: " );

        unsigned int i = 0;
        for ( ; i < n; i++ )
        {
            char c;

            scanf_s( " %c", &c, 1 );

            int digit = hex_digit( c );

            if ( digit < 0 ) break;
            else sum = sum * HEX_BASE + digit; 
        }

        if ( i == n )
        {
            printf("The decimal number is: %ul\n", sum);
        }
        else
        {
            puts( "Illegal input" );
        }    
    }

    return 0;
}

Его вывод может выглядеть следующим образом

Enter the number of digits in the Hexadecimal number: 8
Enter the Hexadecimal number: ffFFffFF
The decimal number is: 4294967295l

Если вы хотите, вы можете добавить в программу проверку, что указанное число введенных шестнадцатеричных цифр не превышает 2 * sizeof( unsigned long ).

0 голосов
/ 27 апреля 2019

a (A) до f (F) не обязательно должны быть последовательными в C.

Если вы хотите, чтобы ваша программа работала на всех реализациях C (klingon space-ship, DS9K , Mars Rover, ..., ...), вы можете попробовать что-то вроде этого

if ((currentdigit == 0) || (strchr("0123456789abcdefABCDEF", currentdigit) == NULL)) /* invalid */;
0 голосов
/ 27 апреля 2019

В вашем коде есть несколько проблем:

  • Вы можете проверить диапазоны символов с помощью оператора &&.Например:

    if (currentDigit >= 'a' && currentDigit <= 'f')
    
  • вы объединяете эти тесты в серию if / else и жалуетесь, если ни один из тестов не соответствует.

  • также отметим, что выражение для sum также неверно.sum += currentDigitInt * pow(16, i); должно быть;

    sum = sum * 16 + currentDigitInt;
    
  • формат printf для unsigned long равен %lu, а не %u.

  • вам следует проверить возвращаемое значение scanf_s, чтобы правильно определить потенциальный конец файла.

  • scanf_s ожидает 2 дополнительных аргумента для спецификатора преобразования %c и может не иметь значениядоступно во всех системах.

  • также обратите внимание, что вам не нужно запрашивать количество шестнадцатеричных цифр, просто вырвитесь из цикла, когда введенный символ является новой строкой во второй раз.

Вот исправленная версия:

#include <stdio.h>

int main() {
    int currentDigit;
    unsigned long int sum;
    int invalid = 0;

    printf("Enter the Hexadecimal number: ");
    sum = 0;
    while ((currentDigit = getchar()) ! EOF && currentDigit != '\n') {
        int currentDigitInt;
        if (currentDigit >= 'a' && currentDigit <= 'f') {
            currentDigitInt = (currentDigit - 'a') + 10;
        } else
        if (currentDigit >= 'A' && currentDigit <= 'F') {
            currentDigitInt = (currentDigit - 'A') + 10;
        } else
        if (currentDigit >= '0' && currentDigit <= '9') {
            currentDigitInt = currentDigit - '0';
        } else {
            invalid = 1;
            continue;     // keep scanning the input until end of line
        }
        sum = sum * 16 + currentDigitInt;
    }
    if (invalid) {
        printf("Invalid input\n");
    } else {
        printf("The decimal number is: %lu\n", sum);
    }
    return 0;
}

Примечания:

  • Стандарт C гарантирует, что 0 - 9 являются последовательными, но пуристы утверждают, что буквы от a до f и A до F могут не быть последовательными для набора символов выполнения.Несмотря на то, что они правильны, затенение программистов-новичков этими соображениями является контрпродуктивным и довольно чрезмерным, поскольку эти диапазоны символов являются последовательными как в ASCII, так и в EBCDIC (промежутки в EBCDIC находятся между i и j и между r и s в обоих случаях).
0 голосов
/ 27 апреля 2019
#include <stdio.h>
#include <ctype.h>
#include <string.h>

int isaTof(int c)
{
    c = toupper(c);

    if(c >= 'A' && c <= 'F') return 1;
    return 0;
}


int isin(int c, const char *allowedchars)
{
    return strchr(allowedchars, c) != NULL;
}

int isHEXNumber(const char *number)
{
    const char allowedchars[] = "abcdefABCDEF0123456789";
    while(*number)
    {
        if(!isin(*number++, allowedchars)) return 0;
    }
    return 1;
}

или версия для придирки

int isHEXNumber(const char *number)
{
    const char allowedchars[] = "abcdefABCDEF0123456789";

    if(!number || |*number) return 0;
    while(*number)
    {
        if(!isin(*number++, allowedchars)) return 0;
    }
    return 1;
}



int main()
{
    const char allowedchars[] = "abcdefABCDEF0123456789";

    printf("%s\n", isin('d', allowedchars) ? "Yes" : "No");

    return 0;
}
...