一、2011年华科机试题

1.文本字符

题目描述

  • 从键盘输入一个文本(ASCII码文件),并将该文本输出到D盘根目录下的abc0.txt文件中,再关闭该文件,输入以ctrl+z结束。
  • 打开D盘根目录下的abc0.txt文件,将单词之间2个以上的空格都压缩为1个空格,输出处理后的文本,同时将处理后的文本输出到D盘根目录下的abc1.txt文件中并关闭该文件。
  • 打开D盘根目录下的abc1.txt文件,统计文件中字符的个数,单词的个数,以及句子中个数并输出统计结果。
#include<stdio.h>
#include<stdlib.h>
int main()
{
	FILE *fp, *fp1;
	//(1)键盘输入
	if((fp = fopen("D:\\abc0.txt", "w")) == NULL)
	{
		printf("cannot open the file!\n");
		exit(0);
	}
	char ch;
	while((ch = getchar()) != EOF)
		fputc(ch, fp);
	fclose(fp);
	//(2)文件输入处理与输出
	if((fp = fopen("D:\\abc0.txt", "r")) == NULL)
	{
		printf("cannot open the file!\n");
		exit(0);
	}
	if((fp1 = fopen("D:\\abc1.txt", "w")) == NULL)
	{
		printf("cannot open the file!\n");
		exit(0);
	}
	bool flag = true;
	while(!feof(fp))
	{
		ch = fgetc(fp);
		if(ch == ' ')
		{
			if(!flag) continue;
			fputc(ch, fp1);
			putchar(ch);
			flag = false;
		}
		else
		{
			fputc(ch, fp1);
			putchar(ch);
			flag = true;
		}
	}
	fclose(fp);
	fclose(fp1);
	//(3)统计字符、单词和句子个数
	if((fp1 = fopen("D:\\abc1.txt", "r")) == NULL)
	{
		printf("cannot open the file!\n");
		exit(0);
	}
	int count1 = 0;
	int count2 = 1;
	int count3 = 0;
	while((ch = fgetc(fp1)) != EOF)
	{
		count1++;
		if(ch == ' ' || ch == ',' || ch == ';' || ch == '.' || ch == '!' || ch == '?')
			count2++;
		if(ch == '.' || ch == '!' || ch == '?')
			count3++;
	}
	printf("\n字符个数:%d\t单词个数:%d\t句子个数:%d\n", count1, count2, count3);
	fclose(fp1);
	return 0;
}

2.整数排序

题目描述

  • 输入任意n个整数并将其无冗余的存放到数组中(n值不得事先指定,数组必须无冗余)然后输出该数组中的n个整数。
  • 对该数组中的n个整数进行排序并输出结果。
#include<stdio.h>
#include<stdlib.h>
int cmp_int(const void *a, const void *b)
{
	return *(int *)a - *(int *)b;
}
int main()
{
	int num, i, len = 0;
	//(1)无冗余输入
	int *array;
	while(scanf("%d", &num) != EOF)
	{
		if(len == 0)
			array = (int *)malloc(sizeof(int));
		else realloc(array, sizeof(int)*(len+1));
		array[len] = num;
		len++;
	}
	
	//(2)排序输出并释放内存
	qsort(array, len, sizeof(array[0]), cmp_int);
	for(i = 0; i < len; i++)
		printf("%d ", array[i]);
	free(array);
	return 0;
}

3.二叉搜索树

题目描述

  • 无冗余接受键盘输入的n个字符串,并将其无冗余的存放到对应的字符数组中,再按照每行一串的格式输出这些字符串。
  • 以单个字符串为数据域,按字典顺序将n个字符串生成为一颗二叉搜索树,并且规定左子树(数据域)小于右子树.(数据域)
  • 先序遍历该二叉搜索树并输出结果。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
typedef struct BiNode
{
	char *data;
	struct BiNode *lchild, *rchild;
}BiNode, *BTree;

BTree insertBTree(BTree BT, char *str)
{
	if(BT == NULL)
	{
		BT = (BTree)malloc(sizeof(BiNode));
		BT->data = str;
		BT->lchild = NULL;
		BT->rchild = NULL;
	}
	else if(strcmp(str, BT->data) < 0)
		BT->lchild = insertBTree(BT->lchild, str);
	else if(strcmp(str, BT->data) > 0)
		BT->rchild = insertBTree(BT->rchild, str);
	return BT;
}

void preOrder(BTree BT)
{
	if(BT != NULL)
	{
		printf("%s\n", BT->data);
		preOrder(BT->lchild);
		preOrder(BT->rchild);
		free(BT);
	}
}

int main()
{
	//无冗余接收n个字符串
	int i, j, n;
	printf("请输入字符串个数:");
	scanf("%d", &n);
	char **str =(char **)malloc(sizeof(char *)*n);
	char ch = getchar();											//接收数字后的换行符
	for(i = 0; i < n; i++)
	{
		str[i] = (char *)malloc(sizeof(char));
		j = 0;
		ch = getchar();
		while(ch!= '\n' && ch != ' ')
		{
			str[i] = (char *)realloc(str[i], sizeof(char)*(j+2));	//需要多一个位置存放'\0'
			str[i][j++] = ch;
			ch = getchar();
		}
		str[i][j] = '\0';
	}
	
	//生成二叉搜索树
	BTree BT = NULL;
	for(i = 0; i < n; i++)
	{
		BT = insertBTree(BT, str[i]);
	}
	//先序遍历输出并释放内存
	preOrder(BT);
	for(i = 0; i < n; i++)
	{
		if(str[i] != NULL)
		{
			free(str[i]);
			str[i] = NULL;
		}
	}
	if(str != NULL)
	{
		free(str);
		str = NULL;
	}
	return 0;
}

