简体   繁体   English

C中递归函数的错误输出

[英]Erroneous output on recursive function in C

I am supposed to make a recursive function that prints an integer digit by digit using putchar() and not printf. 我应该做一个递归函数,使用putchar()而不是printf逐位打印整数。 The output should be 1234 but I am getting 1234(smiley face)1234. 输出应该是1234,但我正在获得1234(笑脸)1234。 Why is this so? 为什么会这样呢?

Also, can you add a '\\n' outside of a printf? 另外,可以在printf之外添加“ \\ n”吗?

Many thanks. 非常感谢。

#include <stdio.h>

int printnumber();

int main()
{
    int n = 1234;
    printnumber(n);
    return 0; 
}

int printnumber(int n) {
    int x, y;
    x = flip(n) % 10;
    putchar(x);
    y = flip(n) / 10;
    if (y < 0)
        printnumber(y);
}

int flip(int n)
{
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    if (n / 10)
        flip(n / 10);
    putchar(n % 10 + '0');
}

Your code has undefined behaviour because function flip declared as having return type int actually returns nothing. 您的代码具有未定义的行为,因为声明为具有返回类型int函数flip实际上未返回任何内容。

Also it seems that function flip does all the job. 而且似乎功能翻转可以完成所有工作。 So it is not clear what is the sense of function printnumber. 因此,不清楚函数printnumber的含义是什么。

You could simply define the function the following way 您可以通过以下方式简单地定义函数

#include <stdio.h>

void print_number( int n )
{
    if ( n < 0 ) 
    {
        putchar('-');
        n = -n;
    }

    if ( n / 10 ) print_number( n / 10 );
    putchar( n % 10 + '0' );
}

int main(void) 
{
    print_number( -1234 );


    return 0;
}

The output is 输出是

-1234

In your code, 在您的代码中

x = flip(n) % 10;

Line invokes undefined behaviour. 行调用未定义的行为。

You did not return any value from int flip(int n) . 您没有从int flip(int n) return任何值。 So, while executing the above stement, the compiler will have no explicit return value from flip(n) call and hence, the result is undefined. 因此,在执行上述命令时,编译器将不会从flip(n)调用获得任何显式的返回值,因此结果是不确定的。

Related Reading: From the C99 specification document, chapter 6.9.1, paragraph 12 相关阅读:来自C99规范文档,第6.9.1章,第12段

If the } that terminates a function is reached, and the value of the function call is used by the caller, the behavior is undefined. 如果到达终止函数的},并且调用者使用了函数调用的值,则该行为未定义。

Note: Think of a simpler logic. 注意:考虑更简单的逻辑。 This is kind of overkill for printing the digits. 这对于打印数字有点过分

That code looks way too complicated. 该代码看起来太复杂了。 Here's my single function version: 这是我的单功能版本:

void printNumber(int n) {
    if (n < 0) {
        putchar('-');
        printNumber(-n);
    } else {
        if (n >= 10) {
            printNumber(n / 10);
        }
        putchar('0' + (n % 10));
    }
}

ie output - and recurse for negative numbers, otherwise using inverted recursion (so that the digits come out in the right order) first recursively calls itself for the leftmost digits and then prints the rightmost digit. 即输出-并递归负数,否则使用倒数递归(以便数字以正确的顺序出现)首先递归调用最左边的数字,然后打印最右边的数字。

It's also possible to avoid the separate divide and modulus operations using the standard div function that produces both in one step, although whether this is more efficient is implementation dependent. 使用标准div函数(一步生成两个函数)也可以避免分开的除法和模运算,尽管这是否更有效取决于实现。

void printNumber(int n) {
    if (n < 0) {
        putchar('-');
        printNumber(-n);
    } else {
        div_t d = div(n, 10);
        if (d.quot) {
            printNumber(d.quot);
        }
        putchar('0' + d.rem);
    }
}

Assuming this is what you intend to do. 假设这是您打算要做的。 While using recursive functions the lines after the recursive function call are pushed onto the stack so we can make use of it and print 1234 as shown below. 在使用递归函数时,将递归函数调用之后的行压入堆栈,以便我们可以使用它并打印1234,如下所示。

#include <stdio.h>

void printnumber();

int main()
{
    int n = 1234;
    printnumber(n);
    return 0; 
}

void printnumber(int n) {
    char ch;
    int x;
    if(n == 0)
    return;
    else
    {
       x = n % 10;
       n = n/10;
       ch = x + '0';
       printnumber(n);
       putchar(ch);
    }
}

Is there any need of flip() function ? 是否有需要flip()函数? You can check this... 你可以检查一下...

#include <stdio.h>

void printnumber(int n);

