C中的递归函数,用于确定整数的数字是升序,降序还是不排序

时间:2019-12-10 23:16:15

标签: c function recursion

我需要编写一个递归函数,如果整数的数字从左到右递增,则返回1;如果递减,则返回-1;否则则返回0。

我的解决方案尝试每次都返回0,我知道为什么,但是我不知道如何解决它。

这是我的代码:

#include <stdio.h>

int check_order(int n)
{
    if (n % 10 > n / 10 % 10)
    {
        return check_order(n / 10);
        if (n == 0)
        {           
            return 1;
        }
    }
    else if (n % 10 < n / 10 % 10)
    {
        return check_order(n / 10);
        if (n == 0)
        {
            return -1;
        }
    }
    else
    {
        return 0;
    }
}

int main()
{
    int n;
    printf("enter a whole number (n > 9):");
    scanf_s("%d", &n);
    printf("function returned: %d\n", check_order(n));
}

5 个答案:

答案 0 :(得分:0)

return语句之后的代码无法访问:

return check_order(n / 10);
if (n == 0)
{
    return -1;
}

除此之外,您在将当前数字与下一个数字进行比较的正确位置上,但是我看不到明确的基本情况(当n < 10,即一个数字时)。 / p>

试图用一种递归函数检查升序和降序很难管理。特别是,在堆栈帧之间传递状态并确定在给定调用中哪些情况仍然有效,则表明返回值工作过度。

为省去返回结构或使用枚举或魔术数字作为标志的麻烦,我将编写两个常规的辅助函数ascending_digitsdescending_digits

#include <stdbool.h>
#include <stdio.h>

bool ascending_digits(int n) {
    if (n < 10) return true;
    if (n % 10 < n / 10 % 10) return false;
    return ascending_digits(n / 10);
}

bool descending_digits(int n) {
    if (n < 10) return true;
    if (n % 10 > n / 10 % 10) return false;
    return descending_digits(n / 10);
}

int check_order(int n) {
    if (ascending_digits(n)) return 1;
    if (descending_digits(n)) return -1;
    return 0;
}

int main() {
    printf("12345: %d\n", check_order(12345));
    printf("54321: %d\n", check_order(54321));
    printf("54323: %d\n", check_order(54323));
    printf("454321: %d\n", check_order(454321));
    printf("1: %d\n", check_order(1));
    printf("12: %d\n", check_order(12));
    printf("21: %d\n", check_order(21));
    return 0;
}

输出:

12345: 1
54321: -1
54323: 0
454321: 0
1: 1
12: 1
21: -1

这些功能不仅更易于理解和单独维护,而且与密不可分地捆绑在一起相比,它们也更具可重用性。

这不处理负数-如果需要,您可以申请abs并从那里去。处理相等的值也是如此;此实现接受诸如1223之类的数字,但是您可以使用<=来执行严格的排序。

答案 1 :(得分:0)

请解释您的算法?

假设您使用以下内容:

  • 为您提供了一个号码。
  • 您需要将该数字转换为数字序列。
    • 如果给定一个数字,则可以将该数字转换为数字序列。
    • 如果给您一个数字序列,请使用 那。
  • 比较每对数字->升序,降序或都不选择。
  • 按顺序/递归组合每对结果。

我们可以使用字符串来简化数字比较,并接受很长的数字序列。

我们可以使用枚举类型来表示顺序。

您如何合并结果?定义一个将两个相邻重叠对的顺序组合在一起的函数,然后就可以组合结果。

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

typedef enum { descending=-1, other=0, ascending=1 } order_t;

order_t pair_order(int a, int b) {
    if( a < b ) return ascending;
    if( a > b ) return descending;
    return other;
}

//strict (increasing/decreasing)
order_t strict_order( order_t x, order_t y ) {
    if( x == y ) return x;
    return other;
}

//monotone (increasing/decreasing)
order_t monotone_order( order_t x, order_t y ) {
    if( x == y ) return x;
    if( other == x ) return y;
    if( other == y ) return x;
    return other;
}

