user-0 提问: C语言构建栈push操作有问题

回复:
user: user-0
content: 引用 3 楼 user-1 的回复:浅拷贝，它拷贝的是对象的地址，它与原对象共享一个对象。    stack->data[++stack->top] = item； 仅copy了地址，没有复制真正的内容，所以说是浅copy。  如你所说：这样写的目的是将二维数组的每一行的指针都指向输入的item这个数组。 这个思路是正确的，但是你需要为其用malloc动态分配一个数组，以保证其所指向的内容是不同的。   Push(stack, realcommand);，保存的是realcommand的地址，指向的是同一个内存地址~~  所以当realcommand的值改变时，就出现了这样的情况 C：\Users\hp\micro> C：\Users\hp\soft\soft>  而 Push(stack, "Users");    Push(stack, "hp");， "Users"、"hp"这两个无名数组的内存地址是不一样的，所以显示正常。  简单的讲吧，如果你压栈函数想用： stack->data[++stack->top] = item；通常情况下，item应当是用malloc动态分配的。  惭愧 ，手误了，没检查，free(stack); 应改为free_stack(stack);   哇 彻底清楚了！！真的非常感谢！ 这积分我留着有何用，全都给你！！再次感谢！

user: user-1
content: 看你的入栈函数，浅copy啊~~~并没有将真正的内容压到栈里去。  按你的思路，改了一下代码.  #include <stdio.h> #include <stdlib.h> #include <string.h>  #define ElementType char //存储数据元素的类型 #define MAXSIZE 1000 //存储数据元素的最大个数  //堆栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成 typedef struct { 	ElementType** data; 	int top; }Stack;  //初始化栈 Stack* InitStack() { 	Stack* stack; 	stack = (Stack*)malloc(sizeof(Stack)); 	stack->data = (ElementType * *)malloc(sizeof(ElementType*) * 1000); 	if (!stack) { 		printf("空间不足\n"); 		return NULL; 	} 	stack->top = -1; 	return stack; }  void PrintStack(Stack* stack) { 	printf("当前栈中的元素:\n"); 	int i; 	for (i = stack->top; i >= 0; i--) { 		printf("%s\n", stack->data[i]); 	} }  int IsFull(Stack* stack) { 	if (stack->top == MAXSIZE - 1) { 		printf("堆栈已满\n"); 		return 1; 	} 	return 0; }  int IsEmpty(Stack* stack) { 	if (stack->top == -1) { 	//	printf("堆栈空\n"); 		return 1; 	} 	return 0; }  //入栈 void Push(Stack* stack, const ElementType* item) { 	if (IsFull(stack)) { 		return; 	} 	++stack->top; 	stack->data[stack->top] = (char*)malloc(sizeof(char) * strlen(item) + 1); 	strcpy(stack->data[stack->top], item); 	//stack->data[++stack->top] = item; }  //出栈  栈的空间是动态分配的，所以要修改出栈函数 //原先出栈函数，需要静态的。 int Pop(Stack* stack) { //, ElementType* item 	if (IsEmpty(stack)) { 		return 0; 	} 	//strcpy(item, stack->data[stack->top]);   	free(stack->data[stack->top]); 	stack->top--; 	return 1; }  //打印路径 void print_path(Stack* stk) { 	printf("C:"); 	if (IsEmpty(stk)) 		printf("\\"); 	else 		for (int i = 0; i <= stk->top; i++) 			printf("\\%s", stk->data[i]); 	printf(">\n"); }  //释放空间 void free_stack(Stack* stk) { 	if (!IsEmpty(stk)) { 		for (int i = stk->top; i == -1; i--) 			Pop(stk); 	} 	free(stk->data); 	free(stk); }   int main() { 	Stack* stack; 	stack = InitStack(); 	Push(stack, "Users"); 	Push(stack, "hp");  	int num = 0; 	scanf("%d", &num); 	getchar(); 	char command[15] = { '\0' };  	while ((num > 0) && (scanf("%[^\n]", command) != EOF)) { 		getchar(); 		if (command[3] == '.') { 			Pop(stack); 			print_path(stack); 		} 		else { 			Push(stack, command + 3); 			print_path(stack); 		} 		num--; 	} 	free(stack); 	return 0; }

