当前位置 : 主页 > 编程语言 > c语言 >

C语言初阶习题

来源:互联网 收集:自由互联 发布时间:2023-08-28
分支语句习题 1.下面代码的执行结果 #include stdio.hint main(){ int i = 0; for (i = 0; i 10; i++) { if (i = 5) printf("%d", i); } return 0;} 输出:死循环输出5 分析:i=0时,进行循环判断部分i=010,执行循环

分支语句习题

1.下面代码的执行结果

#include <stdio.h>
int main()
{
    int i = 0;
    for (i = 0; i < 10; i++)
    {
        if (i = 5)
            printf("%d", i);
    }
    return 0;
}

输出:死循环输出5

分析:i=0时,进行循环判断部分i=0<10,执行循环语句,将i赋值为5并打印输出i,进入循环调整部分:i++ ,6 进入循环判断部分 6<10 ,执行循环语句将i赋值为5并打印输出i,进入循环调整部分:i++ ,6,一直这样5,6死循环下去,所以死循环输出5

2.if语句中0表示假,1表示真 

偏颇的不够准确的说法   正确说法:0表示假,非0表示真

3.switch中的default子句可以放到任意位置                正确

分析:顺序的问题。case语句项与default子句(所有的case语句项不能匹配下执行default子句)顺序可以调换  (这里的任意位置并不是指随意乱放,不是指放到Switch外部。在不能打破原有任务的逻辑下任意调换)

switch中case后表达式只能是整形常量表达式             正确

分析:'a' , char也属于整型的一种 因为字符存储时存的是ascii码值,归类时char也会归类到整型中去

4.下面代码的执行结果

#include <stdio.h>
int fun(int a)
{
    int b;
    switch (a)
    {
    case 1:
        b = 30;
    case 2:
        b = 20;
    case 3:
        b = 10;
    default:
        b = 0;
    }
    return 不;
}
int main()
{
    printf("%d",fun(1));
    return 0;
}

输出: 0

分析:a=1,进入case 1语句项执行b=30因为后面没有遇到break语句,就进入case 2 执行b=20,没有遇到break语句,再进入 case 3执行b=10,没有遇到break语句,再进入default子句执行b=0,执行完最后一条语句退出Switch语句,返回b=0 ,所以输出b=0

5.switch(c) 其中c不可以是什么类型:

A .int  B.long C.char D.float                            答案:D

6.写代码实现: 三个整数从大到小输出

#include <stdio.h>
void swap(int *px, int *py)
{
    int c = 0;
    c = *px;
    *px = *py;
    *py = c;
}
int main()
{ //三个整数从大到小输出
    int a = 0, b = 0, c = 0;
    //输入
    scanf("%d %d %d", &a, &b, &c);
    //调整   其他方法:1.排序 2.swap()
    int tmp = 0;
    if (a < b)
    {
        /* tmp = a;
         a = b;
         b = tmp;*/
        swap(&a, &b);
    }
    if (a < c)
    {
       /*mp = a;
        a = c;
        c = tmp;*/
       swap(&a, &c);
    }
    if (b < c)
    {
        /*tmp = b;
        b = c;
        c = tmp;*/
        swap(&b, &c);
    }
    //输出
    printf("%d %d %d\n", a, b, c);
    return 0;
}

7.写代码实现打印1~100中3的倍数

#include <stdio.h>
int main()
{
    int i = 0;
    for (i = 1; i <= 100; i++) //法一
    {
        if (i % 3 == 0)
        {
            printf("%d ", i);
        }
    }

    for (i = 3; i <= 100; i += 3) //法二
    {
        if (i % 3 == 0)
        {
            printf("%d ", i);
        }
    }
    return 0;
}

8.求两个数的最大公约数

#include <stdio.h>
int main()
{ //最大公约数
    int a = 0;
    int b = 0;
    scanf("%d %d", &a, &b);
    //求最大公约数:
    //暴力求解: 一个一个试除 不够高效
    // eg;6和9的最大的公约数:不会超过6 找<=6的所有数字
    //从大到小试除直到找到第一个能被这两个数同时整除的数字:最大公约数
    int m = (a < b) ? a : b; //找出较小值

    while (1)
    {
        if (a % m == 0 && b % m == 0)
        {
            break;
        }
        m--;
    }
    printf("%d\n", m);
    //辗转相除法  效率高
    // eg 24和18的最大公约数    a(24)%b(18)=c(6)    a(a=b)(18)%b(b=c)(6)=c(0)   最大公约数:6 即a%b等于0时b的值 速度很快
    // 输入18 24还满足?18%24=18  a=b=24 b=c=18 发现又交换回来了
    int c = 0;
    while (c = a % b) //优化:省略赋值,直到c=0 退出循环
    {
        // int c = a % b;
        a = b;
        b = c;
    }
    printf("%d\n", b);
    return 0;
}
//递归?

