2022年C语言的谜题库,你知道几个?

顺序

青春如梦,岁月如花,水如岁月,转瞬即逝。

你好,这是狐狸~~

今天是2022年1月12日,距离农历新年还有18天。时间过得很快。过完腊八,大部分同学都已经放假了。大年三十,但事实并非如此,只是快乐的人不再是你。

今天给大家来点不一样的,C语言拼图库,以及一些让人困惑的错误,为大家做一个总结。应该有一些你经常放错地方的地方。希望看完之后,你至少不会知道这些问题。再犯一个错误。

C语言的15个谜题1、下面的程序不一定会输出HelloWorld,你知道为什么吗?

#include
#include
int main()
{
    while(1)
    {
        fprintf(stdout,"HelloWorld");
        fprintf(stderr,"HelloWorld");
        sleep(1);
    }
    return 0;
}
 

参考答案:stdout 和 stderr 是同一个设备描述符吗?stdout 是块设备,而 stderr 不是。对于块设备,只会输入以下条件,

1)遇到回车

2)缓冲区已满

3)flush 被调用。而 stderr 没有。

2、下面的程序看起来很正常,并使用逗号表达式进行初始化。不幸的是,这个过程是有问题的。你知道为什么吗?

#include
int main()
{
    int a = 1,2;
    printf("a : %d\n",a);
    return 0;
}

参考答案:这个程序会报编译错误(语法错误),逗号表达式是正确的,但是在初始化和变量声明中,逗号不是逗号表达式的意思。为了区分这一点,修改上面的程序,需要加括号: int a = (1,2);

3、下面的程序会产生什么样的输出?

#include
int main()
{
    int i=43;
    printf("%d\n",printf("%d",printf("%d",i)));
    return 0;
}

参考答案:程序会输出4321,你知道为什么吗?要知道为什么,你需要知道 printf 的返回值是什么。printf 的返回值是打印的字符数。

3、根据考试成绩打印出百分位数。

