文章目录
1、设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是( )
2、运行以下程序后,如果从键盘上输入 65 14<回车> ,则输出结果为( )
3、若运行以下程序时,从键盘输入 ADescriptor<回车> ,则下面程序的运行结果是( )
4、如下函数是求两个int数字最大公约数的,指出其中存在的问题【多选】( )
5、执行下面的程序段,语句3的执行次数为( )
6. 错误的集合
思路1:按位异或
思路2:排序计数
7.密码检查
ASCII码表
大家好,我是纪宁。
今天是C语言笔试训练的第四天,加油!
1、设变量已正确定义,以下不能统计出一行中输入字符个数(不包含回车符)的程序段是( )
A: n=0; while(ch=getchar()!='\n')n++; B: n=0; while(getchar()!='\n')n++;
C: for(n=0; getchar()!='\n'; n++); D: n=0; for(ch=getchar();ch!='\n';n++);
这道题比较简单一点,认真看题就会发现,D选项中变量 ch 的值一直没有变过,所以没有统计一行中输入字符个数的功能。这道题选 D
2、运行以下程序后,如果从键盘上输入 65 14<回车> ,则输出结果为( )
int main()
{
int m, n;
printf("Enter m,n:");
scanf("%d%d", &m,&n);
while (m!=n) //1
{
while(m>n) m=m-n; //2
while(n>m) n=n-m; //3
}
printf("m=%d\n",m);
return 0;
}
A: 3 B: 2 C: 1 D: 0
此题考验的就是认真程度,题目不难。
最后的结果是 m=n=1,所以这道题选 C
3、若运行以下程序时,从键盘输入 ADescriptor<回车> ,则下面程序的运行结果是( )
#include <stdio.h>
int main()
{
char c;
int v0=0,v1=0,v2=0;
do
{
switch(c=getchar())
{
case'a':case'A':
case'e':case'E':
case'i':case'I':
case'o':case'O':
case'u':case'U':v1 += 1;
default:v0+= 1;v2+=1;
}
}while(c!='\n');
printf("v0=%d,v1=%d,v2=%d\n",v0,v1,v2);
return 0;
}
A: v0=7,v1=4,v2=7 B: v0=8,v1=4,V2=8
C: v0=11,v1=4,v2=11 D: v0=12,v1=4,v2=12
此题的知识点是关于 switch...case语句
当switch...case 语句中case 后面没有break的时候,程序将会继续进行下去,ADescriptor 是11个字符,加上回车一共12个字符。等于元音字母 aeiou 的有4个,所以 v1=4,而无论等不等于元音字母,他们都会经历 default ,所以 v0 和 v2 都是12,这道题选 D
4、如下函数是求两个int数字最大公约数的,指出其中存在的问题【多选】( )
int gcd(char x,char y)
{
int min = x < y ? x : y;
for (min = 0; min > 0; min--)
if (x % min = 0 && y % min = 0)
return min;
}
A: 参数类型不对 B: 循环变量min初值不对
C: 判断等于的符号不对 D: 返回类型不对
A.函数实参是int,形参用char不对,会发生截断丢失数据。
B.min在for循环开始时更新为0,不再是两个形参中的较小值;
C.判断是否整除的时候误将==写成=赋值运算符;
D.函数最终要返回一个int值,返回值类型没问题,但是这里要强调一个选项中没写出的问题,如果是牛客网上的题,会报编译错误,说该函数不是在所有情况下都有返回值,只有在if条件成立的情
况下有返回值;但是一般在vs上这种情况能通过,编译器会给一个默认的返回值。
所以这道题选 A B C
5、执行下面的程序段,语句3的执行次数为( )
for(i = 0; i <= n-1; i++) // (1)
for(j = n; j > i; j--) // (2)
state; // (3)
A: n(n+2)/2 B: (n-1)(n+2)/2 C: n(n+1)/2 D: (n-1)(n+2)
外循环有n次,当i=0,内循环为n次,当i=1,内循环为n-1次,当i=2时,内循环为n-2次,以此类推,总次数为n+(n-1)+(n-2)+......+2+1,就是个等差数列,由等差求和公式得,等于n(n+1)/2,所以这道题选 C
6. 错误的集合
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。给定一个数组nums 代表了集合 S 发生错误后的结果。请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。此题来自 leetcode
思路1:按位异或
这道题的第一种思路是构造一个数组,包含正确的的从 1 到 n 的整数,然后将这两个数中所有数进行按位异或,因为除了重复的和丢失的那个数字,其他的数字都是从成对出现的,所以按位异或的结果就是答案的那两个数字按位异或的结果。
得到这个结果后,计算出这个结果从后往前的第一个二进制位1,然后记录移动的二进制位数,将这个位数对应的二进制位&1的结果当做分组的标准,将这两个数组里面的数就会分为了两组:这个二进制位位置为1的和为0的,因为分类的起源就是两个要求的数字按位异或的结果,所以他们两个一定会被分到不同的组,而其他的符合要求的数都是成对出现的,按位异或的结果是0,那么就得到了这两个数。详细参考^(按位异或)操作符详解 类似于里面的单身狗问题进阶版。
最后只需要判断这两个数输出的顺序即可。
int* findErrorNums(int* nums, int numsSize,int*returnSize) {
int* nums2 = (int*)malloc(sizeof(int) * numsSize);
int* nums3 = (int*)malloc(sizeof(int) * numsSize*2);
int* nums4 = (int*)malloc(sizeof(int) * numsSize*2);
int i = 0, ret = 0, pos = 0;
for (i = 0; i < numsSize; i++)
{
nums2[i] = i + 1;
}
for (i = 0; i < numsSize; i++)
{
ret ^= nums[i];
ret ^=nums2[i];
}
while ((ret & 1) != 1)
{
ret = ret >> 1;
pos++;
}
int count1= 0,count2=0;
int j = 0;
int z = 0;
for (i = 0; i < numsSize; i++)
{
if (((nums[i] >> pos) & 1) == 1)
{
nums3[j] = nums[i];
j++;
count1++;
}
else
{
nums4[z] = nums[i];
z++;
count2++;
}
if (((nums2[i] >> pos) & 1) == 1)
{
nums3[j] = nums2[i];
j++;
count1++;
}
else
{
nums4[z] = nums2[i];
z++;
count2++;
}
}
int a1 = 0, a2 = 0;
for (i = 0; i < count1; i++)
{
a1 ^= nums3[i];
}
for (i = 0; i < count2; i++)
{
a2 ^= nums4[i];
}
int* arr = (int*)malloc(sizeof(int) * 2);
for (i = 0; i < numsSize; i++)
{
if (a1 == nums[i])//a1重复
{
arr[0] = a1;
arr[1] = a2;
return arr;
}
}
*returnSize=2;
arr[0] = a2;
arr[1] = a1;
free(nums2);
free(nums3);
free(nums4);
return arr;
}
思路2:排序计数
先利用 qsort 函数排序,保证原数组是不降序的,然后定义一个数组,记录原数组中每个数出现的次数,并且要保证一一对应,那么丢失的数组位置新数组里的值就是0,重复数字的位置的值是2,且与原数组的下标是对应的。
int Comper(const void* p1, const void* p2)
{
return (*(int*)p1) - (*(int*)p2);
}
int* findErrorNums(int* nums, int numsSize, int* returnSize){
int* a = (int*)malloc(sizeof(int)*(numsSize));
qsort(nums, numsSize, sizeof(int), Comper);
for(int i = 0; i < numsSize; i++){
a[i] = 0;
}
for(int i = 0; i < numsSize; i++){
a[nums[i]-1]++;
}
int* res = (int*)malloc(sizeof(int)*2);
for(int i = 0; i < numsSize; i++){
if(a[i] == 2){
res[0] = i+1;
}
if(a[i] == 0){
res[1] = i+1;
}
}
*returnSize = 2;
return res;
}
qsort函数使用指南:qsort函数
7.密码检查
小明同学最近开发了一个网站,在用户注册账户的时候,需要设置账户的密码,为了加强账户的安全性,小明对密码强度有一定要求:
1. 密码只能由大写字母,小写字母,数字构成;
2. 密码不能以数字开头;
3. 密码中至少出现大写字母,小写字母和数字这三种字符类型中的两种;
4. 密码长度至少为8
现在小明受到了n个密码,他想请你写程序判断这些密码中哪些是合适的,哪些是不合法的。
这道题相对于上道题简单一些,只需要拿着 ASCII 码不断卡就形了。
void Password_Check(char* str) {
int len = strlen(str);
char* ps = str;
if (len > 100 || len < 8) {
printf("NO\n");
return;
}
if (*str <= 57 && *str >= 48) {
printf("NO\n");
return;
}
do {
if ((*ps < 48) ||
(*ps > 57 && *ps < 65) ||
(*ps > 122) ||
(*str > 90 &&*str < 97)) {
printf("NO\n");
return;
}
} while (*++ps);
ps = str;
int count = 0;
do {
if (*ps <= 57 && *ps >= 48) {
count++;
break;
}
} while (*++ps);
ps = str;
do {
if ((*ps <= 90 && *ps >= 65)) {
count++;
break;
}
} while (*++ps);
ps = str;
do {
if (*ps >= 97 && *ps <= 122) {
count++;
break;
}
} while (*++ps);
if (count < 2)
{
printf("N0\n");
return;
}
printf("YES\n");
}
int main() {
int n = 0;
scanf("%d", &n);
while (n--) {
char* str = (char*)malloc(sizeof(char) * 101);
scanf("%s", str);
Password_Check(str);
free(str);
}
return 0;
}