引申:最小公倍数 ?  暴力求解:从两个数里面较大值为起点不断加1试 同时整除的第一个数值,

max%a==0&&max%b==0//暴力求解的核心

效率更高的做法:a*b/最大公约数=最小公倍数

循环语句习题

1.

C语言初阶习题_C语言

分析:先判断再执行循环体                              答案B

2.以下程序输出的结果是:

#include <stdio.h>
int main()
{
    int a=0,b=0;
    for(a=1,b=1;a<=100;a++)
    {
        if(b>=20) break;
        if(b%3==1)
        {
            b=b+3;
            continue;
        }
        b=b-5;
    }
    printf("%d\n",a);
    return 0;
}

输出:8

分析:先进入for循环初始化部分,再进入for循环判断部分,a<=100,执行循环语句,b%3==1满足进入第二个分支语句,b=4,continue,跳过本次循环后面的代码来到调整部分,a++,a=2,再继续进入for循环判断部分,以此类推,由上分析,b+=3执行完之后才会来到a++部分,又因为b>=20就可以跳出循环,即b=1+3*7时跳出循环,也就说b+=3执行了7次,那么a++也会执行7次1+1*7=8

3.写代码实现:求1~100中所有整数出现多少个数字9?

#include <stdio.h>
int main()
{ // 1~100中整数出现数字9的个数  十位上数字9  个位上数字9
    int i = 0;
    int count = 0; //计数
    for (i = 1; i <= 100; i++)
    {
        if (i % 10 == 9) //个位上是否为数字9
            count++;
        if (i / 10 == 9) //十位上是否为数字9
            count++;
    }
    printf("count = %d", count);//输出count = 20
    return 0;
}

注意:写成 if  else if这种形式只是一个多分支的if语句,只会选择一个分支进去,只会进去一次  i=99,只计了个位的9,十位9不会进去判断了,就会漏值,所以还是写两个if语句,两个都会进去判断,不会出现差漏

4.分数求和,计算:1/1-1/2+1/3-1/4+1/5+......+1/99-1/100

#include <stdio.h>
int main()
{
    int i = 0;
    double sum = 0;
    int flag = 1; //实现正负交替
    for (i = 1; i <= 100; i++)
    {
        sum = sum + flag * (1.0 / i);
        flag = -flag;
    }
    printf("%lf\n", sum);
    return 0;
}

5.求10个整数中的最大值

#include <stdio.h>
int main()
{ //求10个整数中的最大值
    // int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //初始化预设十个数
    int arr[10] = {0};
    // 写成arr[]={0} 等价于 arr[1]={0}  输入多个数字会出现数组越界
    int j = 0;
    for (j = 0; j < 10; j++)
    {
        scanf("%d", &arr[j]); //输入10个值
    }
    int max = arr[0];
    int i = 0;
    for (i = 1; i < 10; i++)
    {
        if (max < arr[i])
        {
            max = arr[i];
        }
    }
    printf("%d\n", max);
    return 0;
}

6.打印9*9乘法表

#include <stdio.h>
int main()
{ //打印9*9乘法表
    int i = 0;
    int j = 0;
    for (i = 1; i <= 9; i++) //打印9行
    {
        for (j = 1; j <= i; j++) //打印每一项
        {
            printf("%d*%d=%2d ", i, j, i * j); //%2d打印两位整数(只有一位整数用空格补齐)
                                               //%2d两位右对齐 %-2d两位左对齐
        }
        printf("\n");
    }
    return 0;
}

函数习题

1.

C语言初阶习题_习题_02

分析:

A return (3,4); (3,4)被当作一个逗号表达式(从左向右依次计算,整个表达式结果是最后一个表达式结果) 只会返回4(最后一个表达式结果)

B  int arr[ ]本质上是 int* arr(arr是一个指针变量,存放的是数组首元素的地址) arr[0]等价于*(arr+0) , arr[1]等价于*(arr+1)     (arr指向第一个元素 arr+1指向第二个元素)如下图观察调试结果也显示可以将3,4返回到主函数

C语言初阶习题_习题_03

#include<stdio.h>
void test(int *px, int *py)
{
    *px = 3;
    *py = 4;
}
int main()
{
    int a = 0, b = 0;
    test(&a, &b);
    printf("%d %d\n",a,b);
    return 0;
}

D

#include<stdio.h>
int a = 0, b = 0;
void test()
{
    a=3;
    b=4;
}
int main()
{ 
    test();
    printf("%d %d\n",a,b);
    return 0;
}

2.打印n*n乘法表 (函数实现;能指定行和列)