二、2012年华科机试题

1.长整数

题目描述

  • 输入一个无符号长整数,将最高字节与最低字节互换,然后输出。
  • 将这个长整数中间两个字节循环左移n位(n要输入),然后再输出。
  • 将长整数按照二进制输出,每8位输出一个空格。
//!!!注意:unsigned long和unsigned int一样只有4个字节
#include<stdio.h>
typedef unsigned long ul;
//二进制打印
void print_ul(ul num)
{
	int buf[32] = {0};
	ul radix = 2;
	int count = 0;
	do
	{
		buf[count++] = num % radix;
		num /= radix;
	}while(num);
	count = 0;
	for(int i = 31; i >= 0; i--)
	{
		printf("%d",buf[i]);
		count++;
		if(count%8 == 0)
			printf(" ");		
	}
	printf("\n");		
}
int main()
{
	//最低最高字节互换并输出
	ul num, high, low, mid;
	printf("请输入无符号长整数:");
	scanf("%lu", &num);
	//print_ul(num);
	high = num << 24;			//交换后的高字节
	low = num >> 24;			//交换后的低字节
	num = num & 0x00ffff00;		
	num = num | high | low;
	print_ul(num);

	//循环左移n位
	int n;
	ul temp = 0;
	printf("请输入移位位数n:");
	scanf("%d", &n);
	n = n % 16;
	mid = num & 0x00ffff00;
	mid = mid >> 8;					//中间两个字节右移到1 2字节处
	mid	= mid << n;					//左移n位后3 4字节为经过循环进入低字节或高字节部分
	temp = (mid & 0xffff0000) >> 8;	
	mid = (mid & 0x0000ffff) << 8;	//左移n位后1 2字节为未进入循环部分
	mid = mid | temp;			
	num = (num & 0xff0000ff) | mid;
	print_ul(num);

	return 0;
}

2.字符串排序

题目描述

  • 输入n个字符串,字符串只能是纯字母或者纯数字,不能事先指定字符串个数,最后将输入字符串倒序输出。
  • 将纯字母的字符串按照字典顺序排序,纯数字的字符串按照数值大小排序,最后再输出
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
//检测字符串合法性,,非法返回0
int check(char *c)
{
	int len = strlen(c);
	for(int i = 1; i < len-1; i++)
	{
		if(isalpha(c[i]) != isalpha(c[0]) || isdigit(c[i]) != isdigit(c[0]))
			return 0;
	}			
	return 1;
}
int main()
{
	//输入字符串并倒序输出
	char **str = (char **)malloc(sizeof(char *));
	char ch = '\0';
	printf("请输入n个字符串(以回车结束):\n");
	int i = 0;
	while(ch != '\n')
	{
		str = (char **)realloc(str, sizeof(char *)*(i+1));
		str[i] = (char *)malloc(sizeof(char));
		int j = 0;
		while((ch = getchar()) != ' ' && ch != '\n')
		{
			str[i] = (char *)realloc(str[i], sizeof(char)*(j+2));
			str[i][j] = ch;
			j++;
		}
		str[i][j] = '\0';
		if(check(str[i])==0)
		{
			printf("input error!\n");
			exit(0);
		}
		i++;
	}
	int count = i;
	printf("排序前倒序输出:\n");
	while(i--)
		printf("%s\n", str[i]);

	//排序输出
	char *temp;
	for(i = 0 ; i < count-1; i++)
		for(int j = 0; j < count-1-i; j++)
		{
			if(strcmp(str[j],str[j+1]) > 0)
			{
				temp = str[j];
				str[j] = str[j+1];
				str[j+1] = temp;
			}
		}
	printf("排序后正序输出:\n");
	for(i = 0; i < count; i++)
		printf("%s\n", str[i]);
	
	//释放内存
	for(i = 0; i < count; i++)
	{
		if(str[i])
		{
			free(str[i]);
			str[i] = NULL;
		}
	}
	if(str)
	{
		free(str);
		str = NULL;
	}
	return 0;
}

三、2013年华科机试题

1.孪生素数

题目描述

  • 素数就是不能再进行等分的整数,比如:7,11,而9不是素数,因为它可以平分为3等份,如果n和n + 2都是素数,则称他们是孪生素数。
  • 编写程序输入m (5 < m < 10000),输出两个数均不超过m的最大孪生素数,例如m = 20时答案是17,19。
#include<stdio.h>
//判断是否为素数,若是返回true,否则返回false
bool check(int m)
{
	int i = 2, n = m;
	while(i < n/2)
	{
		if(n%i == 0)
			return false;
		i++;
	}
	return true;
}
int main()
{
	int m;
	while(scanf("%d", &m) != EOF)
	{
		while(m > 2)
		{
			if(check(m) && check(m-2))
			{
				printf("%d %d\n", m-2, m);
				break;
			}
			m--;
		}
	}
	return 0;
}