switch(grade)
{ case 'A':printf("85~100\n");
case 'B':printf("70~84\n");
case 'C':printf("60~69\n");
case 'D':printf("<60\n");
default:printf("error\n");

参考答案:因为省略了break语句,所以case只起到了标签的作用,而不是判断。因此,当等级值为A时,printf函数在执行完第一条语句后执行第五条printf函数语句。正确的拼写是加“break;” 在每个分支之后。例如

case 'A':printf("85~100\n");break;

4、忽略while和do-while语句的细节区别

main()
  {int a=0,I;
  scanf("%d",&I);
  while(I<=10)
  {a=a+I;
  I++;
  }
  printf("%d",a);
  }
  (2)main()
  {int a=0,I;
  scanf("%d",&I);
  do
  {a=a+I;
  I++;
  }while(I<=10);
  printf("%d",a);
  }

参考答案:可以看出,当输入I的值小于等于10时,两者得到的结果是一样的。当 I>10 时,两种结果不同。因为while循环是先判断后执行,而do-while循环是先执行后判断。对于大于 10 的数字,while 循环不执行循环体一次,而 do-while 语句执行循环体一次。

5、定义数组时变量使用不正确

   int n;
  scanf("%d",&n);
  int a[n];

参考答案:方括号中的数组名是常量表达式,可以包括常量和符号常量。也就是说,C 不允许动态定义数组的大小。

6、请说下面程序的输出是什么?并解释为什么?(注意程序不输出“b is 20”)

#include
int main()
{
    int a=1;
    switch(a)
    {
        int b=20;
        case 1:
            printf("b is %d\n",b);
            break;
        default:
            printf("b is %d\n",b);
        break;
    }
    return 0;
}

参考答案:程序编译时,可能会出现warning: unreachable code at the beginning of switch statement。我们以为进入switch后,变量b会被初始化,但事实并非如此,因为switch-case语句会直接跳过变量b的初始化。所以,程序会输出一个随机的内存值。

7、以下程序的潜在危险是什么?

#include
int main()
{
    char str[80];
    printf("Enter the string:");
    scanf("%s",str);
    printf("You entered:%s\n",str);
    return 0;
}

参考答案:这个问题很简单。这个程序的潜在问题是,如果用户输入的长度超过80个字符,就会出现数组越界问题,你的程序很可能会崩溃。

8、以下程序的输出是什么?

#include
int main()
{
    int i;
    i = 10;
    printf("i : %d\n",i);
    printf("sizeof(i++) is: %d\n",sizeof(i++));
    printf("i : %d\n",i);
    return 0;
}

参考答案:如果你认为输出是,10,4,11

那你错了,第三个错了,第一个是10,没问题,第二个是4c程序设计语言第二版答案,也没问题,因为一个int在32位机器上有4个字节。但是为什么第三个不输出11呢?还是10吗?原因是sizeof不是函数,而是求i++的类型大小的运算符,这是程序运行前(编译时)可以做的事情,所以sizeof(i++)直接换成4吧,运行时不会有 i++ 表达式。

9、定义数组时,定义的“元素个数”被误认为是可以使用的最大下标值

main()
  {static int a[10]={1,2,3,4,5,6,7,8,9,10};
  printf("%d",a[10]);
  }

参考答案:C语言规定:定义时使用a[10],表示a数组有10个元素。它的下标值从0开始,所以数组元素a[10]不存在。

10、下面程序的输出是什么?(绝对不是 10)

参考答案:这道题的输出是100。为什么?问题出在 y = y/*p;,我们原本以为是 y/(*p),然而,我们没有加空格和括号,结果 /* in y/*p 被解释为注释开始。所以,这也是整个噩梦的开始。

11、下面的输出是什么?

 #include
int main()
{
    int i = 6;
    if( ((++i < 7) && ( i++/6)) || (++i <= 9));
    printf("%d\n",i);
    return 0;
}

参考答案:这个问题不是简单的测试前缀++或反后缀++。本题主要考&&和||的短路判断。所有短路求值: For (Condition 1 && Condition2)c程序设计语言第二版答案,如果“Condition 1”为假,则“Condition 2”的表达式将被忽略。 For (Condition 1 || Condition2) ,如果“条件1”为真,则“条件2”的表达被忽略。所以,相信你会知道这个问题的答案是什么。

12、下面的C程序合法吗?如果是,输出是什么?

#include
int main()
{
    int a=3, b = 5;
    printf(&a["Ya!Hello! how is this? %s\n"], &b["junk/super"]);
    printf(&a["WHAT%c%c%c %c%c %c !\n"], 1["this"],2["beauty"],0["tool"],0["is"],3["sensitive"],4["CCCCCC"]);
    return 0;
}

参考答案:这个例子是合法的,输出如下:

你好!这怎么样?超级那是C!这个例子主要展示了另一种用法。下面两种用法是一样的:

“你好”[2] 2[“你好”]

如果知道:a[i]其实就是*(a+i),也就是*(i+a),那么写成i[a]应该不难理解。

13、下面程序的输出是什么?(假设:输入你好,世界)

#include
int main()
{
    char dummy[80];
    printf("Enter a string:\n");
    scanf("%[^r]",dummy);
    printf("%s\n",dummy);
    return 0;
}

参考答案:这个例子的输出是“Hello, Wo”,scanf中的“%[^r]”是干扰它的东西。这意味着它在遇到字符 r 时结束。

14、在不应该的地方添加了地址运算符 &。

 scanf("%s",&str);

参考答案:C语言编译系统对数组名的处理是:数组名代表数组的起始地址,scanf函数中的输入项是字符数组名,不需要加上地址字符 &。应改为:

 scanf("%s",str);

15、 定义函数中的形参和局部变量


int max(x,y)
  int x,y,z;
  {z=x>y?x:y;
  return(z);
  }

参考答案:形参应该定义在函数体之外,局部变量应该定义在函数体内部。应改为:

int max(x,y)
int x,y;
{int z;
z=x>y?x:y;
return(z);
}

总结

本文展示了 14 个 C 语言谜题和答案。代码应该够清晰了,相信我们在日常工作中可能会遇到不少例子。通过这些谜题,希望你能更好地理解C语言。如果不看答案,不知道你是否有足够的信心回答每一个谜题?大家可以试试!

以后我会发布更多的项目资源或者学习资料。希望大家继续关注。如果您有任何问题,您可以留言。收到C/C++学习资料和其他项目源码的可以加群【1083227756】学习。如果你对程序员未来的发展感兴趣,可以关注微信公众号:【狐狸的编码时间】,希望和大家一起学习进步!

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论