int main()
{
    int n = -1234;
    printnumber(n);
    return 0;
}

void printnumber(int n) {
    if(n/10==0)
    {
        if(n<0)
        {
            putchar('-');
            n=-n;
        }
        putchar(n+'0');
        return;
    }
    int x, y;
    x=n%10;
    if(x<0)
    x=-x;
    printnumber(n/10);
    putchar(x+'0');
}

I assume you want : 我想你想要:

  • a function taking an int and displayint it 接受int并对其进行显示的函数
  • calling a recursive function printing digit by digit 调用递归函数逐位打印
  • display adds a new line ( \\n ) after the number 显示屏在数字后添加新行( \\n

But as your functions do not return anything of interest it is better to declare them void. 但是由于您的函数不返回任何感兴趣的内容,因此最好将它们声明为无效。 It would have avoided the undefined behaviour of using the value of a function without any return ( x = flip(n) % 10; in printnumber) 这样可以避免使用函数值而没有任何返回的不确定行为( x = flip(n) % 10;在printnumber中)

You can do for example : 您可以例如:

#include <stdio.h>

/* function declaration before usage */
void flip(int n);
void printnumber(int n)

int main()
{
    int n = 1234;
    printnumber(n);
    return 0; 
}

/* prints a int followed by new line */
void printnumber(int n) {
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    flip(n);
    putchar('\n');
}

/* recursively prints decimal digits of an int */
void flip(int n)
{
    if (n / 10)
        flip(n / 10);
    putchar(n % 10 + '0');
}

EDIT per comment : if you want only one function, you should better put in main what should happen only once : 编辑每个注释:如果只需要一个功能,则最好将main只能发生一次:

#include <stdio.h>

/* function declaration before usage */
void printnumber(int n)

int main()
{
    int n = 1234;
    if (n < 0) {
        putchar('-');
        n = -n;
    }
    printnumber(n);
    putchar('\n');
    return 0; 
}

/* recursively prints decimal digits of an int */
void printnumber(int n)
{
    if (n / 10)
        printnumber(n / 10);
    putchar(n % 10 + '0');
}

Answering your easier question first, you can use putchar('\\n') to output a newline. 首先回答您的简单问题,您可以使用putchar('\\n')输出换行符。 printf just repeatedly calls putchar. printf只是反复调用putchar。

Your code is a little over complex, and among other things flip() doesn't return a value (Always switch on compiler warnings - they tell you when you're doing something silly (or dangerous)). 您的代码有点复杂,除其他事项外,flip()不会返回值(始终打开编译器警告-它们会告诉您何时您在做一些愚蠢(或危险)的事情)。

An implementation would be something like this: 一个实现将是这样的:

#inclde <stdio.h>

void print_digits(unsigned n)
{
    if (n >= 10) { print_digits(n / 10); }
    putchar(n % 10 + '0');
}

void printnumber(int n)
{
    /* Copes with max negative integer */
    unsigned u = n;
    if (n < 0) { putchar('-'); u = -u; }
    print_digits(u);
}

int main(void)
{
    int n = 1234;
    print_number(n);
    putchar('\n');
    return 0;
}

Two issues 两个问题

  1. Using the return value from int flip() , but the function failing to provide a return value invokes undefined behavior (UB) - anything can happen. 使用int flip()的返回值,但未能提供返回值的函数会调用未定义行为(UB)-可能发生任何事情。 @Sourav Ghosh @Sourav Ghosh

  2. n = -n; is a niche problem also. 也是一个利基问题。 When n == INT_MIN on many systems which use 2's complement integer, the result is also UB. 在许多使用2的补码整数的系统上,当n == INT_MIN时,结果也是UB。 To solve that, negate positive numbers and recurse with negative numbers. 要解决此问题,请对正数取反,然后对负数递归。 With int , the range of negative numbers is always at least or greater than the range of positive numbers. 使用int ,负数的范围始终至少等于或大于正数的范围。

Add '\\n' outside of a printf with another putchar() . 用另一个putchar()在printf之外添加'\\n'

#include <limits.h>
#include <stdio.h>

static void printdigit(int n) {
  if (n <= -10) {
    printdigit(n / 10);
  }
  putchar('0' - n % 10);  // use -
}

void printnumber(int n) {
  if (n < 0) {
    putchar('-');
  } else {
    n = -n;
  }
  printdigit(n);
  putchar('\n');
}
int main(void) {
  printnumber(1234);
  printnumber(-1234);
  printnumber(INT_MIN);
  printnumber(INT_MAX);
  printnumber(0);
  return 0;
}

Output 输出量

1234
-1234
-2147483648
2147483647
0

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

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