2.顺转方阵

题目描述

  • 将1、2、3……n2从左上角开始,由外层至中心按顺时针方向螺旋排列所形成的的数字矩阵。
  • 编写程序,读入n,构造并输出n阶顺转方阵。
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
	int n, i, j, count = 1;
	scanf("%d", &n);
	int **array = (int **)malloc(sizeof(int *)*n);
	for(i = 0; i < n; i++)
	{
		array[i] = (int *)malloc(sizeof(int)*n);
		memset(array[i], 0, sizeof(int)*n);
	}
	//右下左上四个方向,一共需要旋转n/2圈
	for(i = 0; i < n/2; i++)
	{
		//右
		for(j = i; j < n-i; j++)
				array[i][j] = count++;
		//下
		for(j = i+1; j < n-1-i; j++)
			array[j][n-i-1] = count++;
		//左
		for(j = n-1-i; j > i; j--)
			array[n-i-1][j] = count++;
		//上
		for(j = n-1-i; j > i; j--)
			array[j][i] = count++;
	}
	//n为奇数,中间有一个数需要单独赋值
	if(n % 2)
		array[n/2][n/2] = count;
	for(i = 0;i < n; i++)
	{
		for(j = 0; j < n; j++)
			printf("%3d ", array[i][j]);
		printf("\n");
	}
	//释放内存
	for(i = 0; i < n; i++)
	{
		if(array != NULL)
		{
			free(array[i]);
			array[i] = NULL;
		}
	}
	if(array != NULL)
	{
		free(array);
		array = NULL;
	}
	return 0;
}

3.最长回文子串

题目描述

  • 子串的含义是:在原串中连续出现的字符串片段,回文的含义是:正读和反读都相同的字符序列,如121和abba是回文,abc不是回文。
  • 编写程序,输入一个由标点符号、空格、英文字母组成点的字符串,输出其中最长的回文子串。如果有多个,输出起始位置最靠左的。在判断时,应该忽略所有标点符号和空格,忽略大小写,但输出应该保持原样。输入字符串长度应该不超过1000,例如:
  • 输入:He say:Madam, I’m Adam.
  • 则输出:Madam, I’m Adam
#include<stdio.h>
#include<string.h>
#include<math.h>
#include<ctype.h>
//检验是否为回文子串
bool check(char *str, int from, int to)
{
	bool flag = true;
	while(from < to)
	{
		while(!isalpha(str[from]))
			from++;
		while(!isalpha(str[to]))
			to--;
		if(!(str[from] == str[to] || abs(str[from]-str[to]) == 32))
		{//不是字符相等或者也不互为大小写
			flag = false;
			break;
		}
		from++;
		to--;
	}
	return flag;
}
int main()
{
	char str[1000];
	gets(str);
	int i, j, max=0, max_from, max_to, len = strlen(str);
	for(i = 0; i < len; i++)
	{
		while(!isalpha(str[i]))						//由于输出开头不能为标点符号,需找到第一个字母
			i++;
		for(j = len-1; j >= i; j--)
		{
			while(!isalpha(str[j]))					//找到字母
				j--;
			if(check(str, i, j) && (j-i) > max)
			{
				max = j - i;
				max_from = i;
				max_to = j;
			}
		}
	}
	while(max_from <= max_to)
		printf("%c", str[max_from++]);
	printf("\n");
	return 0;
}

四、2014年华科机试题

1.超级素数

题目描述

  • 编程找出所有的 4 位超级素数,每行输出 6 个数,两个数之间空格分隔。
  • 超级素数:一个n 位超级素数是指一个n位正整数,它的前 1 位,前 2 位……前 n 位均为素数,例如,2333 是个 4 位超级素数,因为 2, 23, 233, 2333 均为素数。
//注意1既不是素数 也不是合数
#include<stdio.h>
bool check(int n)
{
	bool flag = true;
	for(int i = 2; i < n/2; i++)
	{
		if(n % 2 == 0)
		{
			flag = false;
			break;
		}
	}
	return flag;
}
int main()
{
	int num = 2000,count = 0;
	while(num < 9999)
	{
		if(check(num) && check(num/10) && check(num/100) && check(num/1000))
		{
			count ++;
			printf("%d ", num);
			if(count % 6 == 0)
				printf("\n");
		}
		num ++;
	}
	printf("\n");
	return 0;
}

2.二进制运算

题目描述

  • 以二进制方式输入两个正整数(即 0 和 1 组成的字符串),然后输入一个 4 则运算符(+、-、*、/),按 short 型计算这两个数的运算结果,并将结果按二进制输出(高位 0 可不输出) ,例如:
  • 输入 101 100 *
  • 输出 10100或(0000000000010100)
  • 输入 101 100 +
  • 输出 1001
