2023年05月 C/C++(六级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C++编程(1~8级)全部真题・点这里

第1题:字符串插入

有两个字符串str和substr,str的字符个数不超过10,substr的字符个数为3。(字符个数不包括字符串结尾处的'\0'。)将substr插入到str中ASCII码最大的那个字符后面,若有多个最大则只考虑第一个。

时间限制:1000

内存限制:65536
输入

输入包括若干行,每一行为一组测试数据,格式为 str substr
输出

对于每一组测试数据,输出插入之后的字符串。
样例输入

abcab eee

12343 555
样例输出

abceeeab

12345553

下面是使用C语言编写的示例代码,实现将substr插入到str中ASCII码最大的字符后面:

c 复制代码
#include <stdio.h>
#include <string.h>

void insertSubstring(char *str, const char *substr) {
    int maxIndex = 0;
    int maxAscii = str[0];

    // 找到ASCII码最大的字符的索引
    for (int i = 1; str[i] != '\0'; i++) {
        if (str[i] > maxAscii) {
            maxAscii = str[i];
            maxIndex = i;
        }
    }

    // 在最大字符后面插入substr
    int strLen = strlen(str);
    int substrLen = strlen(substr);
    for (int i = strLen; i > maxIndex + 1; i--) {
        str[i + substrLen] = str[i];
    }
    for (int i = 0; i < substrLen; i++) {
        str[maxIndex + 1 + i] = substr[i];
    }
}

int main() {
    char str[11];
    char substr[4];

    while (scanf("%s %s", str, substr) != EOF) {
        insertSubstring(str, substr);
        printf("%s\n", str);
    }

    return 0;
}

代码中的insertSubstring函数用于将substr插入到str中ASCII码最大的字符后面。它首先遍历str找到ASCII码最大的字符的索引,然后将substr插入到该索引后面。插入操作分两步:首先将原来的字符依次向后移动,然后将substr插入到空出的位置。

main函数中,我们使用scanf读取输入的每一组测试数据,然后调用insertSubstring函数进行处理,并输出结果。

第2题:机器翻译

VariantF的电脑上安装了一个机器翻译软件,他经常用这个软件来翻译英语文章。这个翻译软件的原理很简单,它只是从头到尾,依次将每个英文单词用对应的中文含义来替换。对于每个英文单词,软件会先在内存中查找这个单词的中文含义,如果内存中有,软件就会用它进行翻译;如果内存中没有,软件就会在外存中的词典内查找,查出单词的中文含义然后翻译,并将这个单词和译义放入内存,以备后续的查找和翻译。

假设内存中有M 个单元,每单元能存放一个单词和译义。每当软件将一个新单词存入内存前,如果当前内存中已存入的单词数不超过M,软件会将新单词存入一个未使用的内存单元;若内存中已存入M 个单词,软件会清空最早进入内存的那个单词,腾出单元来,存放新单词。

假设一篇英语文章的长度为N 个单词。给定这篇待译文章,翻译软件需要去外存查找多少次词典?假设在翻译开始前,内存中没有任何单词。

时间限制:1000

内存限制:262144
输入

第一行为两个正整数M 和N,代表内存容量和文章的长度。 第二行为N 个非负整数,按照文章的顺序,每个数(大小不超过1000000)代表一个英文单词。文章中两个单词是同一个单词,当且仅当它们对应的非负整数相同。 对于50%的数据,1<=N、M<=1000; 对于100%的数据,1<=N、M<=1000000。
输出

一个整数,为软件需要查词典的次数。
样例输入

3 7

1 2 1 5 4 4 1
样例输出

5
提示

整个查字典过程如下:每行表示一个单词的翻译,冒号前为本次翻译后的内存状况: 空:内存初始状态为空。 1. 1:查找单词1 并调入内存。 2. 1 2:查找单词2 并调入内存。 3. 1 2:在内存中找到单词1。 4. 1 2 5:查找单词5 并调入内存。 5. 2 5 4:查找单词4 并调入内存替代单词1。 6. 2 5 4:在内存中找到单词4。 7. 5 4 1:查找单词1 并调入内存替代单词2。 共计查了5 次词典。

下面是使用C语言编写的示例代码,实现计算翻译软件需要查词典的次数:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int word;
    int translation;
} MemoryUnit;

