【C语言】练习Day——2

1、给定两个整形变量,交换其内容
这个问题很简单,只需要创建一个临时变量来保存其中一个变量的值就好,代码如下:
//给定两个整形变量,交换其内容
int main()
{
      int a = 10;
      int b = 20;
      int tmp = 0;
      printf("a=%d b=%d\n", a, b);
      tmp = a;
      a = b;
      b = tmp;
      printf("a=%d b=%d\n", a, b);
      getchar();
      return 0;
}

2、不创建临时变量解决第一个问题
这题有两种方法,各有利弊,下面分别分析。
  • 反复利用加减法(或者乘除法)
//给定两个整形变量,交换其内容
int main()
{
      int a = 10;
      int b = 20;
      printf("a=%d b=%d\n", a, b);
      a = a + b;//a=30
      b = a - b;//b=(10+20)-20=10
      a = a - b;//a=(10+20)-10=20
      printf("a=%d b=%d\n", a, b);
      getchar();
      return 0;
}
这种方法容易理解,但是有一个很大的问题,整形变量是有限制的,如果a、b的值足够大,a+b可能会超过整形的最大值,会遗失一些位,导致结果出现错误(乘除法问题会更多)。所以还有另一种算法:
  • 按位异或
int main()
{
      int a = 10;
      int b = 20;     
      printf("a=%d b=%d\n", a, b);
      /*a = 3;          011
      b = 5;           101*/
      a = a^b;//按位异或:  110   6
      b = a^b;//按位异或:  011   3
      a = a^b;//按位异或:  101   5
      printf("a=%d b=%d\n", a, b);
      getchar();
      return 0;
}
程序中对按位异或做了简单的举例说明,具体来说就是将整形变量换为二进制数,然后按位进行异或运算,相同为0,相异为1
按位异或因为没有开辟新的空间,所以不存在加减法出现的问题,但是按位异或也有缺点:比如运行效率低,代码可读性差等。

3、求10个整数中的最大值
//求10个整数中的最大值
int main()
{
      int arr[10] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };   //①
      int i = 0;
      int max = arr[0];                     //②
      for (i = 1; i < 10; i++){
            if (max < arr[i])
                  max = arr[i];
      }
      printf("十个数中的最大值为%d\n", max);
      getchar();
      return 0;
}
这里需要注意两个点:
  • ①处不能写为
      int n = 10;
      int arr[n] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };
arr[ ]中,[ ]中只能放常量,n是变量,所以上述表示方法错误
  • ②处max不要写成固定的数,比如0;因为无法确定数组中的数是否全为正数,如果有负数的话,max=0就无法得出正确结果了。
写作max=arr[0],下面的循环 i 可以从1开始,可以使循环少进行一次。
                      
4、将三个数从大到小输出
//将三个数从大到小输出
int main()
{
      int a = 2;
      int b = 7;
      int c = 8;
      if (a < b){
            int tmp = a;
            a = b;
            b = tmp;
      }
      if (a < c){
            int tmp = a;
            a = c;
            c = tmp;
      }
      if (b < c){
            int tmp = b;
            b = c;
            c = tmp;
      }
      printf("从大到小排列为:%d  %d  %d\n", a, b, c);
      getchar();
      return 0;
}
这个代码可以顺利地从大到小输出a,b,c,但是存在一个很明显的问题:代码复杂重复
用了三次交换,创建了三个临时变量,看起来非常不美观,这个时候就需要用到函数,这里可以用到一个交换函数,修改后代码如下:
void Swap(int m,int n)
{
      int tmp = m;
      m = n;
      n = tmp;
}
int main()
{
      int a = 2;
      int b = 7;
      int c = 8;
      if (a < b){
            Swap(a, b);
      }
      if (a < c){
            Swap(a, b);
      }
      if (b < c){
            Swap(a, b);
      }
      printf("从大到小排列为:%d  %d  %d\n", a, b, c);
      getchar();
      return 0;
}
照理来说代码是无误的,但是我们看一下运行结果:
可以看到结果和我们想要的完全不一样,问题出在哪里呢?我们调试一下

按F10进行逐步调试,调试—窗口—监视,进入监视窗口,首先看一下a,b,c的状况

显然,a,b,c此时还未赋值,都是随机值

定义之后


可以看到直到进入if语句a,b,c也还没有变化,接下来要进入Swap函数(按F11)

进入Swap函数后监视窗口a,b,c都变灰了,因为在Swap函数中,a,b,c是无效变量

函数运行结束后m,n也交换完毕,按理说接下来只要将数据传回主函数即可

但是我们可以看到,Swap函数结束后a,b值并没有交换,这是为什么呢?

这里要涉及到变量的开辟空间,在main函数中定义两个变量a,b
在Swap函数中定义两个变量m,n,其实是在Swap函数中重新开辟空间,然后将a,b的值传进去
但是m,n是局部变量,Swap函数结束的时候会释放空间,m,n的值不能传给a,b,所以即使调用了Swap函数,a,b的值也没有改变。

那么怎么解决呢?

很明显是因为空间问题,我们可以利用传地址的方式,不重新开辟空间,而是直接调用a,b的空间,就不会存在函数结束被销毁的问题了。
//将三个数从大到小输出
void Swap(int* m,int* n)
{
      int tmp = *m;
      *m = *n;
      *n = tmp;
}
int main()
{
      int a = 2;
      int b = 7;
      int c = 8;
      if (a < b){
            Swap(&a, &b);
      }
      if (a < c){
            Swap(&a, &c);
      }
      if (b < c){
            Swap(&b, &c);
      }
      printf("从大到小排列为:%d  %d  %d\n", a, b, c);
      getchar();
      return 0;
}

5、求两个数的最大公约数
//求两个数的最大公约数
//辗转相除法
int main()
{
      int m = 36;
      int n = 16;
      while (m%n)
      {
            int tmp = m%n;
            m = n;
            n = tmp;
      }
      printf("最大公约数为:%d\n", n);
      getchar();
      return 0;


阅读更多
个人分类: 练习 C语言
想对作者说点什么? 我来说一句

没有更多推荐了,返回首页

关闭
关闭
关闭