#include<stdio.h>
//二进制输入
short getNum()
{
	char ch;
	short sum = 0;
	while((ch = getchar()) != ' ')
	{
		sum = sum * 2 + (ch - '0');
	}
	return sum;
}
//二进制输出
void print(short n)
{
	int count = 0; 
	int array[16];
	do
	{
		array[count++] = n % 2;
		n = n / 2;
	}while(n);
	while(count--)
		printf("%d", array[count]);
	printf("\n");
}
int main()
{
	short m, n, result;
	m = getNum();
	n = getNum();
	char ch = getchar();
	if(ch == '+')
		result = m + n;
	else if(ch == '-')
		result = m - n;
	else if(ch == '*')
		result = m * n;
	else if(ch == '/')
		result = m / n;
	print(result);
	return 0;
}

3.合法常量名

题目描述

  • 编写一个程序,判断给定的字符串是否是合法的C整型常量,若是输出Yes;不是则输出No。C整型常量的语法图如下图所示(图中 0 是数字 0)
  • 要求程序能循环接受用户的输入,每行输入一个字符串,给出判定 结果,在输入一个字符串,给定判定结果,……,直至输入Ctrl + Z 结束,例如:
  • 123
  • Yes
  • 078
  • No
  • 100h
  • No
    C整型常量
#include<stdio.h>
#include<string.h>
#include<ctype.h>
//检验字符串最后两位是否为UL、Ul、uL、ul
bool check(char *str, int len)
{
	if((str[len-2] == 'u' || str[len-2] == 'U') && (str[len-1] == 'l' || str[len-1] == 'L'))
		return true;
	else 
		return false;
}
//8进制
void judge_8(char *str, int len)
{
	for(int i = 1;i < len; i++)
	{
		if(!(str[i] >='0' && str[i] <= '7'))
		{
			printf("No\n");
			return;
		}
	}
	printf("Yes\n");
}
//10进制
void judge_10(char *str, int len)
{
	for(int i = 0;i < len; i++)
	{
		if(!isdigit(str[i]))
		{
			printf("No\n");
			return;
		}
	}
	printf("Yes\n");
}
//16进制
void judge_16(char *str, int len)
{
	for(int i = 2;i < len; i++)
	{
		if(!(isdigit(str[i]) || (str[i] >= 'A' && str[i] <= 'F') || (str[i] >= 'a' && str[i] <= 'f')))
		{
			printf("No\n");
			return;
		}
	}
	printf("Yes\n");
}
int main()
{
	char str[1000];
	while(gets(str))
	{
		int len = strlen(str);
		if(check(str,len))
			len -=2;
		//最好都进行判断,否则空格或者回车也会打印Yes或No
		if(str[0] != '0' && isdigit(str[0]))
			judge_10(str, len);
		else if(str[1] == 'x' || str[1] == 'X')
			judge_16(str, len);
		else if(isalpha(str[1]) || isdigit(str[1]))
			judge_8(str, len);
	}
	return 0;
}

五、2015年华科机试题

1.电话号码

题目描述

  • 输入一串字符,并验证其是否为正确的电话号码。
  • 长度必须为11位,第一位必须为 1,第二位为 3、5、6、8 中的一个,其余位必须为 0 ~ 9中的一个数。
#include<stdio.h>
#include<string.h>
#include<ctype.h>
int main()
{
	char str[12];
	while(gets(str))
	{
		bool flag = true;
		//注意str[1]的判断条件
		if(strlen(str) != 11 || str[0] != '1' || !(str[1] == '3' || str[1] == '5' ||str[1] == '6' || str[1] == '8'))
			flag = false;
		for(int i = 0; i < 11; i++)
			if(!isdigit(str[i]))
				flag = false;
		if(flag)
			printf("phone number correct!\n");
		else
			printf("phone number error!\n");
	}
	return 0;
}

2.字符串拼接

题目描述

  • 无冗余地输入两个字符串,并对其进行拼接,输出拼接后的字符串,例如string buff 输出stringbuff。
  • 对于拼接后的字串,输出奇数下标组成的子串和偶数下标组成的子串。例如,srnbf tiguf。
  • 对于奇数下标组成的子串以及偶数下标组成的子串进行过 排序。例如bfnrs fgitu。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
char *getStr(char *str)
{
	str = (char *)malloc(sizeof(char));
	int count = 0;
	char ch;
	while((ch = getchar()) != ' ' && ch != '\n')
	{
		str = (char *)realloc(str, sizeof(char)*(count+2));
		str[count++] = ch;
	}
	str[count] = '\0';
	//printf("%s\n", str);
	return str;
}
void str_cat(char *str1, char *str2)
{
	int len = strlen(str1) + strlen(str2);
	str1 = (char *)realloc(str1, sizeof(char)*(len+1));
	strcat(str1, str2);
	printf("%s\n", str1);
}
void print_str(char *str, int n)
{
	int i, len = strlen(str);
	for(i = n; i < len; i+=2)
		putchar(str[i]);
}
void str_sort(char *str, int n)
{
	int len = strlen(str);
	int i, j;
	char temp;
	for(i = n ; i < len-2; i+=2)
		for(j = n; j < len-2; j+=2)
			if(str[j] > str[j+2])
			{
				temp = str[j];
				str[j] = str[j+2];
				str[j+2] = temp;
			}
	print_str(str, n);
}
int main()
{
	//无冗余输入两个字符串,默认以空格隔开
	char *str1 = NULL, *str2 = NULL;
	str1 = getStr(str1);
	str2 = getStr(str2);
	//拼接字符串输出
	printf("拼接字符串为:");
	str_cat(str1, str2);
	//输出奇数下标和偶数下标的子串
	printf("排序前奇偶子串为:");
	print_str(str1, 0);
	putchar(' ');
	print_str(str1, 1);
	putchar('\n');
	//奇偶子串排序
	printf("排序后奇偶子串为:");
	str_sort(str1, 0);
	putchar(' ');
	str_sort(str1, 1);
	putchar('\n');
	//释放内存
	if(str1 != NULL)
	{
		free(str1);
		str1 = NULL;
	}
	if(str2 != NULL)
	{
		free(str2);
		str2 = NULL;
	}
	return 0;
}