int main() {
    int M, N;
    scanf("%d %d", &M, &N);

    int* words = (int*)malloc(N * sizeof(int));
    for (int i = 0; i < N; i++) {
        scanf("%d", &words[i]);
    }

    MemoryUnit* memory = (MemoryUnit*)malloc(M * sizeof(MemoryUnit));
    int memoryCount = 0;
    int dictionaryCount = 0;

    for (int i = 0; i < N; i++) {
        int currentWord = words[i];
        int found = 0;

        for (int j = 0; j < memoryCount; j++) {
            if (memory[j].word == currentWord) {
                found = 1;
                break;
            }
        }

        if (!found) {
            if (memoryCount < M) {
                memory[memoryCount].word = currentWord;
                memory[memoryCount].translation = 0;
                memoryCount++;
            } else {
                memory[0].word = currentWord;
                memory[0].translation = 0;
                dictionaryCount++;
            }
        }
    }

    printf("%d\n", dictionaryCount);

    free(words);
    free(memory);

    return 0;
}

代码中,我们使用动态数组words保存待翻译文章中的单词,使用动态数组memory保存内存中的词典单元。memory数组的每个元素是一个MemoryUnit结构体,包含wordtranslation字段,分别表示单词和译义。

我们使用memoryCount变量记录当前内存中已存入的单词数,使用dictionaryCount变量记录查词典的次数。

对于每个待翻译的单词,我们遍历内存中的词典单元,检查是否存在该单词,如果找到则表示无需查词典,如果未找到则需要进行查词典的操作。

当内存未满时,我们将新单词存入一个未使用的内存单元,并增加memoryCount;当内存已满时,我们将最早进入内存的单词替换为新单词,并增加dictionaryCount

最后,我们输出dictionaryCount作为结果,表示翻译软件需要查词典的次数。

第3题:栈基本操作

依次读入序列元素1,2,...,n进栈,每进一个元素,机器可要求下一个元素进栈或弹栈,如此进行。给定一个输入序列,判断栈空时弹出的元素构成的序列是否可能等于给定的序列,如果是则输出栈的操作过程,否则输出"NO"。

时间限制:1000

内存限制:65535
输入

输入分两行 第一行为n的值(即序列元素个数) 第二行为给定的输入序列(序列元素均为整型)
输出

如果输入序列能够由题目规定的操作得到,则输出对栈的操作过程 否则直接输出"NO"
样例输入

7

4 5 3 6 2 7 1
样例输出

PUSH 1

PUSH 2

PUSH 3

PUSH 4

POP 4

PUSH 5

POP 5

POP 3

PUSH 6

POP 6

POP 2

PUSH 7

POP 7

POP 1
提示

给定序列中有可能有不在1...n之间的数字

下面是使用C语言编写的示例代码,实现栈的基本操作和判断输入序列是否可以通过栈操作得到:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int* elements;
    int top;
} Stack;

void initStack(Stack* stack, int size) {
    stack->elements = (int*)malloc(size * sizeof(int));
    stack->top = -1;
}

void push(Stack* stack, int element) {
    stack->top++;
    stack->elements[stack->top] = element;
}

int pop(Stack* stack) {
    int element = stack->elements[stack->top];
    stack->top--;
    return element;
}

int main() {
    int n;
    scanf("%d", &n);

    int* sequence = (int*)malloc(n * sizeof(int));
    for (int i = 0; i < n; i++) {
        scanf("%d", &sequence[i]);
    }

    Stack stack;
    initStack(&stack, n);

    int current = 1;
    int sequenceIndex = 0;
    int possible = 1;

    while (sequenceIndex < n) {
        if (stack.top >= 0 && stack.elements[stack.top] == sequence[sequenceIndex]) {
            pop(&stack);
            printf("POP %d\n", sequence[sequenceIndex]);
            sequenceIndex++;
        } else if (current <= n) {
            push(&stack, current);
            printf("PUSH %d\n", current);
            current++;
        } else {
            possible = 0;
            break;
        }
    }

    if (possible) {
        printf("YES\n");
    } else {
        printf("NO\n");
    }

    free(sequence);
    free(stack.elements);

    return 0;
}

