ACM模式练题技巧——C语言
1 数字输入
华为软件机试是采用ACM模式,这种模式需要根据题目要求,按照规定的格式自己手动写输入和输出的代码,如果没有充分准备,考试的时候就有可能会在输入输出这块卡很久,浪费考试的时间。
下面总结了一些常见的输出输出格式,以我们常用的几种语言,给出对应格式的编码模板,掌握的这些输入输出模板,可以让我们在考试的时候快速完成输入输出代码的编写,节省出更多的时间思考和编写逻辑代码。
1.1 多组空格分隔的两个正整数
输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据包括多组,示例如下:
1 5 10 20
C语言
// 直接处理的情况,适用于比较简单的题型
#include <stdio.h>
int main() {
int a,b;
while(scanf("%d %d",&a, &b) != EOF) {//注意while处理多个case
printf("%d\n",a+b);
}
return 0;
}
// 先保存起来再处理的场景,适用于较复杂的题型,需要在while外部处理数据,层次更清晰
#include <stdio.h>
#include <stdint.h>
#define MAX_NUM 100
int main()
{
int inputNum = 0;
int a[MAX_NUM], b[MAX_NUM];
while (scanf("%d %d", &a[inputNum], &b[inputNum]) != EOF) {
inputNum++;
}
for (int i = 0; i < inputNum; i++) {
printf("%d\n", a[i] + b[i]);
}
return 0;
}
1.2 第一行组数后接空格分隔的两个正整数
输入第一行包括一个数据组数t(1 <= t <= 100)接下来每行包括两个正整数a,b(1 <= a, b <= 10^9)示例如下
2 1 5 10 20
C语言
#include <stdio.h>
#include <stdint.h>
int main()
{
int groupNum;
int a, b;
if (scanf("%d", &groupNum) == EOF) {
return -1;
}
for (int i = 0; i < groupNum; i++) {
if (scanf("%d %d", &a, &b) == EOF) {
break;
}
printf("%d\n", a + b );
}
return 0;
}
1.3 空格分隔的两个正整数,当都为0时结束
输入包括两个正整数a,b(1 <= a, b <= 10^9),输入数据有多组, 如果输入为0 0则结束输入
示例如下:
1 5 10 20 0 0
C语言
#include <stdio.h>
#include <stdint.h>
int main()
{
int a, b;
while (scanf("%d %d", &a, &b) != EOF) {
if (a == 0 && b == 0) {
break;
}
printf("%d\n", a + b);
}
return 0;
}
1.4 每行第一个为个数,后面带空格分割,为0时结束
输入数据包括多组。每组数据一行,每行的第一个整数为整数的个数n(1 <= n <= 100), n为0的时候结束输入。接下来n个正整数,即需要求和的每个正整数。
示例如下:
4 1 2 3 4 5 1 2 3 4 5 0
C语言
#include <stdio.h>
#include <stdint.h>
#define MAX_NUM 100
int main()
{
int dataNum;
while (scanf("%d", &dataNum) != EOF) {
if (dataNum == 0) {
break;
}
int sum = 0;
int a;
for (int i = 0; i < dataNum; i++) {
if (scanf("%d", &a) == EOF) {
break;
}
sum += a;
}
printf("%d\n", sum);
}
return 0;
}
1.5 第一行为组数,后面每行第一个数为个数,后面数据带空格分割
输入的第一行包括一个正整数t(1 <= t <= 100), 表示数据组数。接下来t行, 每行一组数据。每行的第一个整数为整数的个数n(1 <= n <= 100)。接下来n个正整数, 即需要求和的每个正整数。
示例如下
2 4 1 2 3 4 5 1 2 3 4 5
C语言
#include <stdio.h>
#include <stdint.h>
int main()
{
int groupNum;
if (scanf("%d", &groupNum) == EOF) {
return -1;
}
for (int groupId = 0; groupId < groupNum; groupId++) {
int dataNum;
if (scanf("%d", &dataNum) == EOF) {
break;
}
int sum = 0;
int a;
for (int i = 0; i < dataNum; i++) {
if (scanf("%d", &a) == EOF) {
break;
}
sum += a;
}
printf("%d\n", sum);
}
return 0;
}
1.6 每行第一个为个数,后面数据带空格分隔
输入数据有多组, 每行表示一组输入数据。每行的第一个整数为整数的个数n(1 <= n <= 100)。接下来n个正整数, 即需要求和的每个正整数。
示例如下
4 1 2 3 4 5 1 2 3 4 5
C语言
#include <stdio.h>
#include <stdint.h>
#define MAX_NUM 100
int main()
{
int dataNum;
while (scanf("%d", &dataNum) != EOF) {
int sum = 0;
int a;
for (int i = 0; i < dataNum; i++) {
if (scanf("%d", &a) == EOF) {
break;
}
sum += a;
}
printf("%d\n", sum);
}
return 0;
}
1.7 多组空格分隔的正整数
输入数据有多组, 每行表示一组输入数据。
每行不定有n个整数,空格隔开。(1 <= n <= 100)。
示例如下
1 2 3 4 5 0 0 0 0 0
C语言
#include <stdio.h>
#include <stdint.h>
int main()
{
int sum = 0;
int a;
while (scanf("%d", &a) != EOF) {
sum += a;
if (getchar() == '\n') {
printf("%d\n", sum);
sum = 0;
}
}
return 0;
}
2 字符串输入
2.1 第一行为整数n,第二行为n个字符串,空格隔开
输入有两行,第一行n
第二行是n个字符串,字符串之间用空格隔开
5 c d a bb e
C语言
#include <stdio.h>
#include <stdint.h>
#define MAX_NUM 100
#define MAX_LEN 1000
int main()
{
int n = 0;
char str[MAX_NUM][MAX_LEN];
if (scanf("%d", &n) == EOF) {
return -1;
}
for (int i = 0; i < n; i++) {
if (scanf("%s", str[i]) == EOF) {
break;
}
}
return 0;
}
2.2 多个测试用例,每个测试用例一行,空格分隔
多个测试用例,每个测试用例一行。
每行通过空格隔开,有n个字符,n<100
a c bb f dddd nowcoder
C语言
#include <stdio.h>
#include <stdint.h>
#define MAX_NUM 100
#define MAX_LEN 1000
int main()
{
char str[MAX_NUM][MAX_LEN];
while (scanf("%s", str[0]) != EOF) {
int n = 1;
while (getchar() != '\n') {
scanf("%s", str[n]);
n++;
continue;
}
for (int i = 0; i < n; i++) {
printf("%s ", str[i]);
}
printf("\n");
}
return 0;
}
2.3 多个测试用例,每个测试用例一行,逗号分隔
多个测试用例,每个测试用例一行。每行通过,隔开,有n个字符,n<100
a,c,bb f,dddd nowcoder
C语言
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#define MAX_NUM 100
#define MAX_LEN 1000
int main()
{
char tmp[MAX_LEN];
char str[MAX_NUM][MAX_LEN];
while (scanf("%s", tmp) != EOF) {
int n = 0;
char *ptr = strtok(tmp, ",");
while(ptr != NULL) {
strcpy(str[n], ptr);
ptr = strtok(NULL, ",");
n++;
}
for (int i = 0; i < n - 1; i++) {
printf("%s,", str[i]);
}
printf("%s", str[n - 1]);
printf("\n");
}
return 0;
}
各类输入输出练习,可以通过以下链接练习
https://ac.nowcoder.com/acm/contest/5652#question
2 排序
C语言不像其他语言,没有专门的方法给数组或者字符串排序,但也有一个快速排序的函数可以使用,就是qsort,掌握qsort函数的用法,在做排序相关的题目时,就不需要自己写排序函数,提高编码效率。以下总结可以学习下,重点掌握数组、字符串、结构体的排序方法。
qsort函数使用方法总结(详细全面+代码)_牛客网 (nowcoder.com)
3 考试常用库函数
3.1 字符串相关库函数
字符串是常考题型,掌握一些常用的库函数,可以有效提高编码效率,可以通过以下链接学习
常用的字符串相关库函数如下表,建议熟练掌握:
memcmp |
memcpy |
memset |
strcat |
strchr |
strcmp |
strcpy |
strlen |
strrchr |
strstr |
strtok |
3.2 字符相关库函数
字符相关库函数主要作用是判断当前字符的类型及大小写转换
考试常用的有以下函数
isalpha |
isdigit |
islower |
isupper |
isxdigit |
isspace |
tolower |
toupper |
4 栈和队列的简单写法
编程考试中,C语言相比于语言来说,最大的不足就是没有定义好的数据结构可以直接使用,需要自己编写代码,这样就会比其他语言多花不少时间,好在考试对数据结构操作的要求比较简单,不用写的很完善,可以写的简单一些,减少写代码的时间,栈和队列是考试中经常用到的数据结构,以下是C语言的简单实现。
4.1 栈
int stack[MAX_LEN];
int top = 0;
void StackInit(void)
{
top = 0;
}
int StackPush(int e)
{
if (top >= MAX_LEN - 1) {
return -1;
}
stack[top] = e;
top++;
return 0;
}
int StackPop(int *e)
{
if (top == 0) {
return -1;
}
*e = stack[top - 1];
top--;
return 0;
}
4.2 队列
#define MAX_LEN 1000
int queue[MAX_LEN];
int head = 0;
int tail = 0;
void QueueInit(void)
{
head = 0;
tail = 0;
}
int QueueIsEmpty(void)
{
return head == tail;
}
int QueueIsFull(void)
{
return (tail + 1) % MAX_LEN == head;
}
int QueueAdd(int e)
{
if (QueueIsFull()) {
return -1;
}
queue[tail] = e;
tail = (tail + 1) % MAX_LEN;
return 0;
}
int QueueGet(int *e)
{
if (QueueIsEmpty()) {
return -1;
}
*e = queue[head];
head = (head + 1) % MAX_LEN;
return 0;
}
5 典型题练习推荐
华为机试题目
https://www.nowcoder.com/exam/oj/ta?page=1&tpId=37&type=37
数组 | HJ97,HJ105,HJ3,HJ64 |
字符串 | HJ13,HJ18,HJ39,HJ19,HJ71,HJ29,HJ85 |
排序 | HJ68,HJ6,HJ30,HJ31,HJ34 |
队列 | HJ24,HJ88, |
链表 | HJ90,HJ48,HJ51 |
栈 | HJ50、HJ54、HJ70 |
二分法 | HJ107 |
BFS | HJ43 |
DFS | HJ67 |