3.字符串变换

题目描述

  • 无冗余的输入一个字符串,输出该字符串。
  • 对于不是首次出现的字符,对其进行过滤,例如 abcdacdef,过滤后为 abcdef。
  • 对于字符 0-9,A-F,a-f,将其对应的 ASCII码的低 4位进行对调,例如将 1011,转换为 1101,并将对应的 ACSII码对应的字符输出,若为字母,转换为大写。
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
//二进制打印
void print(char ch)
{
	int array[8], count = 0;
	printf("%c:",ch);
	do
	{
		array[count++] = ch % 2;
		ch /= 2;
	}while(ch);
	while(count--)
		printf("%d",array[count]);
	putchar(' ');
}
int main()
{
	//无冗余输入输出字符串
	char ch;
	char *str = (char *)malloc(sizeof(char));
	int i, count = 0;
	while((ch = getchar()) != '\n')
	{
		str = (char *)realloc(str, sizeof(char)*(count+2));
		str[count++] = ch;
	}
	str[count] = '\0';
	printf("%s\n",str);
	//过滤非首次出现的字符,若字符包括汉字则hashtable的长度需要增加
	bool hashtable[128] = {false};
	count = 0;
	for(i = 0; str[i] != '\0'; i++)
	{
		if(hashtable[str[i]] == false)
		{
			str[count++] = str[i];
			hashtable[str[i]] = true;
		}		
	}
	str[count] = '\0';
	//printf("%s\n",str);
	//字符串变换(注释代码可分析)
	for(i = 0; str[i] != '\0'; i++)
	{
		if(isalpha(str[i]) || isdigit(str[i]))
		{
			//print(str[i]);
			str[i] = (str[i] & 0xf0) | (str[i] & 0x06)>>2 | (str[i] & 0x03)<<2;
			//print(str[i]);
			if(isalpha(str[i]))
				str[i] = toupper(str[i]);
			putchar(str[i]);
			//putchar('\n');
		}
	}

	//释放内存
	if(str != NULL)
	{
		free(str);
		str = NULL;
	}
	return 0;
}

六、2016年华科机试题

1.评委打分

题目描述

七个评委给选手打分,去掉最高分和最低分,输出平均分,保留一位小数。

//默认去掉一个最高分和一个最低分
#include<stdio.h>
int main()
{
	double score[7];
	double  max, min, sum;
	int i;
	for(i = 0; i < 7; i++)
	{
		scanf("%lf", &score[i]);
		if(i == 0)
		{
			max = score[i];
			min = score[i];
			sum = 0;
		}
		max = max > score[i]? max : score[i];
		min = min < score[i]? min : score[i];
		sum += score[i];
	}
	sum = sum - max - min;
	printf("%-8.2lf", sum/5);
	return 0;
}

2.去空格

题目描述

  输入字符串

  • 去除前面的空格;
  • 中间多个空格只保留一个空格;
  • 数字字母中间加上_符号 。
#include<stdio.h>
#include<ctype.h>
//返回标识,0为空格,1为数字,2为字母,-1为其他
int check(char ch)
{
	if(ch == ' ')
		return 0;
	else if(isdigit(ch))
		return 1;
	else if(isalpha(ch))
		return 2;
	else
		return -1;
}
int main()
{
	char ch;
	char str[1000];
	int count = 0, flag, flag_ch;		//flag标识前一位,flag_ch标识当前位
	while((ch = getchar()) != '\n')
	{
		if(!count && ch == ' ')
			continue;
		flag_ch = check(ch);
		if(!flag)						//前一位为空格
		{
			if(!flag_ch)				//ch为空格
				continue;
		}
		else if(flag_ch == 1 && flag == 2 || flag_ch == 2 && flag == 1)		//字母数字中间加下划线
			str[count++] = '_';	
		str[count++] = ch;				
		flag = flag_ch;					//前一位和当前位都为空格时已经跳过,其余情况均赋值并保留当前位的标识
	}
	str[count] = '\0';
	printf("%s\n", str);
	return 0;
}

3. 合法IP地址

题目描述

输入十进制 IP 地址字符串判断是否合法并编码成32位二进制地址。

