C语言笔试训练【第四天】

文章目录

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,所以这道题选

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;
}

ASCII码表

在标准ASCII码表中,已知英文字母A的ASCII码是01000001,英文字母D的ASCII码是_百度知道

猜你喜欢

转载自blog.csdn.net/zyb___/article/details/132152878