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  | 
查看22道真题和解析