user: user-1
content: 浅拷贝，它拷贝的是对象的地址，它与原对象共享一个对象。   stack->data[++stack->top] = item； 仅copy了地址，没有复制真正的内容，所以说是浅copy。  如你所说：这样写的目的是将二维数组的每一行的指针都指向输入的item这个数组。 这个思路是正确的，但是你需要为其用malloc动态分配一个数组，以保证其所指向的内容是不同的。   Push(stack, realcommand);，保存的是realcommand的地址，指向的是同一个内存地址~~  所以当realcommand的值改变时，就出现了这样的情况 C：\Users\hp\micro> C：\Users\hp\soft\soft>  而 Push(stack, "Users");    Push(stack, "hp");， "Users"、"hp"这两个无名数组的内存地址是不一样的，所以显示正常。  简单的讲吧，如果你压栈函数想用： stack->data[++stack->top] = item；通常情况下，item应当是用malloc动态分配的。  惭愧 ，手误了，没检查，free(stack); 应改为free_stack(stack);

user: user-0
content: 太感谢楼上的大佬了！代码不仅功能实现了，而且代码行文也简洁了许多，学到了很多！万分感谢！ 还有两个小问题，能不能再麻烦大佬给稍微讲解一下：  1. 不是很懂为什么Push函数中 stack->data[++stack->top] = item; 这样的写法是浅拷贝呢？我之前的理解是data是一个二维数组，stack->data[++stack->top] = item;这样写的目的是将二维数组的每一行的指针都指向输入的item这个数组；如果说这样是浅拷贝的话，那么为什么在输入命令行之前，先push了一个users，再push了一个hp，后面不管输入 cd 啥，输出的路径中 users和hp都是没有错的呢？这一点我有点想不明白。  2. 还有就时看到您写了一个叫free_stack的函数，这个函数是不是在您的代码中最终没有使用？还是说在这边您有一个笔误，应该在代码最后return 0之前调用这个函数呢？  引用 1 楼 user-1 的回复:看你的入栈函数，浅copy啊~~~并没有将真正的内容压到栈里去。  按你的思路，改了一下代码.  #include <stdio.h> #include <stdlib.h> #include <string.h>  #define ElementType char //存储数据元素的类型 #define MAXSIZE 1000 //存储数据元素的最大个数  //堆栈的顺序存储结构通常由一个一维数组和一个记录栈顶元素位置的变量组成 typedef struct { 	ElementType** data; 	int top; }Stack;  //初始化栈 Stack* InitStack() { 	Stack* stack; 	stack = (Stack*)malloc(sizeof(Stack)); 	stack->data = (ElementType * *)malloc(sizeof(ElementType*) * 1000); 	if (!stack) { 		printf("空间不足\n"); 		return NULL; 	} 	stack->top = -1; 	return stack; }  void PrintStack(Stack* stack) { 	printf("当前栈中的元素:\n"); 	int i; 	for (i = stack->top; i >= 0; i--) { 		printf("%s\n", stack->data[i]); 	} }  int IsFull(Stack* stack) { 	if (stack->top == MAXSIZE - 1) { 		printf("堆栈已满\n"); 		return 1; 	} 	return 0; }  int IsEmpty(Stack* stack) { 	if (stack->top == -1) { 	//	printf("堆栈空\n"); 		return 1; 	} 	return 0; }  //入栈 void Push(Stack* stack, const ElementType* item) { 	if (IsFull(stack)) { 		return; 	} 	++stack->top; 	stack->data[stack->top] = (char*)malloc(sizeof(char) * strlen(item) + 1); 	strcpy(stack->data[stack->top], item); 	//stack->data[++stack->top] = item; }  //出栈  栈的空间是动态分配的，所以要修改出栈函数 //原先出栈函数，需要静态的。 int Pop(Stack* stack) { //, ElementType* item 	if (IsEmpty(stack)) { 		return 0; 	} 	//strcpy(item, stack->data[stack->top]);   	free(stack->data[stack->top]); 	stack->top--; 	return 1; }  //打印路径 void print_path(Stack* stk) { 	printf("C:"); 	if (IsEmpty(stk)) 		printf("\\"); 	else 		for (int i = 0; i <= stk->top; i++) 			printf("\\%s", stk->data[i]); 	printf(">\n"); }  //释放空间 void free_stack(Stack* stk) { 	if (!IsEmpty(stk)) { 		for (int i = stk->top; i == -1; i--) 			Pop(stk); 	} 	free(stk->data); 	free(stk); }   int main() { 	Stack* stack; 	stack = InitStack(); 	Push(stack, "Users"); 	Push(stack, "hp");  	int num = 0; 	scanf("%d", &num); 	getchar(); 	char command[15] = { '\0' };  	while ((num > 0) && (scanf("%[^\n]", command) != EOF)) { 		getchar(); 		if (command[3] == '.') { 			Pop(stack); 			print_path(stack); 		} 		else { 			Push(stack, command + 3); 			print_path(stack); 		} 		num--; 	} 	free(stack); 	return 0; }