我这个代码是求阶乘,要求对输入的整数n进行合法性检测,就是我输入小数,它会报错,但是我的程序为什么就直接执行了
第一行已经将n定义为了int型,所以你输入的6.99其实是6(int型),将第一行的int改成double,然后将factorial()中的n进行强制类型转换
double n;
int x = factorial(int(n));
你输入的类型已经是int了啊,还n-int(n)干啥呢?
n改为double类型,函数传参时对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时,即为实现整个数组的全排列,这样就实现问题的求解。
能力有限,中间可能还有一些没有说明白的地方,希望大家可以理解。
附图:
方法一:对输入进行检测,判断是否为整数,如果不是整数则视为非法输入,并提示用户重新输入。
具体实现方法是,使用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;
}
参考资料: