在C语言中关于scanf [关闭]

问题描述 投票:1回答:5

我将scanf函数分组并将此函数命名为eno,并在我的C代码中调用此函数后,它无法正常工作。如果我在代码中单独使用scanf函数,它可以工作。所以我的问题是为什么功能不起作用?这里我显示a = 0和b = 1。总是。 :

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

    int eno(int, int);

    int main() {
        int a, b;
        eno(a, b);
        printf("%d  %d", a, b);
    }

   int eno(int j, int k) {
       scanf("%d", &j);
       scanf("%d", &k);
   }
c scanf
5个回答
6
投票

jk在记忆中不同于ab,所以写jkab没有影响。

要让eno修改ab,你需要将指针传递给ab,如下所示:

eno( &a, &b );
...
void eno( int *j, int *k ) // use void instead of int here; eno doesn't return a value
{
  scanf( "%d", j ); // no & operator on j or k, they're already pointers
  scanf( "%d", k );
}

6
投票

这是C的一个非常重要的基本方面。

C按值传递所有函数参数

这意味着最好用一个简单的例子来描述:

void foo(int x)
{
    x = 42;             // Changes x inside foo but NOT x inside bar
    printf("%d\n", x);  // Prints 42
}

void bar()
{
    int x = 5;
    foo(x);
    printf("%d\n", x);  // Prints 5 
}

输出:

42
5

这里要理解的重要一点是x内部的barx内部的另一个变量foo。在x内对foo所做的任何改变都不会改变x中的bar

调用foo(x)将x的值传递给foo。所以在这种情况下它与foo(5)相同。

要从x内部更改barfoo的值,您需要将指针传递给x

那是:

void foo(int *x)         // Notice the * - Means that foo receives a pointer to int
{
    *x = 42;             // Notice the * - Change the value of x in bar
    printf("%d\n", *x);  // Notice the * - Read the value of x in bar
}

void bar()
{
    int x = 5;
    foo(&x);      // Notice the & - it takes the address of x so &x is a pointer to x
    printf("%d\n", x);
}

输出:

42
42

因此,要使代码工作,您需要更改eno,以便它接收指向int而不是int的指针。喜欢:

int eno(int*, int*);

被称为:

eno(&a, &b);

2
投票
eno(a, b);
    ^  ^

int eno(int j, int k)
            ^      ^

ab分别复制到jk。 当函数eno返回时,值未被修改。


这是指针进入图片的地方。

eno(&a, &b);            // pass the address of a and b
    ^   ^

int eno(int* j, int* k) // j and k now point to a and b respectively.
           ^       ^

1
投票

因为你将ab的值传递给eno。您需要通过引用传递它们,如下面的代码所示。您需要使用指针通过引用传递。

#include <stdio.h> 

int eno(int *,int*); 

int main(){ 
   int a,b; 
   eno(&a,&b); 
   printf("%d %d",a,b); 
}

int eno(int *j,int *k)
{ 
   scanf("%d",j); 
   scanf("%d",k); 
}

0
投票

编译时,始终启用警告,然后修复这些警告。

对于gcc,至少使用:-Wall -Wextra -Wconversion -pedantic -std=gnu17

注意:其他编译器使用不同的选项来完成相同的结果。

编译发布的代码导致:

gcc -ggdb -Wall -Wextra -Wconversion -pedantic -std=gnu11 -c "untitled.c" 

untitled.c: In function ‘eno’:
untitled.c:17:4: warning: control reaches end of non-void function [-Wreturn-type]
    }
    ^

untitled.c: In function ‘main’:

untitled.c:10:9: warning: ‘a’ is used uninitialized in this function [-Wuninitialized]
         eno(a, b);
         ^~~~~~~~~

untitled.c:10:9: warning: ‘b’ is used uninitialized in this function [-Wuninitialized]

请注意编译器会告诉您有关已发布代码的三个问题。

这是一个可以按需运行的代码版本。

注意正确使用传递变量的地址,以及函数的正确声明:eno()

请注意正确检查scanf()的调用,以确保操作成功。

包含未使用这些内容的头文件是一种非常糟糕的编程习惯。 I.E. math.hstring.h

变量(和参数)名称应指示contentusage(或更好,两者)

通常,函数名称应该是“活动的”,而不是“神秘的”。它们应该向代码的读者指出函数的作用。

现在,提出的代码只能解决编译器问题,而不是使代码变得更优秀的更微妙的东西:

#include <stdio.h>
//#include <string.h>
//#include <math.h>
#include <stdlib.h>  // exit(), EXIT_FAILURE

void eno( int *, int * );

int main( void )
{
    int a, b;
    eno( &a, &b);
    printf("%d  %d", a, b);
}

void eno(int *j, int *k) 
{
    if( scanf("%d", j) != 1 )
    {
        fprintf( stderr, "scanf to read the variable j failed" );
        exit( EXIT_FAILURE );
    }

    if( scanf("%d", k) != 1 )
    {
        fprintf( stderr, "scanf to read the variable k failed" );
        exit( EXIT_FAILURE );
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.