BUAA北航2021期末数据结构B题

闲来无事,写个题解

原题如图:

另有文字版:

【问题描述】
给定某能正常运⾏结束的⽤户函数调⽤栈信息(当⼀个函数被调⽤时将⼊栈,当调⽤返回时,将出栈)。编写程序,对函数调⽤栈信
息进⾏分析,依据函数⼊栈和出栈信息,分析函数调⽤关系,即⼀个函数调⽤了哪些不同函数。 按运⾏时调⽤序输出调⽤关系
说明:
1. 在⼀个函数中, 同⼀函数有可能被调⽤多次,输出调⽤关系时只输出⼀次 ;若⼀个函数 没有调⽤其它函数,则不输出调⽤关系
2. 函数运⾏时调⽤序是指 函数在调⽤栈中的出现序
3. 程序中 不存在递归调⽤。函数名符合C语⾔标识符的规定,函数名⻓度不超过20,每个函数最多调⽤不超过10个不同函数,程序中 ⽤户定义的函数个数不超过100
算法提示: 当⼀个函数⼊栈时,它就是当前栈顶函数调⽤的⼀个函数
【输⼊形式】
假设⽤8表示函数⼊栈操作;⽤0表示当前函数出栈。当操作为8(⼊栈)时,输⼊形式为:
<操作> <函数名>
当操作为0(出栈)时,输⼊形式为:
<操作>
所有⼊栈操作和出栈操作都是从标准输⼊分⾏输⼊,假设调⽤栈中函数个数最多不超过200。开始时,调⽤栈为空,当 调⽤栈再次为 空时,输⼊结束
【输出形式】
运⾏时调⽤先后顺序 输出函数调⽤关系到标准输出,每⾏为⼀个函数的调⽤关系信息,包括:函数名及被调⽤函数,函数与被调⽤
函数间⽤⼀个 英⽂冒号 “:”分隔,被调⽤函数间⽤⼀个 英⽂逗号 “,”分隔, 最后⼀个函数名后跟⼀个回⻋ 若⼀个函数没有调⽤其它函 数,则不输出
由于字符串的处理有些麻烦,如果将题目中的函数的字符串类型替换成INT整形,是不是就要简化一些?

因此我们首先想到做一个转换,把字符串存储起来,再以数组的下标代替函数,相当于给函数名编了号。接下来应用这个编号进行函数调用。

具体所需的关键数组包括下面三个,一个line为栈,name用来存储函数名,其一维下标天然地就是编号。另外一个ans用来存放函数调用关系。


int line[100];
int ans[100][10];
char name[MAX][20];

将name扫入后,拿到其编号J,并将其入栈。

以下为原代码:
//Assignment EXAM B
#include <stdio.h>
#include <string.h>
#include <stdlib.h>

typedef struct L
{
    int num;
    struct L *next, *last;
} line;

int main()
{
    int i, j, k;
    int a, mark, total;
    int ans[100][10] = {};

    char pre[100] = {};
    char name[100][30] = {};

    line *head, *end, *p, *now;

    i = j = k = 0;
    a = mark = 0;
    total = -1;

    end = p = 0;
    head = (line *)malloc(sizeof(line));
    head->num = 0, head->next = head->last = 0;
    end = head, p = head;

    scanf("%d %s", &a, &pre);

    p = (line *)malloc(sizeof(line));
    p->last = end, p->num = ++total, p->next = 0;
    head->next = p, end = p;
    strcpy(name[total], pre);

    while (scanf("%d", &a))
    {
        if (a == 8)
        {
            mark = 0;
            memset(pre, 0, sizeof(pre));
            scanf("%s", &pre);
            p = (line *)malloc(sizeof(line));
            p->last = end, p->num = ++total, p->next = 0;
            end->next = p, end = p;
            strcpy(name[total], pre);
            now = p->last;

            for (i = 0; i < total - 1; i++)
            {
                if (strcmp(name[now->num], name[i]) == 0)
                {
                    mark = i;
                    break;
                }
            }
            if (mark != 0)
            {
                j = mark, mark = 0;
                for (i = 1; i < ans[j][0]; i++)
                {
                    if (strcmp(pre, name[ans[j][i]]) == 0)
                        mark = 1;
                }
                if (mark == 0)
                {
                    ans[j][0]++;
                    ans[j][ans[j][0]] = p->num;
                }
            }
            else
            {
                ans[now->num][0]++;
                ans[now->num][ans[now->num][0]] = p->num;
            }
        }
        else
        {
            p = end, end = end->last;
            end->next = 0;
            free(p);
            if (!head->next)
                break;
        }
    }

    for (i = 0; i < 99; i++)
    {
        if (ans[i][0])
        {
            printf("%s:%s", name[i], name[ans[i][1]]);
            for (j = 2; j <= ans[i][0]; j++)
                printf(",%s", name[ans[i][j]]);
            printf("\n");
        }
    }
    return 0;
}

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值