#include <stdio.h>
void print_table(int n)
{
    int i = 0;
    int j = 0;
    for (i = 1; i <= n; i++) //打印n行
    {
        for (j = 1; j <= i; j++) //打印每一项
        {
            printf("%d*%d=%2d ", i, j, i * j); //%2d打印两位整数(只有一位整数用空格补齐)
                                               //%2d两位右对齐 %-2d两位左对齐
        }
        printf("\n");
    }
}
int main()
{ //打印n*n乘法表 1.函数实现 2.能指定行和列
    int n = 0;
    scanf("%d", &n);
    print_table(n);
    return 0;
}

递归习题

1.字符串逆序(递归实现)

编写一个函数 reverse(char * str) (递归实现)

  • 实现: 将參数字符申中的字符反向排列,不是逆打
  • 要求: 不能使用C函数库中的字符串操作函数
  • 比如:char arr[]="abcdef" 逆序之后数组的內容变成: fedcba

方法一:迭代实现

#include <stdio.h>
#include <string.h>
//字符串逆序  迭代实现
void reverse(char arr[])
{
    int left = 0;
    int right = strlen(arr) - 1;
    // sz-2
    while (left < right) //第n个和倒数n个交换  >=没有可交换的了
    {                    //循环   迭代
        int tmp = arr[left];
        arr[left] = arr[right];
        arr[right] = tmp;
        left++;
        right--;
    }
}

int main()
{ //字符串反向排序(字符串数组存储内容反向) 函数实现
    char arr[] = "abcdef";
    reverse(arr);
    printf("%s\n", arr);
    return 0;
}

方法二:递归实现(只有一个参数)

#include <stdio.h>
#include <string.h>
//只有一个参数 递归实现
int my_strlen(char *str)
{
    int count = 0;
    while (*str != '\0')
    {
        count++;
        str++;
    }
    return count;
}

// 字符串逆序
//字符串反向排序(字符串数组存储内容反向) 递归实现
void reverse(char *str)
{ //逆序 abcdef ->交换af+逆序bcde ->交换af 交换be+逆序cd -> 交换af 交换be 交换cd
    // 1.tmp=a a=f (暂时不把a放到f处)2.f=\0(让从b开始向后组成一个字符串)3.逆序bcde 4.f=tmp
    char tmp = *str;
    int len = my_strlen(str);
    *str = *(str + len - 1); //这里不能sizeof求字符串字符串大小,这里数组没有传过来,传的是地址
    *(str + len - 1) = '\0';
    if (my_strlen(str + 1) >= 2) //中间剩一个字符就不用逆序了
        reverse(str + 1);        //要加限制条件否则会死递归
    *(str + len - 1) = tmp;
}

int main()
{
    char arr[] = "abcdef";
    reverse(arr);
    printf("%s\n", arr);
    return 0;
}

方法三:递归实现(多参数)     以下代码是错误示范

#include <stdio.h>
//多参数(arr right left)递归实现
//逆序abcdef :先用left和right锁定的a和f进行交换 逆序bcde (left+1 right-1 再让新left和新right锁定的字符be进行交换 逆序cd)
//直到left >=right 中间没有可以交换元素
//不需要\0找结束位置,直接用left right 限制范围

void reverse(char arr[], int left, int right)
{
    char tmp = arr[left];//元素交换了之后,再判断left<right,满足再次逆序中间的元素
    arr[left] = arr[right];
    arr[right] = tmp;
    if (left < right)
        reverse(arr, left + 1, right - 1);
}

int my_strlen(char *str)
{
    int count = 0;
    while (*str != '\0')
    {
        count++;
        str++;
    }
    return count;
}

int main()
{
    char arr[] = "abcdef";
    int left = 0;
    int right = my_strlen(arr) - 1;
    reverse(arr, left, right); //将arr中left锁定的元素和right的元素之间的字符串进行逆序
    printf("%s\n", arr);
    return 0;
}

C语言初阶习题_习题_04

发现cd无法逆序,为什么?同时,当字符串是奇数个字符时又会逆序正确,偶数个字符则会逆序错误?

void reverse(char arr[], int left, int right)
{
    char tmp = arr[left];//元素交换了之后,再判断left<right,满足再次逆序中间的元素
    arr[left] = arr[right];
    arr[right] = tmp;
    if (left < right)
        reverse(arr, left + 1, right - 1);
}

分析:先进行交换,在判断是否有中间元素,有就把中间元素逆序,这个代码思路感觉没有错,用实例来代入一下:

eg “ab"

第一次进入reverse():得到的参数:&arr[0]  left=0 right=1   先进行元素交换(left和right指向的元素进行交换),交换完为:“ba”,此时left=0 right=1(从main中接收过来一直没有改变left和right的值)满足判断条件,又递归进入reverse()  left + 1, right - 1

第二次进入reverse():得到的参数: &arr[0] left=1 right=0,先进行元素交换,交换完为:“ab”,再进行条件判断,此时left=1 ,right=0递归结束

所以全程一共交换了两次,相当于没有逆序

eg"abc"

第一次进入reverse():得到的参数:&arr[0]  left=0 right=2   先进行元素交换,交换完为:“cba”,此时left=0 right=2 满足递归判断条件,又递归进入reverse()  left + 1, right - 1

第二次进入reverse():得到的参数: &arr[0] left=1 right=1,先进行元素交换,因为此时left和right都指向了同一个元素,交换完还是为:“cba”,再进行条件判断,此时left=1 ,right=1 递归结束

eg"abcd"

第一次进入reverse():得到的参数:&arr[0]  left=0 right=3   先进行元素交换,交换完为:“dbca”,此时left=0 right=3 满足递归判断条件,又递归进入reverse()  left + 1, right - 1

第二次进入reverse():得到的参数: &arr[0] left=1 right=2,先进行元素交换,交换完还是为:“dcba”,此时left=1 ,right=2 满足递归判断条件,又递归进入reverse()  left + 1, right - 1

第三次进入reverse():得到的参数:&arr[0] left=2 right=1,先进行元素交换,交换完为:“dbca”,再进行条件判断,此时left=2 ,right=1递归结束   

中间那个的bc没有逆序

小结:left<right时中间才有元素进行交换,但是上面的程序却在left>=right时仍然进行了一次交换,所以出错了,奇数最后一次交换的是一个元素,相当于没有交换,所以逆序结果还是正确的,偶数是最中间的两个元素交换了两次,所以逆序结果出错

改进:元素进行交换时也放在left<right判断条件下,避免多余的交换

void reverse(char arr[], int left, int right)
{
    if (left < right)
    {
        char tmp = arr[left];//元素交换了之后,再判断left<right,满足再次逆序中间的元素
        arr[left] = arr[right];
        arr[right] = tmp;
        reverse(arr, left + 1, right - 1);
    }
            
}

2.计算一个数的每位之和(递归):输入非负整数,返回组成它的数字之和

#include <stdio.h>
//#include <stdio.h>
//计算一个数的每位之和(递归)
int DigitSum(unsigned int n) // 1234
{                            // DigitSum(1234)->DigitSum(123)+4->DigitSum(12)+3+4->DigitSum(1)+2+3+4
    if (n > 9)               //两位数及以上才进行拆分 一位数不用拆
        return DigitSum(n / 10) + n % 10;
    else
        return n;
}

int main()
{
    unsigned int n = 0;
    scanf("%u", &n);
    int sum = DigitSum(n);
    printf("%d\n", sum);
    return 0;
}
int DigitSum(unsigned int n) // 1234
{                            // DigitSum(1234)->DigitSum(123)+4->DigitSum(12)+3+4->DigitSum(1)+2+3+4
    if (n > 9)               //两位数及以上才进行拆分 一位数不用拆
        return DigitSum(n / 10) + n % 10;
    else
        return n;
}

int main()
{
    unsigned int n = 0;
    scanf("%u", &n);
    int sum = DigitSum(n);
    printf("%d\n", sum);
    return 0;
}

3.递归实现N的K次方

#include <stdio.h>
//递归实现N的K次方
double Pow(int n, int k)//不要用pow避免与库函数冲突
{                       // Pow(n,k)->n*Pow(n,k-1) (k>0)
                        // k=0   1   k>0 Pow(n,k)  k<0  1.0/Pow(n,-k) 小数
    if (k > 0)
        return Pow(n, k - 1) * n;
    else if (0 == k)
        return 1;
    else
        return 1.0 / Pow(n, -k);
}

int main()
{

    int n = 0;
    int k = 0;
    scanf("%d %d", &n, &k);
    double ret = Pow(n, k);
    printf("%lf\n", ret);
    return 0;
}

4.小乐乐上课需要走n阶台阶,因为他腿比较长,所以每次可以选择走一阶或者走两阶,那么他一共有多少种走法?

输入描述:输入包含一个整数n (1 ≤ n ≤ 30)

输出描述:输出一个整数,即小乐乐可以走的方法数。

分析:n=1 fib(n)=1   n=2  fib(n)=2  n>2 fib(n)=fib(n-1)+fib(n-2) ( fib(n)表示计算走n个台阶的走法 )  走一个台阶:只有一种走法    走两个台阶:只有两种走法(一次走一步,一次走两步)      走10个台阶有 fib(10) 种走法,第一步只走一步,还剩下9阶台阶,有fib(9)种步法;第一步走两步,还剩下8阶台阶,有fib(8)种步法。一共有fib(8)+fib(9)种步法=======> 走n个台阶,有fib(n)种走法,按第一步走一步和第一步走两步两种情况,一共有fib(n-1)+fib(n-2)种步法                                                                                 

#include <stdio.h>

int fib(int n)
{
    if (n <= 2)
        return n;
    else
        return fib(n - 1) + fib(n - 2);
}

int main() 
{
    int n = 0;
    scanf("%d", &n);
    int m = fib(n);
    printf("%d", m);
    return 0;
}


数组习题

1.

C语言初阶习题_习题_05

分析:答案:C a[10]=2 数组a[10]只有10 个元素下标0~9,此处越界访问了

2.

C语言初阶习题_习题_06

分析:(3,4)逗号表达式 从左向右依次计算,整个表达式的结果是最后一个表达式结果 (3,4)= 4      答案:B

int arr[] = {1,2,4,5};//{1,2,(3,4),5}  4*4=16byte

补充:

int num = 10;    //num类型是int
int arr[10] = {0}//数组arr类型是int [10](去掉数组名剩下的部分)

//两种等价的写法
printf("%d\n", sizeof(arr));     //数组名 40
printf("%d\n", sizeof(int [10]));//数组的类型 40
//注意10不能省略掉 10也是类型的一部分
printf("%d\n", sizeof(int [5])); //20 换个数字就是另外一个数组的类型

C语言初阶习题_C语言_07

3.

char str[]="hello world";
printf("%d\n",sizeof(str));//12 h e l l o _ w o r l d \0
printf("%d\n",strlen(str));//11 h e l l o _ w o r l d

sizeof是一个操作符,是用来变量或类型(类型不占空间的,还是看的这个类型所创建出来的变量)所占内存空间的大小,不关注内存中存放的具体内容。 单位是字节

strlen()是一个库函数,是专门求字符串长度的,只能针对字符串,从参数给定的地址向后一直找\0,统计\0之前出现的字符的个数

4.

C语言初阶习题_C语言_08

分析:不是字符串长度,acY没有\0字符串长度是不确定的,可以大于或等于acX   数组长度:数组的元素个数   答案:C

注意:

  • 随着数组下标由小变大,数组地址由低到高变化
  • int arr[][3]={{0,2},{},{3,4,5}};//错误初始化 中间不能加一个空的{}

5.交换数组:将数组A和数组B的内容进行交换

#include <stdio.h>
int main()
{ //交换数组 (内容进行交换) 两个数组一样大
    int arr1[] = {1, 3, 5, 7, 9};
    int arr2[] = {2, 4, 6, 8, 0};
    /*  //错误的示范
      int tmp[] = {0};
      //1.tmp中就一个元素空间不够
      //2.数组名是首元素地址  地址是一个常量值 不是空间 无法进行交换
      tmp = arr1;
      arr1 = arr2;
      arr2 = tmp;*/
    int i = 0;
    int sz = sizeof(arr1) / sizeof(arr1[0]);
    for (i = 0; i < sz; i++)
    {
        int tmp = arr1[i];
        arr1[i] = arr2[i];
        arr2[i] = tmp;
    }
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr1[i]);
    }
    printf("\n");
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr2[i]);
    }
    return 0;
}

6.数组操作:创建一个整型数组,完成对数组的操作

  1. 实现init()初始化数组为全0
  2. 实现print() 打印数组的每个元素
  3. 实现reverse() 完成数组元素的逆置
#include <stdio.h>
//数组操作
//初始化函数 初始化为0
//打印函数
//逆置函数
void init(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        arr[i] = 0;
    }
}

void print(int arr[], int sz)
{
    int i = 0;
    for (i = 0; i < sz; i++)
    {
        printf("%d ", arr[i]);
    }
    printf("\n");
}

void reverse(int arr[], int sz)
{
    int left = 0;
    int right = sz - 1;
    while (left < right)
    {
        int tmp = arr[left];
        arr[left] = arr[right];
        arr[right] = tmp;
        left++;
        right--;
    }
}

int main()
{
    int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    int sz = sizeof(arr) / sizeof(arr[0]);
    print(arr, sz); //初始化前
    reverse(arr, sz);
    print(arr, sz); //逆序后
    init(arr, sz);
    print(arr, sz); //初始化后
    return 0;
}

7.有一个整数序列(可能有重复的整数),现删除指定的某一个整数,输出删除指定数字之后的序列,序列中未被删除数字的前后位置没有发生改变。

输入描述:

  • 第一行输入一个整数(0≤N≤50)。
  • 第二行输入N个整数,输入用空格分隔的N个整数。
  • 第三行输入想要进行删除的一个整数。

输出描述:输出为一行,删除指定数字之后的序列。

#include <stdio.h>

int main() 
{
    int n;
    scanf("%d", &n);
    int arr[n];//支持c99
   // int arr[50] = {0};
    int i = 0;
    for (i = 0; i < n; i++) 
    {
        scanf("%d", &arr[i]);
    }
    int del = 0;
    scanf("%d", &del);
    int j = 0; 
    //j作为下标锁定的位置就是用来存放不删除的数据的
    //不需要创建新数组存放
    for (i = 0; i < n; i++) 
    {
        if (arr[i] != del) 
        {
            // arr[j]=arr[i];
            //j++; //两种写法等价
            arr[j++] = arr[i];
        }
    }
    for (i = 0; i < j; i++) 
    {
        printf("%d ", arr[i]);
    }
    return 0;
}

8.输入n个成绩,换行输出n个成绩中最高分数和最低分数的差。

输入描述:

  • 两行,第一行为n,表示n个成绩,不会大于10000。
  • 第二行为n个成绩(整数表示,范围0~100),以空格隔开。

输出描述:一行,输出n个成绩中最高分数和最低分数的差。

方法一:

#include <stdio.h>

int main() 
{
    int n = 0;
    scanf("%d", &n);
    int arr[n];
    int i=0;
    for(i=0;i<n;i++)
    {
        scanf("%d",&arr[i]);
    }
    int max=arr[0];
    for(i=0;i<n;i++)
    {
        if(arr[i]>max)
        {
            max=arr[i];
        }
    }
    int min=arr[0];
    for(i=0;i<n;i++)
    {
        if(arr[i]<min)
        {
            min=arr[i];
        }
    }
    printf("%d",max-min);
    return 0;
}

方法二://代码优化

#include <stdio.h>

int main()
{
    int n = 0;
    scanf("%d", &n);
    int arr[n];
    int i = 0;
    int max = 0;
    int min = 100;
    for (i = 0; i < n; i++)
    {
        scanf("%d", &arr[i]);
        if (arr[i] > max)
            max = arr[i];
        if (arr[i] < min)
            min = arr[i];
    }
    printf("%d", max - min);
    return 0;
}

操作符习题

1.下面代码的结果是( )

C语言初阶习题_习题_09

答案:B 

分析:
c=++a;//先++再使用 a=a+1=6  c=a=6   
b=++c,c++,++a,a++;
//=优先级大于逗号表达式  
//b=++c c=c+1=7 b=c=7
//c++ c=c+1=8      ++a a=a+1=7 a++ a=a+1=8 
b+=a++ + c;
//b=b+(a++)+c=7+8+8=23   a++ a=a+1=9 
//a=9 b=23 c=8

2.统计二进制中1的个数,写一个函数返回参数二进制中1的个数

#include <stdio.h>
//方法1
/*int count_1(unsigned int n)
{ // 10 二进制:1010   十进制 %10 /10取出十进制每一位  1234   二进制:%2 /2 得到二进制每一位
	// 10%2=0  10/2=5  5%2=1  5/2=2  2%2=0  2/2=1  1%2=1  1/2=0
	//取出二进制的每一位就是取模的值  从最后一位开始
	int count = 0;
	while (n)
	{
		if (n % 2 == 1)
			count++;
		n /= 2;
	}
	return count;
}*/
//问题:输入负整数出错
// eg  -1
// 10000000 00000000 00000000 00000001原码
// 11111111 11111111 11111111 11111110 反码
// 11111111 11111111 11111111 11111111 补码
//补码中32个1  按理说应该会输出32 结果却输出0
//改进:形参设置为无符号类型 将传递过来的-1 的补码看成很大的正数(第一位不再看成符号位)

//方法2    负数正数都行
/*int count_1(int n)
{
	int count = 0, i = 0;
	for (i = 0; i < 32; i++)
	{
		if ((n >> i) & 1 == 1)
			//把数字n的二进制数的每一位移到到最低位 &1判断1/0
			count++;
	}
	return count;
}*/

//法1法2效率不高

//方法3
// n=15 
// n=n&(n-1)
//1111  n
//1110  n-1
//1110  n
//1101  n-1
//1100  n
//1011  n-1
//1000  n
//0111  n-1
//0000  n     发现每进行一次按位与就会消失一个1  统计1的个数,可以看这个表达式执行几次即可
//只关注1的个数  效率高

int count_1(int n)
{
	int count = 0;
	while (n)
	{
		n = n & (n - 1);
		count++;
	}
	return count;
}
//如果想判断一个数是否为2^n
//2^1  2  0010
//2^2  4  0100
//2^3  8  1000  发现2^n中二进制序列始终只有一个1
//if(n&(n-1)==0)  ===>n就是2^n  (n&(n-1)执行一次去掉一个1,而2^n只有一个1) 

int main()
{ //统计二进制中1的个数
	int n;
	scanf("%d", &n);
	int m = count_1(n);
	printf("%d\n", m);
	return 0;
}

3.求两个数二进制中不同的个数

C语言初阶习题_C语言_10

#include <stdio.h>

// 两个int  二进制序列中不同的位数的统计
//方法1
/*int count_diff(int m, int n)
{
    int count = 0, i = 0;
    for (i = 0; i < 32; i++)
    {
        if (((m >> i) & 1) != ((n >> i) & 1))
        {
            count++;
        }
    }
    return count;
}*/

//方法2
int count_diff(int m, int n)
{
    int num = m ^ n;
    //相同为0 相异为1 只关注相异的
    int count = 0;
    while (num)
    {
        num = num & (num - 1);
        count++;
    }
    return count;
}

int main()
{
    int m = 0, n = 0;
    scanf("%d %d", &m, &n);
    int ret = count_diff(m, n);
    printf("%d", ret);
    return 0;
}

4.打印整数二进制的奇数位和偶数位,获取整数的二进制序列中的所有的偶数位和奇数位,分别打印出二进制序列

//假设最低位为第1位
//10
//00000000 00000000 00000000 00001010

#include <stdio.h>
int main()
{
	//获取奇数位数字   第N位来到最低位移动N-1
	int num = 0;
	scanf("%d", &num);
	int i = 0;
	//第31位移动30位到最低位  第1位移动0位到最低位
	for (i = 30; i >= 0; i-=2)
	{
		printf("%d ", ((num >> i) & 1));
	}
  printf("\n");
	//获取偶数位数字
	// 第32位移动31位到最低位  第2位移动1位到最低位
	for (i = 31; i >= 1; i-=2)
	{
		printf("%d ", ((num >> i) & 1));
	}

	return 0;
}

5.

C语言初阶习题_C语言_11

答案:D  分析:vs:4+4+4=12  linux:3+3=6  6+4=10 问题代码

6

C语言初阶习题_C语言_12

//全局变量 静态变量都是放在静态区的  
//全局变量 静态变量不初始化的时候,默认会被初始化为0
//局部变量放在栈区不初始化默认会被初始化为随机值

//sizeof这个操作符计算返回的结果是size_t类型的,是无符号整型的

//表达式中有int和unsigned int会进行算术转换 int -> unsigned int   
//有符号int:-1-->
//无符号int:11111111 11111111 11111111 11111111 看成一个很大的正整数
//10000000 00000000 00000000 00000001 
//11111111 11111111 11111111 11111110
//11111111 11111111 11111111 11111111 补码
//答案:

7  打印X形图案

输入描述: 多组输入,一个整数(2~20),表示输出的行数,也表示组成“X”的反斜线和正斜线的长度。

输出描述: 针对每行输入,输出用“*”组成的X形图案。

#include <stdio.h>

int main() 
{
    int i = 0, j = 0, num = 0;
    while (scanf("%d", &num) != EOF) 
    {
        for (i=0;i<num;i++)
        {
            for(j=0;j<num;j++)
            {
                if(j==i) printf("*");
                else if(j==num-1-i) printf("*");
                else printf(" ");
            }
            printf("\n");
        }
    }
    return 0;
}

指针习题

1.下面代码的结果是

C语言初阶习题_C语言_13

分析:short*类型指针的特点,解引用一次可以访问两个字节  +1一次可以跳过两个字节      数据在内存中存放时,有一个顺序的问题:大小端字节序

整型数据在内存中存放时是倒着存放的

C语言初阶习题_习题_14

C语言初阶习题_习题_15

C语言初阶习题_习题_16

输出00345

2  

C语言初阶习题_习题_17

C语言初阶习题_C语言_18

输出:6      12     答案:C

3

C语言初阶习题_C语言_19

答案:C          分析:  D指针有关系运算可以比较大小

4

C语言初阶习题_C语言_20

分析:整数在内存中是倒序存放

任何一个变量/表达式都有两个属性:值属性 类型属性  

int a=3;
a+4.5——>值属性:7.5 类型属性double(int算术转换为double+double)
a=3——>值属性:3 类型属性:int
&a——>值属性:a的地址 类型属性:int*

C语言初阶习题_习题_21

答案:C

5 使用指针打印数组内容

C语言初阶习题_习题_22

C语言初阶习题_C语言_23

6 字符串逆序

C语言初阶习题_习题_24

C语言初阶习题_习题_25

使用scanf(),遇到空格就不读取了所以不用scanf()用gets()

C语言初阶习题_C语言_26

第一个和最后一个交换,以此类推

#include <stdio.h>
#include <string.h>
int main()
{
    char arr[10001] = {0};
    //接收字符串有空格  使用scanf(),遇到空格就不读取了
    gets(arr);
    int left = 0;
    int right = strlen(arr) - 1;
    while (left < right)
    {
        char tmp = arr[left];
        arr[left] = arr[right];
        arr[right] = tmp;
        left++;
        right--;
    }
    printf("%s\n", arr);
    return 0;
}

7

C语言初阶习题_C语言_27

#include <stdio.h>
int main()
{ //求Sn=a+aa+aaa+aaaa+aaaaa 前5项之和
	int a = 0;
	int n = 0;
	scanf("%d %d", &a, &n);//a代表每一项数字  n:项数
	int i = 0;
	int sum = 0;
	int k = 0;//每一项代表的数字
	for (i = 0; i < n; i++)
	{
		k = k * 10 + 2;
		sum += k;
	}
	printf("%d\n", sum);
	return 0;
}

8   求0~100000的水仙花数并输出:n位数字的各位数字的n次方之和等于本身eg:153=13+53+33

//这里的水仙花数不是严格意义上的水仙花数(水仙花数一般指三位自幂数) 
//12345
#include <stdio.h>
#include <math.h>
//方法一
int main()
{
	int i = 0;
	for (i = 0; i <= 100000; i++)
	{
		//1.计算i是几位数 ->n  2.得到i的每一位 计算n次方之和
	//认为任何数至少是一位数n从1开始
		int n = 1;
		int tmp = i;
		//避免在循环内部改变循环变量 而且下面还要计算i的每一位n次方之和
		while (tmp / 10)
		{
			n++;
			tmp /= 10;
		}
		tmp = i;
		int sum = 0;//每个i都要进行计算不能放到循环外面去
		while (tmp)
		{
			sum += pow(tmp % 10, n);//pow返回类型为double型,会有算术转换造成精度丢失 但是我们知道这里是整数没有误差的
			tmp /= 10;
		}
		if (sum == i)
		{
			printf("%d ",i);
		}

	}
	return 0;
}
//方法二:函数
#include <stdio.h>
#include <math.h>

int if_narcissistic_number(int i)
{

	//1.计算i是几位数 ->n  2.得到i的每一位 计算n次方之和
	//认为任何数至少是一位数n从1开始
	int n = 1;
	int tmp = i;
	//避免在循环内部改变循环变量 而且下面还要计算i的每一位n次方之和
	while (tmp / 10)
	{
		n++;
		tmp /= 10;
	}
	tmp = i;
	int sum = 0;//每个i都要进行计算不能放到循环外面去
	while (tmp)
	{
		sum += pow(tmp % 10, n);//pow返回类型为double型,放到int造成精度丢失 但是我们知道这里是整数没有误差的
		tmp /= 10;
	}
	/*if (sum == i)
	{
		return 1;
	}
	else
	{
		return 0;
	}*/
	//优化
	return sum == i;

}

int main()
{
	int i = 0;
	for (i = 0; i <= 100000; i++)
	{
		if (if_narcissistic_number(i))//_+小写字母的书写习惯
		{
			printf("%d ",i);
		}
	}
	return 0;
}

9   打印菱形

C语言初阶习题_C语言_28

//上+下  上面有line行 下面line-1行
#include <stdio.h>
int main()
{
    //上
    int i = 0;
    int line = 0; //打印上半部分的行数
    scanf("%d", &line);
    for (i = 0; i < line; i++)
    {
        //打印每一行
        int j = 0;
        //打印空格
        for (j = 0; j < line - 1 - i; j++)
        {
            printf(" ");
        }
        //打印*
        for (j = 0; j < 2 * i + 1; j++)
        {
            printf("*");
        }
        printf("\n");
    }

    //下
    for (i = 0; i < line - 1; i++)
    {
        //打印每一行
        int j = 0;
        //打印空格
        for (j = 0; j <= i; j++)
        {
            printf(" ");
        }
        //打印*
        for (j = 0; j < 2 * (line - 1 - i) - 1; j++)
        {
            printf("*");
        }
        printf("\n");
    }
    return 0;
}

10

C语言初阶习题_C语言_29

答案:A  分析:int(*arr)[10]:arr是一个数组指针(指向了[10]),指向数组的指针*arr arr与*组合表示arr是指针;数组arr[10] arr与[10]结合表示arr是数组名

结构体习题

1

C语言初阶习题_习题_30

C语言初阶习题_C语言_31

C语言初阶习题_习题_32

答案:B  分析:优先级高于* 不加()就不行 p.a 本身就是错的解引用又用在了a上也是错的

2

C语言初阶习题_习题_33

分析:输出:wang

3.喝汽水问题

C语言初阶习题_习题_34

#include <stdio.h>
int main()
{
    int money = 0;
    scanf("%d", &money);
    /*int total = money;//方法一
    int empty = money;
    //置换
    while (empty >= 2)
    {
        total += empty / 2;
        empty = empty % 2 + empty / 2;
    }
    printf("%d\n", total);*/

    //规律  2*money-1  方法二
    if (money > 0)
        printf("%d\n", 2 * money - 1);
    else
        printf("%d\n", 0);

    return 0;
}
上一篇:栈(一)
下一篇:没有了
网友评论