//scanf输入数字,避免字符串的繁杂的判断
#include<stdio.h>
#include<stdlib.h>
//二进制转换
void convert(int n)
{
	int array[8]={0};
	int count = 0;
	do
	{
		array[count++]  = n % 2;
		n /= 2;
	}while(n);
	for(int i = 7; i >= 0; i--)
		printf("%d", array[i]);
}
bool check(int a)
{
	if(a >= 0 && a <= 255)
		return true;
	else
		return false;
}
int main()
{
	//合法IP地址判断
	int a, b, c, d;
	scanf("%d.%d.%d.%d", &a, &b, &c, &d);
	if(check(a) && check(b) && check(c) &&check(d))
		//printf("%d.%d.%d.%d\n", a, b, c, d);
		printf("correct!\n");
	else
	{
		printf("error!\n");
		exit(0);
	}
		
	//转换32位二进制
	convert(a);
	putchar('.');
	convert(b);
	putchar('.');
	convert(c);
	putchar('.');
	convert(d);
	putchar('\n');
	return 0;
}

七、2017年华科机试题

1.字符三角形

题目描述

输入一个字符,打印如下结构
2017_01

#include<stdio.h>
#include<ctype.h>
void print(char ch, char c)
{
	int count = ch - c + 1;
	int blank = 0, i;
	while(count--)
	{
		char temp = c;
		for(i = 0; i < blank ; i++)		//打印每行空格
			printf(" ");
		blank += 2;
		while(temp < ch)				
		{
			printf("%c ", temp++);		//打印每行前半部分
		}
		while(temp >= c)
		{
			printf("%c ", temp--);		//打印每行后半部分
		}
		ch--;							//每行中间值减小
		printf("\n");
	}
	
}
int main()
{
	char ch;
	scanf("%c", &ch);
	if(isalpha(ch))
	{
		if(ch >= 'a' && ch <= 'z')
			print(ch, 'a');
		if(ch >= 'A' && ch <= 'Z')
			print(ch, 'A');
	}
	else
		printf("Input error!\n");
	return 0;
}

2.字符串压缩

题目描述

  • 以字符串的方式接收一串数字,如12345。
  • 把每 2 位对应的数字加 32 ,保存为对应的 ASCII 码字符保存,如 12 + 32 = 44,然后把 44 对应的字符保存到新的字符串。
  • 如果数字个数为奇数,末尾补0。
#include<stdio.h>
#include<string.h>
int main()
{
	char str[1000], buf[500];
	while(gets(str))
	{
		int len = strlen(str);
		if(len % 2 == 1)				//个数为奇数末尾补0
		{
			str[len-1] = '0';
			str[len] = '\0';
			len++;
		}
		int i, j = 0;
		for(i = 0; i < len; i+=2)
		{
			buf[j++] = (str[i] - '0')*10 + (str[i+1] - '0') + 32;
		}
		buf[j] = '\0';  
		printf("%s\n", buf);
	}
	return 0;
}

3.大数加法

题目描述:a + b

 参考2009~2010年华科机试题,也可以用链表头插法和指针实现。

八、2018年华科机试题

1.统计英文

题目描述

从键盘输入一行英文句子,句子中只有英文单词和空格,每个单词之间由若干个空格隔开,英文单词由大小写字母组成,编程完成下列任务:

  • 统计并输出此句子中英文字母的个数。
  • 统计并输出此句子中单词的个数。
  • 查找句子中出现次数最多的字母(不区分大小写)和次数,当出现最多的字符不止一个时,都能找到,并输出找到的所有字母及次数。(输出时大小写字母均可)例如,输入句子:This Is An Pencil Case,则输出为:
  • 字母个数:18
  • 单词个数:5
  • 最多的字母:i,s
  • 出现的次数:3
#include<stdio.h>
#include<ctype.h>
int main()
{
	char str[1000];
	while(gets(str))
	{
		//统计并输出字母、单词个数
		int count_c = 0, count_w = 1;			//单词个数即空格个数 + 1
		int i, hashtable[128] = {0};
		for(i = 0; str[i] != '\0'; i++)
		{
			if(str[i] == ' ')
				count_w++;
			if(isalpha(str[i]))
				count_c++;
			hashtable[str[i]]++;
		}
		printf("字母个数:%d\n单词个数:%d\n", count_c, count_w);
		//查找句子中出现次数最多的字母(不区分大小写)和次数
		//hashtable空间换时间策略,且可以扩展统计所有字符
		int max = 0;
		for(i = 65; i < 91; i++)
			if(max < hashtable[i] + hashtable[i+32])
				max = hashtable[i] + hashtable[i+32];
		printf("最多的字母:");
		bool flag = false;
		for(i = 65; i < 91; i++)
				if(max == hashtable[i] + hashtable[i+32])
					if(flag)
						printf(",%c ", i);
					else
					{
						printf("%c", i);
						flag = true;
					}
		printf("\n出现的次数:%d\n", max);
	}
	return 0;
}

2.十二进制

题目描述

十二进制是数学中一种以 12 为底数的记数系统,它由 0 ~ 9,a,b 组成。与十进制的对应关系是 0 ~ 9 对应 0 ~ 9,a 对应 10,b 对应 11。例如,十二进制的 a2,十进制是122,输入一个仅含十二进制数字的字符串(字母一律小写,不超过 8 个字符),编程完成下列任务:

  • 输出该十二进制数每一位对应的十进制数。(从高位到低位顺序输出,空格隔开)
  • 实现“十二进制”转“十进制”算法,输出该十二进制对应的十进制数。
  • 输出转换后的十进制数在内存中的每个二进制数位。(共四字节,字节之间空格隔开)
  • 例如,输入十二进制数:a2,则输出为:
  • 10 2
  • 122
  • 00000000 00000000 00000000 01111010