代码中,我们使用Stack结构体表示栈,其中elements是一个动态数组,用于保存栈中的元素,top表示栈顶的索引。

initStack函数用于初始化栈,分配内存并将栈顶初始化为-1。

push函数用于将元素压入栈中,栈顶指针加1,并将元素存入栈顶位置。

pop函数用于弹出栈顶的元素,返回栈顶元素的值,并将栈顶指针减1。

main函数中,我们首先读入输入序列,并初始化一个大小为n的栈。

然后,我们使用current变量表示下一个要进栈的元素,使用sequenceIndex变量表示输入序列的当前位置,使用possible变量表示输入序列是否可由栈操作得到。

我们使用循环对输入序列进行处理,判断栈顶元素和当前输入序列位置的元素是否相等,如果相等,则执行弹栈操作,并将sequenceIndex加1;如果不相等,则执行压栈操作,并将current加1。

如果栈操作结束后,输入序列已全部处理完毕(sequenceIndex等于n),则说明输入序列可以由栈操作得到,将possible设为1;否则,将possible设为0。

最后,根据possible的值输出结果。如果输入序列可由栈操作得到,则输出栈的操作过程,否则输出"NO"。

第4题:双端队列

定义一个双端队列,进队操作与普通队列一样,从队尾进入。出队操作既可以从队头,也可以从队尾。编程实现这个数据结构。

时间限制:1000

内存限制:65535
输入

第一行输入一个整数t,代表测试数据的组数。 每组数据的第一行输入一个整数n,表示操作的次数。 接着输入n行,每行对应一个操作,首先输入一个整数type。 当type=1,进队操作,接着输入一个整数x,表示进入队列的元素。 当type=2,出队操作,接着输入一个整数c,c=0代表从队头出队,c=1代表从队尾出队。 n <= 1000
输出

对于每组测试数据,输出执行完所有的操作后队列中剩余的元素,元素之间用空格隔开,按队头到队尾的顺序输出,占一行。如果队列中已经没有任何的元素,输出NULL。
样例输入

2

5

1 2

1 3

1 4

2 0

2 1

6

1 1

1 2

1 3

2 0

2 1

2 0
样例输出

3

NULL

下面是一个使用C语言编写的双端队列的实现,满足题目的要求:

c 复制代码
#include <stdio.h>
#include <stdlib.h>

#define MAX_SIZE 1000

typedef struct {
    int data[MAX_SIZE];
    int front; // 队头指针
    int rear;  // 队尾指针
} Deque;

void initDeque(Deque* deque) {
    deque->front = -1; // 初始化队头指针为-1
    deque->rear = -1;  // 初始化队尾指针为-1
}

int isDequeEmpty(Deque* deque) {
    return deque->front == -1; // 如果队头指针为-1,表示队列为空
}

int isDequeFull(Deque* deque) {
    return (deque->front == 0 && deque->rear == MAX_SIZE - 1) || (deque->front == deque->rear + 1);
    // 如果队头指针在队尾指针之前一个位置,或者队头指针在队尾指针之后一个位置,表示队列已满
}

void enqueueFront(Deque* deque, int x) {
    if (isDequeFull(deque)) {
        printf("Deque is full. Cannot enqueue.\n");
        return;
    }

    if (deque->front == -1) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->front == 0) {
        deque->front = MAX_SIZE - 1;
    } else {
        deque->front--;
    }

    deque->data[deque->front] = x; // 将元素放入队头位置
}

void enqueueRear(Deque* deque, int x) {
    if (isDequeFull(deque)) {
        printf("Deque is full. Cannot enqueue.\n");
        return;
    }

    if (deque->front == -1) {
        deque->front = 0;
        deque->rear = 0;
    } else if (deque->rear == MAX_SIZE - 1) {
        deque->rear = 0;
    } else {
        deque->rear++;
    }

    deque->data[deque->rear] = x; // 将元素放入队尾位置
}