order_t check_order( char* p, int remain ) {
    //printf("p:%s\n",p); //uncomment to watch progress
    if( remain<2 ) return other;
    if( remain==2 ) return pair_order(p[0], p[1]);
    return strict_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
    //return monotone_order( pair_order(p[0], p[1]), check_order(p+1, remain-1) );
}

char* order_name[] = {
    "descending",
    "other",
    "ascending"
    ""
};

int main()
{
    char line[666] = "none";
    while ( strlen(line) > 0 ) {
    printf("enter a number (at least 2 digits):");
    fgets(stdin,line,sizeof(line)-1);
    if( strlen(line) > 0 && line[strlen(line)-1] == '\n' )
        line[strlen(line)-1] = '\0';
    order_t order = check_order(line);
    printf("function returned: (%d)%s\n", order, order_name[order+1]);
    }
}

答案 2 :(得分:0)

我认为您是从正确的道路开始的,但需要进一步完善代码。我的解决方案借用@ChuckCottrill的方法,因为我喜欢他的enum,但我不喜欢他不打球(即转换为字符串而不是处理int) 。)我还借用了@ggorlen的漂亮测试示例,但我也不喜欢这种解决方案,因为当只需要一次通过时,它可能需要多次通过数字才能找出答案:

#include <stdio.h>

typedef enum { descending=-1, other=0, ascending=1 } order_t; // a la @ChuckCottrill

order_t check_order(int n)
{
    if (n > 9) {
        int right = n % 10;
        int left = n / 10 % 10;

        if (right > left) {
            n /= 10;

            if (n > 9) {
                return (ascending == check_order(n)) ? ascending : other;
            }

            return ascending;
        }

        if (right < left) {
            n /= 10;

            if (n > 9) {
                return (descending == check_order(n)) ? descending : other;
            }

            return descending;
        }
    }

    return other;
}

int main() { // a la @ggorlen
    printf("12345: %d\n", check_order(12345));
    printf("54321: %d\n", check_order(54321));
    printf("54323: %d\n", check_order(54323));
    printf("454321: %d\n", check_order(454321));
    printf("1: %d\n", check_order(1));
    printf("12: %d\n", check_order(12));
    printf("21: %d\n", check_order(21));
}

输出

> ./a.out
12345: 1
54321: -1
54323: 0
454321: 0
1: 0
12: 1
21: -1
> 

答案 3 :(得分:0)

该版本可以使用任何长度,因为它将字符串作为参数。 并且以递归状态(递归或递减)的形式递归函数可以使代码更短,功能更少。

int check_order(char *str, int index, int previous) {
     char current = str[index];       // char at index
     char next = str[index+1];        // char at index+1
     if (current == 0 || next == 0) {
          return previous;            // End of string
     }
     // Ascending or descending?
     int status = next > current ? 1 : (next < current ? -1 : 0); 
     if (status == 0 || index > 0 && status != previous) {
          // If neither -1/1 nor status == previous (while not initial call)
          return 0;
     }
     return check_order(str, index+1, status); // Check from next index
}

main 函数必须确保字符串至少为2个字符

int main(int argc, char **argv) {
     char *str = *++argv;
     // Some optional checks on str here... (like this is a number)
     int status = 0; // Default value if string length < 2
     if (strlen(str) >= 2) {
        status = check_order(str, 0, 0);
     }
     printf("Check order for %s is %d\n", str, status);
     return 0;
}

答案 4 :(得分:0)

这是一个简单的递归:

int f(int n){
  if (n < 10)
    return 0;

  int dr = n % 10; // rightmost digit
  n = n / 10;
  int dl = n % 10; // second digit from the right 
  int curr = dl < dr ? 1 : -1; // current comparison 
  if (dl == dr) curr = 0; // keep strict order

  if (n < 10)
    return curr;

  return curr == f(n) ? curr : 0; // are the comparisons consistent?
}