我的代码不知何故运行,但它没有给出预期的结果,所以为了理解它,我开始调试,它显示发生了一个异常,在我使用free()
的行中出现了一个分段错误。下面是我的代码:
struct stack
{
char ch;
struct stack *prev;
} *top = NULL;
typedef struct stack st;
char pop();
void push(char c);
int evaluate(char arr[100]);
int main()
{
char arr[100];
printf("Enter the string to check format of string in wcwR");
gets(arr);
if (evaluate(arr) == 1)
{
printf("Entered string is in correct format");
}
else
{
printf("Entered string is in wrong format");
}
}
int evaluate(char arr[100])
{
int i;
for (i = 0; arr[i] != 'c' && arr[i] != 'C'; i++)
{
push(arr[i]);
}
i++;
int j = i;
int flag = 0;
while (arr[j] != '\0')
{
if (arr[j] != pop())
{
return 0;
}
else
{
flag = 1;
}
}
if (flag == 1)
{
return 1;
}
}
void push(char c)
{
st *p;
p = (struct stack *)malloc(sizeof(struct stack));
p->ch = c;
p->prev = top;
top = p;
}
char pop()
{
st *temp;
char item;
temp = top;
item = top->ch;
top = top->prev;
**free(temp);** //here exception occurred
return item;
}
请帮助我解决这个问题,也可以有人建议任何合适的技术来解决这样的问题,我自己?谢谢
2条答案
按热度按时间bwitn5fc1#
我将向你们展示一种处理这类问题的通用方法。我甚至不会说它是一个好的,但它对我来说一般工作,并在这里工作的第一次运行,至少在我运行的几个测试。
(This这是一篇很长的文章,因为我正在使用从代码和注解中复制和粘贴来构建示例)。
关于发布的代码
我不清楚你想干什么。一般来说,最好在代码之前发布任务的描述。通过阅读代码,我相信:
evaluate()
C
或c
C
之前的字符串在C
之后反转,则evaluate
返回true
stack
的使用是根据请求。备注:
arr[100]
这样的固定值。封装东西和使用jus指针更容易gets
。几十年来,false
的0
malloc
内存写入代码时,向free
写入代码(并测试它)。main
应该是代码的第一个函数,如果可能的话,放在单独的文件中。stack
在哪里?下面是代码中的
struct
:这是有问题的和脆弱的。
Node
。不是stack
。在编程堆栈、列表、树或类似的容器时,更安全的做法是注意容器是节点的集合(可能是空的)。每个节点都包含(或指向)一些数据。*堆栈不是节点。节点不是堆栈。
一个可能的
Stack
这里我们有一堆节点。和堆栈本身中的一些元数据:尺寸
我将进一步介绍一个完整的示例,包括C代码和输出。我正在从程序中复制和粘贴。
栈不是任务
我们需要一个堆栈实现。但是我们绝对不想把程序和栈的代码混在一起,因为
栈函数
我们需要最少的POP、PUSH和TOP操作,以及一个构造函数和一个析构函数。让我们考虑一下:
使用指针使得在代码中编写1或1,000个堆栈变得微不足道。在
C++
RAII概念中,我们将首先编写create
和destroy
。create
和destroy
的可能代码没什么特别的:我们分配一个堆栈,并通过使
size = 0
为空来设置它。(题外话:请记住,在C中有一个邪教,说不要在
malloc()
中使用强制转换。我会的永远不会作为对程序员和读者的提醒。即使像这样非常简单的代码也会为Node
或Stack
分配内存。编译器不需要这种类型转换,但是通过编写和重复它,你可以确定什么是什么,防止许多错误,为你保存很多麻烦。这种麻烦需要花费金钱、工作和时间。)(This邪教是基于一个从未更新的书从90年代和一些Usenet职位甚至从以前。在网络编程或文本编辑等领域,通常会在几行代码中为许多类型的缓冲区分配内存,甚至
malloc()
的表达式也是一个函数调用,用于计算我们需要的缓冲区大小。就这样一个一个的投像给我们清楚的说明了什么是什么。不需要演员,但也没有工资)。正如预期的那样,但每个堆栈都有自己的
size
这一事实使事情变得更简单。导航堆栈释放节点,然后free
堆栈。为什么总是返回NULL
?这只是为了使在同一行中重置指针成为可能。每天都有成千上万的程序因为使用了无效的指针而崩溃。我们不希望有任何利润。此程序可以运行:
只是精神上的支持。
top
TOP其实很简单:返回栈顶的值,栈保持不变:一行
pop
POP删除顶部的元素并将其返回给调用者:
正如预期的那样,保存元素,重新分配顶部,
free
节点,调整大小,只有几行。push
PUSH是创建一个节点并将其链接到堆栈顶部的过程。
show
:的帮助函数一般来说,堆栈没有一个方法来显示它的内容,除了测试。但我们确实在测试,所以:
这个版本有一个可选的标题,在测试中非常方便。请参阅范例。
'str_to_stack`
这只是一种将字符串压入堆栈的方法。排成一行。因此,我们可以将代码编写为:
只是为了看看
这比循环或交互式代码好得多
栈文件
stuff.h
栈头文件stuff.c
堆栈实现因此,我们可以在任何程序中包含头文件,只需编译
stuff.c
即可完整测试
这个程序
one
堆栈Overflow
other
one
复制到other
输出
evaluate()
怎么样现在我们有一个堆栈可以使用。让我们将
evaluate
更改为如果
str
是预期格式的字符串,则返回1
的函数。可能的实现
逻辑很简单,实际上不需要堆栈。但我们肯定可以用一个。不变量:
c
或C
所以
测试程序
此代码允许在顶部输入测试字符串并运行代码。一个单循环。没有读取,没有文件。
输出
完整代码
main.c
gmol16392#
你的异常并没有发生在你认为它发生的地方。弹出时你没有检查空栈,即。
top == NULL
。然后,您尝试用top->ch
解引用NULL
。代码还有其他问题。使用
fgets()
而不是gets()
,后者已被弃用。ifflag == 0
结尾没有返回值(如果“c”或“C”后面没有字符,则可以返回)。只有return flag;
没有if
。你的for
循环可以在字符串的末尾运行,因为你没有检查\0
。您没有检查malloc()
的返回值。