一、选择题
1.执行下面程序,正确的输出是(c)
A: 5,7 B: 7,5 C: 3,8 D: 8,3
答案解析:
正确答案:C
swap函数调用时没有进行传参,所以在swap函数中进行交换的是全局变量;输出语句这里
考虑局部优先的原则,故选C。
补充:
1. 作用域
作用域(scope)是程序设计概念,通常来说,一段程序代码中所用到的名字并不是总是有效/可用的而限定这个名字的可用性的代码范围就是这个名字的作用域。
(1)局部变量的作用域就是所在的局部范围。(同一个{}内)
(2)全局变量的作用域就是整个工程(注:换一个.c文件使用全局变量,要声明(extern)下变量)
注意:当全局变量与局部变量同名冲突时,遵循局部优先的原则。
2.生命周期
变量的生命周期指的是变量的创建到变量的销毁之间的一个时间段
(1) 局部变量的生命周期是:进入作用域生命周期开始,出作用域生命周期结束。
(2) 全局变量的生命周期是:整个程序的生命周期。
2.以下不正确的定义语句是( )
A: double x[5] = {2.0, 4.0, 6.0, 8.0, 10.0};
B: char c2[] = {'\x10', '\xa', '\8'};
C: char c1[] = {'1','2','3','4','5'};
D: int y[5+3]={0, 1, 3, 5, 7, 9};
答案解析:
正确答案:B
B选项考查转义字符,因为八进制数字是0-7,没有8,所以B选项中'\8'是错误的
\ddd ddd表示1到3个八进制数 如:\130 转义为 字符X
\xhh hh表示1到2位十六进制数 如:\x30 转义为 字符0
补充:字符型数据在内存中存储的是字符的ASCII码值的二进制形式,一个字符的存储占用一个字节。
3.test.c 文件中包括如下语句,文件中定义的四个变量中,是指针类型的变量为【多选】( )
A: a B: b C: c D: d
答案解析:
正确答案:ACD
因为#define是宏定义,只是直接替换,INT_PTR a, b; 进行宏替换后代码是这样的:int *a, b;这里的int *是a的类型,b的类型是int,故此时b只是int类型。而typedef是把该类型定义一个别名,别名是一个独立的类型了,使用这个类型创建的变量都是这个类型的。
所以 a,c,d才是指针类型
4、有如下定义语句,则正确的输入语句是【多选】( )
A: scanf("%d%s",&b,&c); B: scanf("%d%s",&b,c);
C: scanf("%d%s",b,c); D: scanf("%d%s",b,&c);
答案解析:
正确答案:AB
&c和c两个地址值是一样的,程序的效果相同,也没错,但同时也必须把变量b的地址给scanf,所以CD错误,AB正确
补充:
1.scanf是格式输入函数
①一般格式为:scanf(格式控制,地址列表);
其中“格式控制”规定数据的输入格式,必须用双引号括起来,其内容仅仅是格式说明。“地址列表”则由一个或多个地址组成的列表,可以是变量的地址,或字符串的首地址。
②输入数据时,在两个数据之间以一个或多个空格间隔,也可以用回车键、跳格键(tab键)。
注:当是%d,%d形式,则格式输入数据,不用空格间隔。
2.数组名是什么?
①结论:数组名是首元素的地址。
②两个例外:
1、sizeof(数组名),这里的数组名是表示整个数组,计算的是整个数组的大小,单位是字节。
2、&数组名,这里的数组名是表示整个数组,&数组名取出的是数组的地址。
5. 若给定条件表达式 (M)?(a++):(a--) ,则其中表达式 M ( )
A: 和(M==0)等价 B: 和(M==1)等价 C: 和(M!=0)等价 D: 和(M!=1)等价
答案解析:
正确答案:C
条件表达式(M)?(a++):(a--)。 (exp1)? (exp2): (exp3)为三目运算符。
计算规则为:
C语言规定:0为假,非0为真。
所以 若要求与M等价,则要满足M取0时为假,取非0数值时为真。
c选项中:假定M取0,则M表示假,当M是0时,表达式M!=0不成立,为假,计算a--; 当M取非0数值时,M为真,表达式M!=0成立,为真,计算a++; 符合题意,选C
二、编程题
输入数字 n ,按顺序打印出从 1 到最大的 n 位十进制数。比如输入 3 ,则打印出 1、2、3 一直到最大的 3 位 数 999 。
代码实例:
代码1:
static int arr[100000]; int* printNumbers(int n,int* returnsize) { //计算最大的数 int a=1; int i=0; for(i=0;i<n;i++) { a*=10; } //计算返回的个数 *returnsize=a-1; //给数组赋值 for(i=0;i<*returnsize;i++) { arr[i]=i+1; } return arr; }
分析:
通过读题目,它是要求我们用返回一个整形列表来代替打印,并不是真的打印;这是要求我们写函数实现。
函数的组成;
ret_type fun_name (para1,*)
{
statement;//语句项
}
ret_type 返回类型
fun_name 函数名
para 函数参数(注:函数参数之间用逗号隔开)(*就是等等的意思)
函数体:由{}括起来的
__________________________________________________________________________
1.函数返回类型
题目要求:返回一个整形列表,即我们返回整形数组;因为数组在内存中是连续的,所以知道数组的首元素地址我们就可以知道所有数组元素了。即返回类型:int*
2.函数名:见名知意——printNumbers(打印号码)
3.函数形参:
①int n 接收输入的数字n(传值调用:形参不影响实参)
②int* returnsize returnsize是打印个数的变量指针(传址调用:形参影响实参)
补充:
static修饰的全局变量——称为静态全局变量
(1)全局变量本身是具有外部链接属性的,在A文件中定义的变量,在B文件中可以通过[链接]使用(extern-声明外部符号)
(2)但是如果全局变量被static修饰,这个外部链接属性就变成了内部链接属性,这个全局变量只能在自己所在的源文件内部使用
(3)static的修饰,会把外部链接属性变成内部链接属性,最终使得全局变量的作用域变小了
在有些平台static其实不加也行,但是牛客网要加static。后面遇到类似情况 可以想到按照这种方式来处理就ok了
代码2:
static int arr[100000]; int* printNumbers(int n,int* returnsize) { *returnsize=pow(10,n)-1;//pow是计算x的y次幂的 int i=0; for(i=0;i<*returnsize;i++) { arr[i]=i+1; } return arr; }
2、根据输入的日期,计算是这一年的第几天。输入保证年份为4位数且日期合法。
输入描述:输入一行,每行空格分割,分别是年,月,日
输出描述:输出是这一年的第几天
代码实例:
#include <stdio.h> int is_leap_year(int year) { if((year%4==0)&&(year%100!=0)||(year%400==0)) { return 1; } else { return 0; } } int main() { int month_day[]={0,31,28,31,30,31,30,31,31,30,31,30,31}; int year,month,day; //多组输入——循环 while((scanf("%d %d %d",&year,&month,&day))!=EOF) { //1、先加当前月份的天数 int total_day=day; //2、再向前累加每月的天数 for(int i=month-1;i>0;i--) { total_day+=month_day[i]; } //判断是否为闰年且是否大于2月,是闰年+1 if((is_leap_year(year))&&month>2) { total_day++; } printf("%d",total_day); } return 0; }
分析:
这道题解法其实将每个月的天数枚举出来,然后根据当前月份向前累加满月的天数,然后再加上当前月所在的天数。最终考虑平闰年的 2 月份区别是否增加一天。
其中需要注意的是平年和闰年的判断,而且是闰年的月份大于 2 的时候,也就是 2 月走完,总天数才能加 1 (比如 2000年2月18日 ,虽然是闰年,但是 2月 都没走完那是不能加上闰年多出的一天的)
1、月大月小口诀:一月大,二月平,三月大,四月小,五月大,六月小,七月大,八月大,九月小,十月大,十一月小,十二月大(大:31,小:30,平:28)
2、判断闰年的条件
①能被4整除,并不能被100整除。
②能被400整除