简体   繁体   English

如何在不使用 arrays 的情况下使用 C 中的 scanf 输入 integer?

[英]How to take integer input with scanf in C without using arrays?

I want to take input like the following:我想接受如下输入:

Write: 1 5 3写:1 5 3

OR或者

Write: 1 2写:1 2

OR或者

Write: 2 4 9 4写:2 4 9 4

OR或者

Write: (press Enter directly)写入:(直接回车)

However, problem is that I want to take max 5 integer or less.但是,问题是我想最多取 5 个 integer 或更少。 Therefore, I wrote this expression:因此,我写了这个表达式:

scanf("%d %d %d %d %d",&a,&b,&c,&d,&e);

When I did that, if I write integers, such as 1 4 6, the program continues to want integers until I complete the number of integers to 5.当我这样做时,如果我写整数,例如 1 4 6,程序将继续需要整数,直到我将整数的数目完成为 5。

Also, sometimes, I need to skip this part by pressing enter without writing an integer. But, I can not implement that.另外,有时,我需要在不写 integer 的情况下按 enter 来跳过这部分。但是,我无法实现它。

I did that also:我也这样做了:

 scanf("%d%c", &firstStore,&control);
    if(control==' ')
    {
        scanf("%d%c", &secondStore,&control);
        if(control==' ')
        {
            scanf("%d%c", &thirdStore,&control);
            if(control==' ')
            {
                scanf("%d%c", &fourthStore,&control);
                if(control==' ')
                {
                    scanf("%d", &fifthStore);
                }
            }
        }
    }

The problem with this code is that I can not skip this part if I want.这段代码的问题是,如果我愿意,我不能跳过这部分。 I mean this code wants to take minimum one integer always.我的意思是这段代码总是想要最少一个 integer。

RULE:规则:

The usage of arrays is banned.禁止使用 arrays。

I would suggest to get a whole line and then parse it:我建议得到一整行然后解析它:

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

int main() {
    char line[1024];
    if (fgets(line, 1024, stdin) == NULL) {
        perror("Error occured");
        return 2;
    }
    if (line[strlen(line)-1] != '\n') {
        while (getchar() != '\n');
    } else {
        line[strlen(line)-1] = '\0';
    }
    int counter = 0;
    for (char * word = strtok(line, " "); word; word = strtok(NULL, " ")) {
        int number = atoi(word);
        // do something with your number
        counter++;
    }
    if (counter == 0) {
        return 1;
    }
    return 0;
}

Like all of the other answers, the following solution violates the rule of not using arrays, because I cannot think of any clean solution to the problem which does not use them.像所有其他答案一样,以下解决方案违反了不使用 arrays 的规则,因为我想不出任何不使用它们的问题的干净解决方案。

The problem with using scanf is that it will treat spaces and newline characters equally.使用scanf的问题在于它将平等对待空格和换行符。 This is not what you want.这不是你想要的。

For line-based user input, it makes more sense to always read one line at a time, and treat every line individually.对于基于行的用户输入,始终一次读取一行并单独处理每一行更有意义。 In order to read one line of user input as a string, you can use the function fgets .为了将一行用户输入作为字符串读取,您可以使用 function fgets You can then convert this string to numbers using the function sscanf or strtol .然后,您可以使用 function sscanfstrtol将此字符串转换为数字。

Here is a solution that uses the function sscanf :这是一个使用 function sscanf的解决方案:

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

int main( void )
{
    for (;;) //infinite loop
    {
        char line[200];
        int numbers[5];
        int num_numbers;

        //prompt user for input
        printf( "Please enter up to 5 numbers: " );

        //attempt to read one line of input from user
        if ( fgets( line, sizeof line, stdin ) == NULL )
            break;

        //verify that line was not too long for input buffer
        if ( strchr( line, '\n' ) == NULL && !feof( stdin ) )
        {
            printf( "Line too long for input buffer!\n" );
            exit( EXIT_FAILURE );
        }

        //attempt to convert string to numbers
        num_numbers = sscanf(
            line,
            "%d %d %d %d %d",
            &numbers[0], &numbers[1], &numbers[2],
            &numbers[3], &numbers[4]
        );

        //print result
        if  ( num_numbers == 0 || num_numbers == EOF )
        {
            printf( "Was not able to match any numbers.\n" );
        }
        else
        {
            printf( "Successfully matched %d numbers:\n", num_numbers );
            for ( int i = 0; i < num_numbers; i++ )
            {
                printf( "%d\n", numbers[i] );
            }
        }
        printf( "\n" );
    }
}

