大家可以看看我的代码哪里有问题吗

我这个代码是求阶乘,要求对输入的整数n进行合法性检测,就是我输入小数,它会报错,但是我的程序为什么就直接执行了

img

img

第一行已经将n定义为了int型,所以你输入的6.99其实是6(int型),将第一行的int改成double,然后将factorial()中的n进行强制类型转换

double n;

int x = factorial(int(n));

你输入的类型已经是int了啊,还n-int(n)干啥呢?

n改为double类型,函数传参时对n强制转换

  • 你可以参考下这个问题的回答, 看看是否对你有帮助, 链接: https://ask.csdn.net/questions/7653124
  • 这篇博客你也可以参考下:将长度为n的顺序表转换为带头结点的单链表,元素位序不变
  • 除此之外, 这篇博客: 【算法】n阶行列式求值 全排列中的 行列式求值&&全排列 部分也许能够解决你的问题, 你可以仔细阅读以下内容或跳转源博客中阅读:
  • 个人感觉自己写的行列式求值的程序与全排列的程序有几分神似,所以就把它们放到一起啦。

    先来看求n阶行列式的程序

    #include<stdio.h>
    #include <stdlib.h>
    //C语言初学者,欢迎大家指正
    void show(int **p,int size)                //打印出数组中的元素
    {
        int i,j;
        for (i=0;i<size;i++){
            for (j=0;j<size;j++)
            {
                printf("%-5d",p[i][j]);
            }
            printf("\n");
        }
    }
    
    long long int hanglieshi(int **p,int m,int n)      //(核心函数)求n阶行列式的值
    {
        int i,j,temp,flag=1;
        long long int result=0;
        if (m==n-1)                        //递归的出口
            return p[m][m];
        for (i=m;i<n;i++)                
        {
            for (j=m;j<n;j++)            //i列元素与m列元素进行交换  下文求全排列的程序也有类似的代码
            {
                temp=p[j][m];            
                p[j][m]=p[j][i];
                p[j][i]=temp;
            }
            if (i!=m) flag=-1;            //确定符号  我在这里卡了一段时间
            else flag=1;
            result+=flag*p[m][m]*hanglieshi(p,m+1,n);    //递归实现
            for (j=m;j<n;j++)            //再将i列元素与m列元素换回来
            {
                temp=p[j][m];
                p[j][m]=p[j][i];
                p[j][i]=temp;
            }
        }
        return result;
    }
    
    int main()
    {
        int n,i,j;
        printf("请输入行列式的阶数(最好是12阶以内,要不然运行时间会很长):");
        scanf("%d",&n);
        int **p=(int **)malloc(sizeof (int *)*n);     //申请一个n*n二维数组
        for (i=0;i<n;i++)
        {
            p[i]=(int *)malloc(sizeof(int )*n);
        }                                             //二维数组申请完毕
        printf("请输入行列式\n");
        for (i=0;i<n;i++)                             //向二维数组中赋值
        {
            for (j=0;j<n;j++)
            {
               // scanf("%d",&p[i][j]);
                  p[i][j]=rand()%100;                 //可以自己输入,也可以用随机函数
            }
        }
    printf("******************************\n");
    show(p,n);
    printf("行列式的值为%d",hanglieshi(p,0,n));
        for (i=0;i<n;i++)                            //释放内存
            free(p[i]);
        free(p);
    }
    

    程序思路:将第m行展开

    我觉得求n阶行列式这个问题和全排列这个问题,基本差不多,都是通过递归调用来实现的,下文附上全排列问题的代码。

    #include <stdio.h>
    void exchange(int *m,int *n)            //实现两个数字的交换
    {
        int temp;
        temp=*m;
        *m=*n;
        *n=temp;
    }
    
    void quanpai(int n,int m,int *p)        //核心函数,n代表总的元素个数,m代表实现后m个元素的全排列
    {
        int i;
        if (m==1){                          //递归的出口,将这个数列全部打印出来
            for(i=0;i<n;i++)
                printf("%5d",p[i]);
            printf("\n");
        }
        else {
            for (i=n-m;i<n;i++){              //核心代码,具体解释见下文
                exchange(&p[i],&p[n-m]);
                quanpai(n,m-1,p);
                exchange(&p[i],&p[n-m]);
            }
        }
    }
    
    void main()
    {
        int p[3]={1,2,3};
        quanpai(3,3,p);
    }
    

    我还没学算法,所以,对于时间复杂度或者是空间复杂度的分析还不懂,不过都是递归算法,效率都会比较低。
    对于上文所说的全排列的核心代码,我来解释一下。
    首先,我觉得要实现递归,最先要解决问题就是寻找Question(n)与Question(n-1)之间的关系。对于实现后面m个元素全排列这个问题,我们需要先确定一个元素,定为p[n-m],然后实现后面m-1个元素的全排列,然后再将p[n-m]与后面的元素依次进行交换,每次交换后,都调用一下函数,实现后面m-1个元素的全排列,然后换回来,保证每次调用函数时数组不变。当m==n时,即为实现整个数组的全排列,这样就实现问题的求解。

    能力有限,中间可能还有一些没有说明白的地方,希望大家可以理解。

    附图:
    在这里插入图片描述

  • 您还可以看一下 孙玖祥老师的图解数据结构与算法课程中的 左旋和右旋的代码实现小节, 巩固相关知识点
  • 以下回答由chatgpt基于相关博客总结生成:

    方法一:对输入进行检测,判断是否为整数,如果不是整数则视为非法输入,并提示用户重新输入。

    具体实现方法是,使用scanf函数读取输入,再使用判断输入是否合法的函数进行判断。判断函数可以使用isdigit()函数,该函数是C标准库stdlib.h头文件中的函数,作用是判断一个字符是否为数字字符。

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    #include <ctype.h>
    
    int main(){
        int input;
        printf("请输入一个整数:");
        while(scanf("%d", &input) != 1 || getchar() != '\n' || !isdigit(input)){
            printf("输入非法,请重新输入一个整数:");
            while(getchar() != '\n'){};
        }
        printf("输入合法,您输入的数是:%d\n", input);
        return 0;
    }
    

    方法二:在代码中进行判断,如果输入值不是整数,则直接返回。

    具体实现方法是,读取输入之后,使用函数判断输入值是否为整数,如果不是则直接返回,否则继续执行后续操作。判断函数可以使用atof()函数(在stdlib.h头文件中),该函数可以将字符串转换为双精度浮点数,若转换失败则返回0。

    代码如下:

    #include <stdio.h>
    #include <stdlib.h>
    
    int main(){
        double input;
        char str[30];
        printf("请输入一个整数:");
        fgets(str, 30, stdin);
        input = atof(str);
        if(input == 0){
            printf("非法输入,程序结束。\n");
            return 0;
        }
        printf("输入合法,您输入的数是:%d\n", (int)input);  //强制类型转换为整型
        return 0;
    }
    

    以上两种方法都可以实现对输入小数的非法情况的检测。

    除此之外,还可以使用正则表达式对输入进行判断,这是更加通用的方法,但实现起来较为复杂,不建议在这里详细讲解。

    另外,如果只需要判断是否为整数,也可以在输入接受时使用%f格式控制字符串,并利用scanf函数返回值来判断是否为整数。代码如下:

    #include <stdio.h>
    
    int main(){
        int input;
        printf("请输入一个整数:");
        while((scanf("%d", &input) != 1)){
            printf("输入非法,请重新输入一个整数:");
            while(getchar() != '\n'){};
        }
        printf("输入合法,您输入的数是:%d\n", input);
        return 0;
    }
    

    参考资料:

    1. C语言中的isdigit()函数:https://www.runoob.com/cprogramming/c-function-isdigit.html
    2. C语言中atof()函数:https://www.runoob.com/cprogramming/c-function-atof.html
    3. C语言中scanf()函数:https://www.runoob.com/cprogramming/c-function-scanf.html