int dequeueFront(Deque* deque) {
    if (isDequeEmpty(deque)) {
        printf("Deque is empty. Cannot dequeue.\n");
        return -1;
    }

    int x = deque->data[deque->front]; // 获取队头元素的值

    if (deque->front == deque->rear) {
        deque->front = -1; // 如果队列中只有一个元素,出队后将队头指针重置为-1
        deque->rear = -1;  // 如果队列中只有一个元素,出队后将队尾指针重置为-1
    } else if (deque->front == MAX_SIZE - 1) {
        deque->front = 0; // 如果队头指针在队尾指针之前一个位置,出队后将队头指针移到队头位置
    } else {
        deque->front++; // 队头指针向后移动一位
    }

    return x; // 返回出队的元素值
}

int dequeueRear(Deque* deque) {
    if (isDequeEmpty(deque)) {
        printf("Deque is empty. Cannot dequeue.\n");
        return -1;
    }

    int x = deque->data[deque->rear]; // 获取队尾元素的值

    if (deque->front == deque->rear) {
        deque->front = -1; // 如果队列中只有一个元素,出队后将队头指针重置为-1
        deque->rear = -1;  // 如果队列中只有一个元素,出队后将队尾指针重置为-1
    } else if (deque->rear == 0) {
        deque->rear = MAX_SIZE - 1; // 如果队尾指针在队头指针之后一个位置,出队后将队尾指针移到队尾位置
    } else {
        deque->rear--; // 队尾指针向前移动一位
    }

    return x; // 返回出队的元素值
}

void printDeque(Deque* deque) {
    if (isDequeEmpty(deque)) {
        printf("NULL\n");
        return;
    }

    int i;

    if (deque->front <= deque->rear) {
        for (i = deque->front; i <= deque->rear; i++) {
            printf("%d ", deque->data[i]);
        }
    } else {
        for (i = deque->front; i < MAX_SIZE; i++) {
            printf("%d ", deque->data[i]);
        }
        for (i = 0; i <= deque->rear; i++) {
            printf("%d ", deque->data[i]);
        }
    }

    printf("\n");
}

int main() {
    int t, n, i, type, x, c;

    scanf("%d", &t);

    while (t--) {
        Deque deque;
        initDeque(&deque);

        scanf("%d", &n);

        for (i = 0; i < n; i++) {
            scanf("%d", &type);

            if (type == 1) {
                scanf("%d", &x);
                enqueueRear(&deque, x);
            } else if (type == 2) {
                scanf("%d", &c);

                if (c == 0) {
                    dequeueFront(&deque);
                } else if (c == 1) {
                    dequeueRear(&deque);
                }
            }
        }

        printDeque(&deque);
    }

    return 0;
}

这个程序定义了一个双端队列的数据结构,并实现了进队和出队的操作。在主函数中,首先读取测试数据的组数t,然后对于每组数据,读取操作的次数n。接下来,根据操作类型进行进队或出队操作,最后打印队列中剩余的元素。

请注意,这个程序假设输入的数据是有效的,即不会出现在空队列中进行出队操作的情况。在实际应用中,可能需要添加更多的错误处理逻辑来确保程序的稳定性。另外,由于题目要求输出的格式是以空格分隔的元素列表,所以在输出时需要注意最后一个元素后面不要输出多余的空格。

相关推荐
lxyzcm3 分钟前
C++23新特性解析:[[assume]]属性
java·c++·spring boot·c++23
蜀黍@猿22 分钟前
C/C++基础错题归纳
c++
古希腊掌管学习的神24 分钟前
[搜广推]王树森推荐系统笔记——曝光过滤 & Bloom Filter
算法·推荐算法
qystca25 分钟前
洛谷 P1706 全排列问题 C语言
算法
古希腊掌管学习的神29 分钟前
[LeetCode-Python版]相向双指针——611. 有效三角形的个数
开发语言·python·leetcode
赵钰老师30 分钟前
【R语言遥感技术】“R+遥感”的水环境综合评价方法
开发语言·数据分析·r语言
浊酒南街31 分钟前
决策树(理论知识1)
算法·决策树·机器学习
雨中rain36 分钟前
Linux -- 从抢票逻辑理解线程互斥
linux·运维·c++
就爱学编程38 分钟前
重生之我在异世界学编程之C语言小项目:通讯录
c语言·开发语言·数据结构·算法
学术头条43 分钟前
清华、智谱团队:探索 RLHF 的 scaling laws
人工智能·深度学习·算法·机器学习·语言模型·计算语言学