This program has the following behavior:该程序具有以下行为:

Please enter up to 5 numbers: 20 30 35 40
Successfully matched 4 numbers:
20
30
35
40

Please enter up to 5 numbers: 
Was not able to match any numbers.

Please enter up to 5 numbers: 12 17
Successfully matched 2 numbers:
12
17

Please enter up to 5 numbers: 5
Successfully matched 1 numbers:
5

Here is a solution which uses the function strtol instead of sscanf :这是一个使用 function strtol而不是sscanf的解决方案:

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

#define MAX_NUMBERS 5

int main( void )
{
    for (;;) //infinite loop
    {
        char line[200], *p = line, *q;
        long numbers[MAX_NUMBERS];
        int num_numbers = 0;

        //prompt user for input
        printf( "Please enter up to 5 numbers: " );

        //attempt to read one line of input from user
        if ( fgets( line, sizeof line, stdin ) == NULL )
            break;

        //verify that line was not too long for input buffer
        if ( strchr( line, '\n' ) == NULL && !feof( stdin ) )
        {
            printf( "Line too long for input buffer!\n" );
            exit( EXIT_FAILURE );
        }

        //convert as many numbers as possible
        for ( int i = 0; i < MAX_NUMBERS; i++ )
        {
            numbers[i] = strtol( p, &q, 10 );
            if ( p == q )
                break;

            p = q;
            num_numbers++;
        }

        //print result
        if  ( num_numbers == 0 )
        {
            printf( "Was not able to match any numbers.\n" );
        }
        else
        {
            printf( "Successfully matched %d numbers:\n", num_numbers );
            for ( int i = 0; i < num_numbers; i++ )
            {
                printf( "%ld\n", numbers[i] );
            }
        }
        printf( "\n" );
    }
}

This second program has exactly the same output as the first program.第二个程序与第一个程序具有完全相同的 output。

Check the return value of scanf() .检查scanf()的返回值。

From the man page of scanf :scanf的手册页

On success, these functions return the number of input items successfully matched and assigned;成功时,这些函数返回成功匹配和分配的输入项数; this can be fewer than provided for, or even zero, in the event of an early matching failure.在早期匹配失败的情况下,这可能比规定的要少,甚至为零。

So your code should something like:?所以你的代码应该是这样的:?

#include <stdio.h>

int main(void)
{
    int n;

    while ((scanf("%d")) == 1) {
        /* perform actions */
    }


    return 0;
}

To implement the part in which you don't type anything, you have to use a function other than scanf() .要实现您不键入任何内容的部分,您必须使用 function 而不是scanf() Consider fgets() or getchar() .考虑fgets()getchar()

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

int main(void)
{
    int n;
    char buff[500];

    while (fgets(buff, sizeof buff, stdin) != NULL) {
        if (buff[0] == '\n') { /* empty - just newline character */
            continue;
        }

        if (sscanf(buff, "%d", &n) != 1) { /* unsuccessful conversion */
            exit(1);
        }

    }


    return 0;
}

This will work considering each line has a single number or you type a single number each time.考虑到每一行都有一个数字或您每次键入一个数字,这将起作用。 If your line has multiple numbers, you will have to parse it differently, possibly by using strtok() or by modifying sscanf() .如果你的行有多个数字,你将不得不以不同的方式解析它,可能通过使用strtok()或修改sscanf()

You can use the %n format and loop so you can check the whole string using sscanf() .您可以使用%n格式和循环,这样您就可以使用sscanf()检查整个字符串。

From the man page for %n :%n的手册页:

Nothing is expected;没有什么可期待的; instead, the number of characters consumed thus far from the input is stored through the next pointer, which must be a pointer to int, or variant whose size matches the (optionally) supplied integer length modifier.相反,到目前为止从输入中消耗的字符数通过下一个指针存储,该指针必须是指向 int 的指针,或者其大小与(可选)提供的 integer 长度修饰符匹配的变体。

So you could replace the if block with something like:所以你可以用类似的东西替换 if 块:

    int char_read;
    int start = 0;

    while (start < sizeof(buff) && 
    sscanf(&buff[start], "%d%n", &n, &char_read) == 1) { /* 1 successful conversion */
        printf("%d\n", n);
        start += char_read;
    }

Working example工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM