比特C语言小练

文章涵盖了C语言中的表达式求值规则,包括了对++运算符的复杂用法,指出表达式可能因计算顺序不同产生不同结果。同时,介绍了计算水仙花数的方法,以及如何通过指针遍历数组和打印内容。还讨论了结构体成员访问和二级指针的概念。最后,给出了字符串逆序的函数实现。
摘要由CSDN通过智能技术生成

下面代码的结果是:(D

#include <stdio.h>

int main()

{

int i = 1;

int ret = (++i)+(++i)+(++i);

printf("ret = %d\n", ret);

return 0;

}

A. 10 B. 12 C. 9 D. 程序错误

答案解析:

表达式(++i)+(++i)+(++i),只有操作符的优先级和结合性,没法确定唯一计算路径

所以这个表达式可能因为计算顺序的差异导致结果是不一致的,所以表达式是错误的表达式。

可以在VS和Linux gcc测试,结果可能有差异。

关于表达式求值说法不正确的是:(D

A. 表达式求值先看是否存在整形提升或算术转换,再进行计算

B. 表达式真正计算的时候先看相邻操作符的优先级决定先算谁

C. 相邻操作符的优先级相同的情况下,看操作符的结合性决定计算顺序

D. 只要有了优先级和结合性,表达式就能求出唯一值

答案解析:

D: 错误,有了优先级和结核性,表达式也有可能有不同的计算机路径,导致计算结果的差异。

下面代码的结果是:A

#include <stdio.h>

int i;

int main()

{

i--;

if (i > sizeof(i))

{

printf(">\n");

}

else

{

printf("<\n");

}

return 0;

}

A. > B. < C. 不输出 D. 程序有问题

答案解析:

C语言中,0为假,非0即为真。

全局变量,没有给初始值时,编译其会默认将其初始化为0。

i的初始值为0,i--结果-1,i为整形,sizeof(i)求i类型大小是4,按照此分析来看,结果应该选择B,但是sizeof的返回值类型实际为无符号整形,因此编译器会自动将左侧i自动转换为无符号整形的数据,-1对应的无符号整形是一个非常大的数字,超过4或者8,故实际应该选择A

计算求和求Sn=a+aa+aaa+aaaa+aaaaa的前5项之和,其中a是一个数字,例如:2+22+222+2222+22222

/*思路:
通过观察可以发现,该表达式的第i项中有i个a数字,因此:
假设第i项为temp,则第i+1项为temp*10+a
具体参考以下代码*/
int main()
{
    int a = 0;
    int n = 0;
    int i = 0;
    int sum = 0;
    int tmp = 0;
    scanf("%d%d", &a, &n);
    for(i=0; i<n; i++)
    {
        tmp = tmp*10+a;
        sum += tmp;
    }
    printf("%d\n", sum);

    return 0;
}

打印水仙花数

求出0~100000之间的所有“水仙花数”并输出。

“水仙花数”是指一个n位数,其各位数字的n次方之和确好等于该数本身,如:153=1^3+5^3+3^3,则153是一个“水仙花数”。

/*思路:
此题的关键在于只要知道判断一个数据是否为水仙花数的方式,问题就迎刃而解。假定给定一个数据data,具体检测方式如下:
1. 求取data是几位数
2. 获取data中每个位置上的数据,并对其进行立方求和
3. 对data中每个位上的数据立方求和完成后,在检测其结果是否与data相等即可,
相等:则为水仙花数
否则:不是
具体实现参考以下代码。*/
int main()
{
    int i = 0;
    for(i=0; i<=999999; i++)
    {
        int count = 1;
        int tmp = i;
        int sum = 0;
        //判断i是否为水仙花数
        //1. 求判断数字的位数
        while(tmp/10)
        {
            count++;
            tmp = tmp/10;
        }
        //2. 计算每一位的次方和
        tmp = i;
        while(tmp)
        {
            sum += pow(tmp%10, count);
            tmp = tmp/10;
        }
        //3. 判断
        if(sum == i)
            printf("%d ", i);
    }
    return 0;
}

使用指针打印数组内容

写一个函数打印arr数组的内容,不使用数组下标,使用指针。

arr是一个整形一维数组。

int main()
{
    int arr[] = {1,2,3,4,5,6,7,8,9,10};
    //在这里完成代码
    // 分析:因为数组中存储的元素类型是int类型的,因此只要给一个int的指针,依次取索引数组中的每个元素即可
    int* p = arr;  // 数组名代表数组首元素的地址
    for(int i = 0; i < sizeof(arr)/sizeof(arr[0]); ++i)
    {
        printf("%d ", *p);   // *p: 取到p所指向位置的元素
        ++p;                 // 获取p的下一个位置
    }
       return 0;
}

下面程序要求输出结构体中成员a的数据,以下不能填入横线处的内容是(B)

#include < stdio.h >

struct S

{

int a;

int b;

};

int main( )

{

struct S a, *p=&a;

a.a = 99;

printf( "%d\n", __________);

return 0;

}

A. a.a B. *p.a C. p->a D. (*p).a

答案解析:

结构体类型变量需要访问其成员时,用.运算符,如果是指向结构体变量的指针访问时,需要用->,或者先对指针解引用,取到指向的结构体类型的变量,再通过.访问,但是要注意优先

如有以下代码:则下面的叙述不正确的是:(D )

struct student

{

int num;

char name[32];

float score;

}stu;

A. struct 是结构体类型的关键字 B. struct student 是用户定义的结构体类型

C. num, score 都是结构体成员名 D. stu 是用户定义的结构体类型名

答案解析:

A:正确,在C语言中需要自定义类型时,要用到struct关键字

B:正确:在C语言中,用struct定义的结构体,定义结构体类型变量时,需要用struct student

C:正确:结构体中的变量名称,称之为结构体的成员

D:错误:stu是定义的结构体类型变量,不是名称,如果想要让stu为结构体类型名称时,必须在结构体定义时添加 typedef关键字

关于二级指针描述描述正确的是:( B

A. 二级指针也是指针,只不过比一级指针更大 B. 二级指针也是指针,是用来保存一级指针的地址

C. 二级指针是用来存放数组的地址 D. 二级指针的大小是4个字节

答案解析:

A:错误,二级指针是指针,不能说起比一级指针大,只能说二级指针指向的空间中存储的也是一个地址

B:正确

C:错误,数组的地址一般用一级指针存储,或者用数组指针接收

D:二级指针是指针,但是否占4个字节不一定,要看具体的系统

下面关于指针运算说法正确的是:( C

A. 整形指针+1,向后偏移一个字节 B. 指针-指针得到是指针和指针之间的字节个数

C. 整形指针解引用操作访问4个字节 D. 指针不能比较大小

答案解析:

注意:此题是有问题的,说法不严谨,如果将整形指针理解成int*类型的指针,那么一下说法解析如下

A:错误,整形指针+1,向后便宜一个整形类型的大小,即4个字节

B:错误,两个指针相减,指针必须指向一段连续空间,减完之后的结构代表两个指针之间相差元素的个数

C:正确,整形指向的是一个整形的空间,解引用操作访问4个字节

D:指针中存储的是地址,地址可以看成一个数据,因此是可以比较大小的

下列程序段的输出结果为(C

unsigned long pulArray[] = {6,7,8,9,10};

unsigned long *pulPtr;

pulPtr = pulArray;

*(pulPtr + 3) += 3;

printf(“%d,%d\n”,*pulPtr, *(pulPtr + 3));

A. 9,12 B. 6,9 C. 6,12 D. 6,10

答案解析:

unsigned long pulArray[] = {6,7,8,9,10};
unsigned long *pulPtr;
pulPtr = pulArray; 
// 数组名代表数组首元素地址,因此pulptr指向的是数组中第一个元素的位置
*(pulPtr + 3) += 3; 
// pulptr+3访问的是数组中第三个元素(数组下标从0开始),故将9改为9+3=12
printf(“%d,%d\n”,*pulPtr, *(pulPtr + 3)); 
// 打印第一个和第三个元素,因此:打印6和12

喝汽水问题

【题目内容】喝汽水,1瓶汽水1元,2个空瓶可以换一瓶汽水,给20元,可以多少汽水(编程实现)。

/*思路:
1. 20元首先可以喝20瓶,此时手中有20个空瓶子
2. 两个空瓶子可以喝一瓶,喝完之后,空瓶子剩余:empty/2(两个空瓶子换的喝完后产生的瓶子) + empty%2(不够换的瓶子)
3. 如果瓶子个数超过1个,可以继续换,即重复2*/
int main()
{
    int money = 0;
    int total = 0;
    int empty = 0;
    scanf("%d", &money);
    //方法1
    total = money;
    empty = money;
    while(empty>1)
    {
        total += empty/2;
        empty = empty/2+empty%2;
    }
    return 0;
}

打印菱形

【题目内容】用C语言在屏幕上输出以下图案:

/*思路:
仔细观察图形,可以发现,此图形中是由空格和*按照不同个数的输出组成的。
上三角:先输出空格,后输出*,每行中
  空格:从上往下,一行减少一个
  *:2*i+1的方式递增
下三角:先输出空格,后输出*,每行中
  空格:从上往下,每行多一个空格
  *: 从上往下,按照2*(line-1-i)-1的方式减少,其中:line表示总共有多少行
按照上述方式,将上三角和下三角中的空格和*分别输出即可。 */
int main()
{
    int line = 0;
    int i = 0;
    scanf("%d", &line);//7
    //打印上半部分
    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;
}

字符串逆序

【题目内容】写一个函数,可以逆序一个字符串的内容。

/*思路:该题比较简单,请参考代码*/
void Reverse(char* str)
{
    char* left = str;
    char* right = str + strlen(str)-1;
    while(left < right)
    {
        char temp = *left;
        *left = *right;
        *right = temp;
        ++left;
        --right;
    }
}
int main()
{
    char str[101] = {0};
    while(gets(str))
    {
        Reverse(str);
        printf("%s\n", str);
        memset(str, 0, sizeof(str)/sizeof(str[0]));
    }
    return 0;
}
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值