C programming: print only int from fgets

元气小坏坏 提交于 2020-01-11 02:08:48

问题


See this main:

int main(void)
{
    int i;
    int ch;
    char str[512];
    fgets(str, sizeof str, stdin);

    for (i = 0; i <= (strlen(str)); i++)
    {
        if (str[i] != '\0' && str[i] != '\n')
        {
            int num = atoi(&str[i]);
            printf("%d\n", num);
        }
    }

    return 0;
}

I want to get line with numbers from user and get all the numbers without any spaces or tabs.

For example:

The input 1 2 3. But in this case this the output:

1
2
2
3
3

So why i received 2 and 3 twice?


回答1:


Here's how I would do it:

char line[256];
if (fgets(line, sizeof line, stdin) != NULL)
{
    const char *ptr = line;
    while (*ptr != '\0')
    {
        char *eptr = NULL;
        const long value = strtol(ptr, &eptr, 10);
        if (eptr != ptr)
            printf("%ld\n", value);
        else
            break;
        ptr = eptr;
    }
}

This uses strtol() so it will also handle negative numbers; if this is incorrect you can of course add checks to filter them out. I think this is way better than anything using strtok().




回答2:


Because the you also pass the position of the string which starts with spaces. they get the first number to be 2 and 3 respectively twice. That is what is returned.

for (i = 0; i <= (strlen(str)); i++)
{
    if (str[i] != '\0' && !isspace(str[i]) )
    {
        int num = atoi(&str[i]);
        printf("%d\n", num);
    }
}

Prints:

1
2
3

For the purpose of tokenizing you can use strtok and to convert it to number strtol etc. These provides much better control over the error cases than atol/atoi do.




回答3:


When it reaches the space character in the input it will call atoi() with " 2 3" (resulting in 2) and later on " 3" (resulting in 3) which creates the unexpected numbers.




回答4:


From the ref of atoi():

The function first discards as many whitespace characters (as in isspace) as necessary until the first non-whitespace character is found. [...]

That means that if you give as input to that function " 2", it will return 2.


Change this:

if (str[i] != '\0' && str[i] != '\n')

to this:

if (str[i] != ' ' && str[i] != '\0' && str[i] != '\n')

and you will get:

1
2
3

Here is a tip about debugging this code: In your output, you got 2 and 3 twice, but not 1.

In other words, you get the number that were after a space twice. 1 didn't have a space before it.

This should make you thing that there is something spooky about the spaces there.

Indeed, you would enter the body of the if statement, even if str[i] was a space!

By adding a condition to check if the current character is not a space, to enter the boby of the if statement, you actually skip the spaces.




回答5:


It is a good idea to always think of error handling. What if the user wrongly press space and tabs. So first remove spaces and tabs if exist :

char *c = string;
while ((*c == ' ') || (*c == '\t'))
    ++c;

and then use atoi().




回答6:


The solution with strtok isn't that hard either:

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

int main(void)
{
    char s[128];
    fgets(s, sizeof s, stdin);
    const char *delim = " \t\n";

    char *p = strtok(s, delim);
    while(p) {
        int val = strtol(p, NULL, 10);
        printf("%d\n", val);
        p = strtok(NULL, delim);
    }
    return 0;
}

Though do keep in mind that it's a bit iffy in that it uses hidden state (not good for multithreaded programs), and of course it modifies the input string, so it can't be a constant (but why would you do that).




回答7:


You can use isdigit or isalpha() function (based upon your use) available in ctype.h. following is code snippet using isdigit function:

for (i = 0; i <= (strlen(str)); i++)
{
    if (isdigit(str[i]))
    {
        int num = atoi(&str[i]);
        if(i && str[i-1]=='-') num *= -1;
        printf("%d\n", num);
        i += ( num==0 ) ? 1 : (int)log10(abs(num))+1;
    }
}

See it working here.
Check here for example on isdigit and isalpha() functions.

Regarding your question that:

So why i received 2 and 3 twice?

See following explanation available at cplusplus.com which explains the atoi() function.

The function first discards as many whitespace characters (as in isspace) as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many base-10 digits as possible, and interprets them as a numerical value.



来源:https://stackoverflow.com/questions/47451405/c-programming-print-only-int-from-fgets

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!