今天是个好日子。我是C语言的新手,而且堆栈溢出,所以请对我轻松一点:)
我对C中的此堆栈代码有几个疑问:
1)push(&stackPtr, value);
为什么stackPtr必须具有&符号?没有它会得到什么功能?
2)topPtr = newPtr;
为什么topPtr必须是* topPtr?没有它的代码又是怎么回事?
3)*topPtr = (*topPtr)->nextPtr;
为什么* topPtr必须具有*?没有*号怎么办?
感谢您提前提出任何答案。
#include <stdio.h>
#include <stdlib.h>
// self-referential structure
struct stackNode {
int data; // define data as an int
struct stackNode *nextPtr; // stackNode pointer
};
typedef struct stackNode StackNode; // synonym for struct stackNode
typedef StackNode *StackNodePtr; // synonym for StackNode*
// prototypes
void push(StackNodePtr *topPtr, int info);
int pop(StackNodePtr *topPtr);
void printStack(StackNodePtr currentPtr);
void instructions(void);
// function main begins program execution
int main(void)
{
StackNodePtr stackPtr = NULL; // points to stack top
int value; // int input by user
instructions(); // display the menu
printf("%s", "? ");
unsigned int choice; // user's menu choice
scanf("%u", &choice);
// while user does not enter 3
while (choice != 3) {
switch (choice) {
// push value onto stack
case 1:
printf("%s", "Enter an integer: ");
scanf("%d", &value);
push(&stackPtr, value);
printStack(stackPtr);
break;
// pop value off stack
case 2:
// if stack is not empty
if (stackPtr != NULL) {
printf("The popped value is %d.\n", pop(&stackPtr));
}
printStack(stackPtr);
break;
default:
puts("Invalid choice.\n");
instructions();
break;
} // end switch
printf("%s", "? ");
scanf("%u", &choice);
}
puts("End of run.");
}
// display program instructions to user
void instructions(void)
{
puts("Enter choice:\n"
"1 to push a value on the stack\n"
"2 to pop a value off the stack\n"
"3 to end program");
}
// insert a node at the stack top
void push(StackNodePtr *topPtr, int info)
{
StackNodePtr newPtr = malloc(sizeof(StackNode));
// insert the node at stack top
if (newPtr != NULL) {
newPtr->data = info;
newPtr->nextPtr = *topPtr;
topPtr = newPtr;
}
else { // no space available
printf("%d not inserted. No memory available.\n", info);
}
}
// remove a node from the stack top
int pop(StackNodePtr *topPtr)
{
StackNodePtr tempPtr = *topPtr;
int popValue = (*topPtr)->data;
*topPtr = (*topPtr)->nextPtr;
free(tempPtr);
return popValue;
}
// print the stack
void printStack(StackNodePtr currentPtr)
{
// if stack is empty
if (currentPtr == NULL) {
puts("The stack is empty.\n");
}
else {
puts("The stack is:");
// while not the end of the stack
while (currentPtr != NULL) {
printf("%d --> ", currentPtr->data);
currentPtr = currentPtr->nextPtr;
}
puts("NULL\n");
}
}
最佳答案
这都是非常基本的C语言,因此我会尽量保持清晰,但是我建议您仔细阅读有关该主题的参考书。
该代码定义了一个包含某些数据的结构stackNode
和一个指向该相同结构的“指针”。
因为stackNode
是结构,所以当您将其作为参数传递给函数时,编译器会创建它的副本并将其提供给函数。这称为“通过副本传递参数”。范例:
StackNode node;
foo(node) ;
void foo(StackNode n) {
/* foo() function can use the parameter n which is a local copy of node.
you can modify n in the foo() function, that will not modify the node variable */
}
这意味着该函数无法修改您的原始数据。它可以修改函数的本地副本,该副本在函数末尾丢失。
如果要修改给定的参数,则必须“按地址”而不是“按副本”传递参数。您可以这样进行:
StackNode node;
foo(&node) ;
void foo(StackNode *n) {
/* foo() function accesses the node variable via its address n. (*n) represents
the content at address n, which is node. */
}
在此代码中,函数foo()获取StackNode的地址(而不是StackNode的副本)。通过“取消引用”地址,您可以访问指针“指向”的内容,因此可以“实际”对其进行修改。 “取消引用”由“ *”运算符执行,而“&”运算符给出变量的“引用”(地址)。
所以现在,到您的代码。我会以稍微不同的顺序回答您的问题,以使其更清楚(我认为)。
void push(StackNodePtr *topPtr, int info)
的作用是malloc一个新节点,使其指向当前的topPtr,然后修改topPtr以指向该新节点。因此,它修改了topPtr。
因此,topPtr需要通过引用传递。
因此,您需要
void push(StackNodePtr *topPtr, int info)
而不是void push(StackNodePtr topPtr, int info)
因此,您需要使用
push(&stackPtr ,value)
进行调用如果您呼叫
push(stackPtr ,value)
,则:首先,您的编译器应该抱怨(至少发出警告)
当您修改内存的未知区域时,您将有一天或一天崩溃
您现在还应该了解为什么需要
(*topPtr) = newPtr
而不是topPtr = newPtr
的原因。因为您要修改stackPtr,所以需要取消引用topPtr。在后面的代码中相同。
这就是说,我可以想到实现堆栈要容易得多... ;-)
关于c - C栈实现。有关取消引用和双指针的问题,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/58633245/