#include<stdio.h>
#include<stdlib.h>
#include<ctype.h>
void convert(int n)
{
	int array[32] = {0};
	int i = 0;
	do
	{
		array[i++] = n % 2;
		n /= 2;
	}while(n);
	int count = 0;
	for(i = 31; i >= 0; i--,count++)
	{
		printf("%d", array[i]);
		if(count%8 == 7)
			printf(" ");
	}
	printf("\n");
}
int main()
{
	char str[1000];
	while(gets(str))
	{
		// 输出该十二进制数每一位十进制与数字的十进制数。
		int i, temp, sum = 0;
		for(i = 0; str[i] != '\0'; i++)
		{
			if(isdigit(str[i]))
				temp = str[i] - '0';
			else if(str[i] == 'a' || str[i] == 'b')
				temp = str[i] - 87;
			else
			{
				printf("intput error!\n");
				exit(0);
			}
			printf("%d ", temp);
			sum = sum*12 + temp;
		}
		printf("\n%d\n", sum);
		//转换二进制
		convert(sum);
	}
	return 0;
}

3.N/D

题目描述

  • 编写程序,接收 3 个以 N/D 形式输入的分数,其中 N (0 <= N <= 65535)为分子,D(0 <= N <= 65535)为分母。
  • 输出他们的小数形式,如果小数形式存在循环节,则用括号括起来,如1 / 3 = .33333……表示为 .(3)。例如,输入:8/5 1/3 11/13,则输出为 8/5 = 1.6 1/3 = .(3) 11/13 = .(846153)
/*
模拟除法的过程,比如我们要计算1/7这个小数的循环节,我们事先求出整数部分,也就是1/7=0。
然后再求小数部分,求出第一组商con和它所对应的余数r,con=(1×10)/7=1,r=(1×10)%7=3,
然后进入循环,将第一组数据保存起来,接着算第二组,con=(3×10)/7=4,r=(3×10)%7=2。
*/
//余数:res  商:mod  pos:循环节开始的位置  count:除法次数
#include<stdio.h>
int main()
{
	int N, D;
	while(scanf("%d/%d", &N, &D) != EOF)
	{
		int res[100], mod[100];
		res[0] = N / D;
		mod[0] = N % D;
		int count = 1, pos = 0, i;
		while(count < 100 && mod[count-1] != 0)
		{
			res[count] = (mod[count-1] * 10) / D;	
			mod[count] = (mod[count-1] * 10) % D;
			if(mod[count] == 0)
				break;
			for(i = 1; i < count; i++)
			{
				if(mod[count] == mod[i])			//余数相等,即循环节开始位置
				{
					pos = i;
					break;
				}
			}
			if(pos)
				break;
			count++;
		}
		printf("%d/%d = ", N, D);
		if(!pos)									//pos = 0 时  1.整除没有小数  2.整除有小数
		{
			if(res[0] !=0 && mod[0] == 0)			//1.整除没有小数
			{
				printf("%d", res[0]); 
				continue;
			}
			if(res[0])								//2.整除有小数:整数部分为 0 或不为 0 两种情况	
				printf("%d.", res[0]);									
			else printf(".");
			for(i = 1; i <= count; i++)				//输出整除的小数
			{
				printf("%d", res[i]);
			}
		}
		else										//pos != 0   不能整除
		{
			if(res[0])								//整数部分为 0 或不为 0 两种情况
				printf("%d", res[0]);									
			else printf(".");
			for(i = 1; i < pos; i++)			    //输出循环节前面的小数
			{
				printf("%d", res[i]);
			}
			printf("(");
			for(i = pos; i <= count-1; i++)			//输出(循环节小数)
			{
				printf("%d", res[i]);
			}
			printf(")");
		}
		printf("\n");
	}
	return 0;
}

九、2019年华科机试题

1.梅森素数

题目描述

梅森数,是指形如 2^p-1 的一类数,其中指数p是大于等于2的正整数,常记为M§ 。如果梅森数是素数,就称为梅森素数。

  • 输入一个长整型数,然后输出比该数字小的梅森素数,例如输入:90,输出为
  • M(2)=3
  • M(3)=7
  • M(5)=31
  • 注意:为方便第2题调用和测试,笔者添加了很多与本题无关的注释;
/*
梅森数,是指形如 2^p-1 的一类数,其中指数p是大于等于2的正整数,常记为M(p) 。
如果梅森数是素数,就称为梅森素数。
输入一个长整型数,然后输出比该数字小的梅森素数。
*/

//1. /* /* */ 这种嵌套调用情况,即多个左注释只需要找到第一个 */ 即可
//2. /*// 这种调用情况
//3.  或者 //*/ 或者 ///*这种情况,直接检索到行末即可
/* /*1种情况
*/ 

/*//
第2种情况
*/

