闲来无事,写个题解
原题如图:
另有文字版:
【问题描述】
给定某能正常运⾏结束的⽤户函数调⽤栈信息(当⼀个函数被调⽤时将⼊栈,当调⽤返回时,将出栈)。编写程序,对函数调⽤栈信
息进⾏分析,依据函数⼊栈和出栈信息,分析函数调⽤关系,即⼀个函数调⽤了哪些不同函数。
并
按运⾏时调⽤序输出调⽤关系
。
说明:
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;
}