如何使用C语言中的fgets从用户获取整数?

4

我是C语言的初学者。我正在尝试使用fgets()编写一个程序,根据用户输入的3个整数计算体积,但我无法理解为什么我的代码不起作用。

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

int volumn(int a, int b, int c);

int main(int argc, char* argv[]){
    char* height, width, depth;
    fgets(&height, 10, stdin);
    fgets(&width, 10, stdin);
    fgets(&depth, 10, stdin);

    printf("\nThe volumn is %d\n", volumn(atoi(&height), atoi(&width), atoi(&depth)));

    return 0;
}

int volumn(int a, int b, int c){
    return a * b * c;
}

编辑: 当我运行上面的代码时,我会得到以下错误/警告:

goodbyeworld.c:8:11: warning: incompatible pointer types passing 'char **' to
      parameter of type 'char *'; remove & [-Wincompatible-pointer-types]
    fgets(&height, 10, stdin);
          ^~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/stdio.h:238:30: note: 
      passing argument to parameter here
char    *fgets(char * __restrict, int, FILE *);
                                ^
goodbyeworld.c:12:48: warning: incompatible pointer types passing 'char **' to
      parameter of type 'const char *'; remove & [-Wincompatible-pointer-types]
    printf("\nThe volumn is %d\n", volumn(atoi(&height), atoi(&width), a...
                                               ^~~~~~~
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/stdlib.h:132:23: note: 
      passing argument to parameter here
int      atoi(const char *);
                          ^
2 warnings generated.

2
你好,欢迎来到Stack Overflow!您能否更具体地说明它为什么不起作用?它是否编译成功?您是否收到任何错误消息?如果它运行了,当它运行时会发生什么?请编辑您的问题。 - Anders
1
在编译时,始终启用所有警告(对于gcc,至少使用:-Wall -Wextra -pedantic),然后修复警告。使用发布的代码,您将看到两个警告:1)未使用的变量'argc' 2)未使用的变量'argv []'以及您已经看到的警告。 - user3629249
4个回答

6

首先,像以下这样的定义:

 char* height, width, depth;

height指针化为char,其余两个变量也指向char

其次(虽然在这里不是很相关,但总体上很重要),您没有为想要使用的指针分配内存(如果有的话)。

如果您已经确定输入长度为10,那么可以将所有三个变量都定义为数组,并直接使用它们的名称,例如

#define VAL 10
char height[VAL] = {0};
char width[VAL] = {0};
char depth[VAL] = {0};

然后

fgets(height, 10, stdin);

最后,考虑使用strtol()代替atoi(),能更好地处理错误。


我认为这里缺少的分配非常重要。 - user2371524
确实,但仅仅修复了那个问题,接下来就是段错误了 ;) - user2371524
@FelixPalmen 这就是我转用数组的原因。 :) - Sourav Ghosh
我该如何使用strtol()将身高转换为整数?我尝试了atoi(height),但它没有起作用。 - johnwj
@tbee:一个简单的 atoi(height) 怎么可能不起作用呢? - Jongware
显示剩余3条评论

3

您的问题有一个简单的解决方案。

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

int volumn(int a, int b, int c){
    return a*b*c;
}

int main(){

    char height[10];
    char width[10];
    char depth[10];

    printf("Please enter size of object:\n");
    fgets(height, 10, stdin);
    fgets(width, 10, stdin);
    fgets(depth, 10, stdin);

    int valheight = atoi(height);
    int valwidth = atoi(width);
    int valdepth = atoi(depth);

    printf("\nThe volumn is %i\n", volumn(valheight, valwidth, valdepth));

    return 0;
}

0
你不应该这样做。当你可以获得输入的整数时,使用atoi将输入转换为整数是没有意义的。你需要的是scanf
你的代码应该像这样...
#include <stdio.h>
#include <stdlib.h>

int volumn (int a, int b, int c);

int
main (int argc, char* argv[])
{
    int height;
    int width;
    int depth;

    scanf ("%10d", &height);
    scanf ("%10d", &width);
    scanf ("%10d", &depth);

    printf ("\nThe volumn is %d\n", volumn (height, width, depth));

    return 0;
}

int
volumn (int a, int b, int c)
{
    return a * b * c;
} 

4
我从未发现scanf()在实际的交互式输入中有任何用处(我认为这正是提问者在这里想要做的)。 - user2371524
@FelixPalmen 我不明白为什么fgetsscanf更“交互”。 - Coffee'd Up Hacker
3
通过使用 fgets() 函数,你可以适当地应对意料之外的输入,这在交互式场景中经常会发生。 - user2371524
如果只有在遇到换行符/EOF时才返回,那么我仍然不明白 fgets 有什么优势。获取输入后,可以在之后进行任何想要的验证。使用 scanf 至少可以指定你期望的数据类型,使验证更加简单。 - Coffee'd Up Hacker
2
在某些情况下可能更简单,但灵活性要少得多,因为它不会让您访问原始输入。我总是会选择其他解决方案,例如像其他答案中建议的strtol() - user2371524
显示剩余8条评论

0
在C语言中,数组的名称会降级为指向数组第一个地址的指针。
然而,维度已经成为指向空地址的指针。
代码需要将它们指向已分配的内存。
通常可以通过类似以下代码来实现:
if( NULL == (height = malloc( 20 ) ) ) { // handle error and exit }

我使用了20而不是10,因为int类型可以有13个字符加上符号加上换行符加上NUL字节,20留下了一点额外的空间。

fgets()的第一个参数是输入缓冲区的指针,“height”等被定义为指针,因此不需要另一个“&”

但是,使用malloc()还需要在退出程序之前传递每个指针到free()。

请记住,在32位系统上,int(对于某些操作系统)可以处理+/-2gig即10位数字+符号+换行符+NUL,大约是13或14个字符。

建议使用:

int main( void )
{
    int height;
    int width;
    int depth;

    if( 1 != (scanf( "%d", &height ) ) ) 
    { // then scanf failed
        perror( "scanf for height failed: );
        exit( EXIT_FAILURE );
    }

    // implied else, scanf successful

    similar statements for the other two inputs

    printf ("\nThe volumn is %d\n", volumn (height, width, depth));
    return 0;
} // end function: main

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接