Проверьте, являются ли все значения, введенные в массив символов, числовыми

#arrays #c #char

#массивы #c #символ

Вопрос:

У меня есть массив символов, где должны быть только числа (10 цифр). Если пользователь вводит буквы или специальные символы (даже среди этих цифр), программа должна снова предложить пользователю ввести число.

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

 int f = 1;
int i = 0;
int flag =1;
char num[11];
printf("Enter a number: ");

while (f == 1) {
    scanf("s", num);

    while (flag == 1 amp;amp; isdigit(num[i])) {
        i  ;
        if (i == 10) {
            f = 0;
            flag =0;
        }
    }

    if (!isdigit(num[i])) {
        printf("Enter numerical char: ");
    }
}       
 

После того, как я ввожу неверное значение, отображается пустая строка. Если я добавлю какое-либо значение в эту пустую строку, только тогда он скажет «Введите числовой символ:» и предложит снова ввести число.

PS Я знаю, что есть способ гарантировать, что вводятся только числовые значения, учитывая тот факт, что символы, в отличие от чисел, заключены в одинарные кавычки. (понятия не имею, как это сделать tbh)

Заранее спасибо!

Комментарии:

1. Где вы устанавливаете i значение 0?

2. Я предлагаю преобразовать строку с strtol() помощью, чтобы вы могли проверить символ, на котором остановилось преобразование, или strtoll() .

3. Я не уверен, что понял ваш вопрос. Я установил i в 0 в самом начале. @stark

4. Итак, что находится i на втором числе?

Ответ №1:

Есть несколько способов сделать это.

Простой способ — использовать fgets для получения строки.

Затем мы можем использовать strtol для декодирования числа [и мы проверяем конечный символ на достоверность].

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

Вот несколько примеров кода с комментариями, которые показывают оба способа:

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

// getstr -- get a string with prompt
// RETURNS: length or (<0 -> error)
int
getstr(char *buf,int buflen,const char *prompt)
{
    char *cp;
    int ret = 0;

    // NOTE: usage of the error codes in errno.h is arbitrary

    while (ret <= 0) {
        // ensure buffer has enough space
        if (buflen < 2) {
            ret = -ENOMEM;
            break;
        }

        // output prompt
        printf("%s: ",prompt);
        fflush(stdout);

        // get a line
        cp = fgets(buf,buflen,stdin);

        // EOF
        if (cp == NULL) {
            ret = -ENODATA;
            break;
        }

        // get buffer length
        ret = strlen(buf);

        // empty string
        if (ret <= 0)
            continue;

        // point to last char
        cp = amp;buf[ret - 1];

        // ensure we got a newline -- if not, fgets had to chop the line (i.e.)
        // the line is too long to fit in the buffer
        if (*cp != 'n') {
            ret = -ENOSPC;
            break;
        }

        // strip the newline -- we are done
        *cp = 0;
        --ret;
    }

    return ret;
}

// getnum_strtol -- get number using strtol
long
getnum_strtol(const char *prompt)
{
    int len;
    int readflg = 1;
    char *cp;
    char buf[100];
    long num = 0;

    while (readflg) {
        len = getstr(buf,sizeof(buf),prompt);

        if (len < 0)
            exit(1);

        num = strtol(buf,amp;cp,10);

        // ensure we got a least one digit
        if (cp <= buf)
            continue;

        switch (*cp) {
        case ' ':
        case 't':
        case 0:
            readflg = 0;
            break;
        default:
            printf("getnum_strtol: not a valid number -- buffer '%s', invalid '%s'n",
                buf,cp);
            break;
        }
    }

    return num;
}

// getnum_manual -- get number _not_ using strtol
long
getnum_manual(const char *prompt)
{
    int len;
    int readflg = 1;
    int sign = 0;
    int valid;
    int chr;
    char *cp;
    char buf[100];
    long num = 0;

    while (readflg) {
        len = getstr(buf,sizeof(buf),prompt);

        // fatal error
        if (len < 0)
            exit(1);

        // point to buffer start
        cp = buf;

        // find first non-whitespace character
        valid = 0;
        while (1) {
            chr = *cp;

            // end of string
            if (chr == 0)
                break;

            // found character
            valid = ((chr != ' ') amp;amp; (chr != 't'));
            if (valid)
                break;

              cp;
        }
        if (! valid)
            continue;

        // reset the accumlated number and the sign
        num = 0;
        sign = 0;
        valid = 0;

        // loop through all characters in buffer
        while (1) {
            chr = *cp  ;

            // get the sign of the number (and skip an explicit sign)
            if (sign == 0) {
                switch (chr) {
                case ' ':
                    sign = 1;
                    chr = *cp  ;
                    break;
                case '-':
                    sign = -1;
                    chr = *cp  ;
                    break;
                default:
                    sign = 1;
                    break;
                }
            }

            // stop decoding number on whitespace
            switch (chr) {
            case ' ':
            case 't':
                chr = 0;
                break;
            }

            // check for clean end of number
            if (chr == 0) {
                if (valid) {
                    readflg = 0;
                    break;
                }
            }

            // not a valid digit
            if (! isdigit((unsigned char) chr)) {
                cp -= 1;
                printf("getnum_manual: not a valid number -- buffer '%s', invalid '%s'n",
                    buf,cp);
                break;
            }

            // add digit to number
            num *= 10;
            chr -= '0';
            num  = chr;

            // we got at least one valid digit
            valid = 1;
        }
    }

    // apply sign
    num *= sign;

    return num;
}