//第3种情况// 或者 //*/ 或者 ///* 
#include<stdio.h>
#include<math.h>
//判断素数
bool check(long n)
{
	long num = n;
	for(long i = 2; i < n/2; i++)
		if(n%i == 0)					//能够整除
			return false;				
	return true;
}
int main()
{
	long N, n, p = 2;
	scanf("%ld", &N);
	n = (long)(pow(2, p) - 1);
	while(n <= N)
	{
		if(check(n))
			printf("M(%ld) = %ld\n", p, n);		//打印结果
		p++;
		n = (long)pow(2, p) - 1;
	}
	return 0;
}

2.代码处理

题目描述

将第一题的源代码保存为abc.c文件。并且要求abc.c文件中有相当数量的注释,包括 // 和 // 两种形式的注释。

  • 读取 abc 文件的内容,将其显示在控制台上,并为每行代码增加一个行号。
  • 使源代码中的 // 类型的注释内容不显示在控制台中。
  • 使源代码中的 // 类型的注释内容不显示在控制台中。
//注意: /* */ */ 这种嵌套调用注释情况不允许,除非跟在//后面
//只需要考虑
//1. /* /* */ 这种嵌套调用情况,即多个左注释只需要找到第一个 */ 即可
//2. /*// 这种调用情况
//3.  或者 //*/ 或者 ///*这种情况,直接检索到行末即可
#include<stdio.h>
#include<stdlib.h>
int row = 1;
//打印行号
void print_row(char *str)
{
	if(row == 1)
		printf(" %-3d| ", row);
	else
		printf("\n %-3d| ", row);
}
//检索换行符或者文件结束符EOF的位置
int findPos(char *str, int i)
{
	while(!(str[i] == '\n' || str[i] == EOF))
		i++;
	return i;
}
//检索 */ 中 * 的位置
int findRight(char *str, int i)
{
	while(!(str[i] == '*' && str[i+1]  == '/'))
	{
		if(str[i] == '\n')
		{
			row++;
			print_row(str);
		}
		i++;
	}
	return i;
}
int main()
{
	FILE *fp;
	if((fp = fopen("E:\\abc.cpp","r")) == NULL)
	{
		printf("cannot open the file!\n");
		exit(0);
	}
	int flag = 0, i = 0;										//记录 /* 的个数
	char str[2000];
	while(!feof(fp))
		str[i++] = fgetc(fp);									//文件读入
	str[i] = '\0';
	//printf("%s", str);
	print_row(str);												//打印第一行的行号
	for(i = 0; str[i] != '\0'; i++)
	{
		if(str[i] == '/' && str[i+1] == '/')					//注释为//则找到换行符或者EOF的位置
			i = findPos(str, i);
		if(str[i] == '/' && str[i+1] =='*')						//遇到 /* 则flag加 1
		{
			flag++;
			i += 2;												//i+2 防止 /*/ 这种情况 
			i = findRight(str, i) - 1;							//i 自动递增到 */ 中*的位置
		}
		if(str[i] == '*' && str[i+1] =='/' && flag != 0)		//遇到 */ 则flag减 1,i 总共递增两次
		{
			flag = 0;
			i++;
			continue;
		}
		if(str[i] == '\n')
		{
			row ++;
			print_row(str);
			continue;
		}
		printf("%c", str[i]);
	}
	fclose(fp);
	return 0;
}

3.凯撒密码

题目描述

从键盘输入一个由字母组成的字符串,对字符串中的每个字符进行偏移操作,每个字符都向后偏移两个。即:a -> c,Z -> B。然后输出偏移后的每个字符的奇校验码及其对应的十进制数,如果字符中 1 的个数为偶数,将其最高位置为 1。

  • 输入:aD
  • 输出:原文:aD
  • 密文:cF
  • c 11100011 227
  • F 01000110 70
#include<stdio.h>
void checkCode(char ch)
{
	int array[8] = {0};
	int i = 0, count = 0, product = 1;			//count计算二进制 1 的个数、十进制
	do
	{
		array[i]= ch % 2;
		if(array[i] == 1)
			count++;
		ch /= 2;
		i++;
	}while(ch);
	if(count % 2 ==  0)
		array[7] = 1;
	count = 0;
	for(i = 7; i >= 0; i--)
	{
		printf("%d",array[i]);
		count = count*2 + array[i];
	}
	printf(" %d\n", count);
}
int main()
{
	//输出原文、密文
	char str[1000];
	gets(str);
	printf("原文:%s\n", str);
	printf("密文:");
	for(int i = 0; str[i] != '\0'; i++)
	{
		if(str[i] >= 'a' && str[i] <= 'x' || str[i] >= 'A' && str[i] <= 'X')
			str[i] += 2;
		else if(str[i] == 'y' || str[i] == 'z' || str[i] == 'Y' || str[i] == 'Z')
			str[i] -=24;
		printf("%c", str[i]);
	}
	printf("\n");
	//输出每个密文字符的奇偶校验码该码的十进制数
	for(i = 0; str[i] != '\0'; i++)
	{
		printf("%c ", str[i]);
		checkCode(str[i]);
	}
	return 0;
}
Logo

汇聚原天河团队并行计算工程师、中科院计算所专家以及头部AI名企HPC专家,助力解决“卡脖子”问题

更多推荐