int
main(int argc,char **argv)
{
    char *cp;
    int opt_s = 0;
    long num;

    // skip over program name
    --argc;
      argv;

    // get options
    for (;  argc > 0;  --argc,   argv) {
        cp = *argv;
        if (*cp != '-')
            break;

        cp  = 2;
        switch (cp[-1]) {
        case 's':  // use strtol
            opt_s = ! opt_s;
            break;
        }
    }

    while (1) {
        if (opt_s)
            num = getnum_strtol("Enter number [strtol]");
        else
            num = getnum_manual("Enter number [manual]");
        printf("The number entered is: %ldn",num);
        if (num == 999)
            break;
    }

    return 0;
}
 

Комментарии:

1. Незначительный: «если нет, fgets пришлось вырезать строку (т. Е.) // строка слишком длинная, чтобы поместиться в буфер» или был прочитан какой-то текст (не полный буфер), и fgets() результаты отображаются в конце файла.

Ответ №2:

Работа с вводом из stdin C может быть затруднительной. Я попытался объяснить, что нужно сделать в комментариях, сохраняя ваши переменные в том виде, в котором вы хотели, чтобы они использовались. Но мне нужно было добавить int ch , чтобы захватить входные данные stdin . Способ, которым я захватил ввод, ДАЛЕК! из идеального, но он иллюстрирует идею и делает то, что вам нужно. Но, чтобы улучшить ваш ответ, я бы предложил переместить его в собственную функцию. Кроме того, он игнорирует ввод цифр, превышающих 10 символов, поэтому, если, например, вы вводите 012345678901234567, он просто проигнорирует ввод после 10-й цифры, но все равно пройдет тест на ваши переменные и флаги. Комментарии должны быть понятны сами по себе. Я не проверял это, кроме как для того, чтобы убедиться, что он скомпилирован и один раз для цифр и один раз для цифр и текста, но идея есть, и вы должны иметь возможность расширить ее в соответствии с вашими требованиями.

 #include <ctype.h>
#include <stdio.h>
#include <stdlib.h> /* for fflush */

int main()
{
    int f = 1; /* set f on */
    int i = 0;
    int flag = 0; /* set flag OFF */
    char num[11];
    int ch; /* adding ch to read characters from stdin */
    
    printf("Enter a number: "); /* flush stdout if no newline */
    fflush(stdout);

    while(f == 1) {

        /* you need to read stdin to the newline */
        /* but not exceed the bounds of num */
        ch = fgetc(stdin);
        while(ch != 'n' amp;amp; ch != EOF) {
            if(i < 10) /* reusing your i variable that you set to 0, don't exceed 10 to save space for '' */
                num[i] = ch;
            i  ;
            ch = fgetc(stdin); /* get another character */
        }
        /* now add '' to terminate your string */
        /* but not beyond num[10] */
        if(i > 10) {
            num[10] = '';
        } else {
            num[i] = '';
        }
        
        /* now that we are done reading stdin reset i to 0 to restore how you had it */
        i = 0;
        
        /* lets test num working with your variables */
        while(num[i] != '' amp;amp; flag == 0) {
            /* test for digit at num[i] */
            if(!isdigit(num[i]))
                flag = 1; /* not a digit so set your flag variable on */
            i  ;
        }
        
        /* process your flag variable */
        if(flag == 0) { /* flag is off so everything is ok */
            f = 0; /* turn f off to exit loop */
        } else { /* flag is on, so get another number */
            printf("Enter numerical char: "); /* flush stdout if no newline */
            fflush(stdout);
            flag = 0; /* turn your flag variable back off */
            i = 0; /* reset i to 0 to check the next input */
        }
        
    }
    
    /* let's see what we got in num */
    printf("%sn", num);
    
    return 0;
}