对于这样一个基本问题我很抱歉,但我一直在寻找答案,但却找不到发生这种情况的原因。
下面的代码在我推送第一个scanf以获取新的char *并将其推送到堆栈时编译出错误我得到了分段错误。
我可以通过在调用push函数时传递& val来传递分段11错误。 push(& val)但是当我像这样传递地址时,新节点不存储新信息。实施例
我要求字符串#1 - >月亮
推送值并打印堆栈
月亮二一
我要求第二个字符串 - >工作
打印堆栈,这发生了
工作二一一
所以我是C的新手并且意识到这与指针有关,并且通过引用传递vs地址vs内容(或者我的结论)也许有人可以指出我的指针和参考的好方向阅读我'已经阅读了几个,但我不确定为什么下面的代码不起作用。也许还有另一个我尚未发现的读物。
#include <stdio.h> //includes requried.
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
//defining node for stack
typedef struct node{
char *data;
struct node *pNext;
}node;
//defining functions
void push(char* a);
void printStack();
void error(char* msg);
//declaring global variables
node *pTop = NULL; //pointer to top of stack
//main function
int main(int charc, char* argv[]){
char *val;
push("One");
push("Two");
printStack();
printf("Push a new String to the stack: ");
scanf(" %s", val);
push(val);
printStack();
printf("Push a new String to the stack: ");
scanf(" %s", val);
push(val);
printStack();
}
void push(char* a) {
if (pTop == NULL) {
//stack empty, just set pTop to a new node:
pTop = malloc(sizeof(node));
pTop -> data = a;
pTop -> pNext = NULL;
} else {
//make a new node:
node *pNew = malloc(sizeof(node));
pNew -> data = a;
//assign this node's next pointer to the top node:
pNew -> pNext = pTop;
//this node is the new top of stack:
pTop = pNew;
}
}
void printStack() {
//get temporary pointer:
node *pTemp = pTop;
if (pTemp == NULL) {
error("Print error: stack empty");
return;
}
//walk down the stack, printing each value:
do {
printf("%s ", pTemp -> data);
pTemp = pTemp -> pNext;
} while (pTemp != NULL);
printf("\n");
}
void error(char* msg) {
printf("%s\n", msg);
}
答案 0 :(得分:2)
您使用的是未初始化的变量。
char *val;
//...
scanf(" %s", val);
传递给scanf
的地址将导致未定义的行为。您必须为scanf
分配一些内存才能使用。
我是如何发现这一点的?编译器发出警告!提供MCVE的+1。
答案 1 :(得分:1)
已经指出你没有初始化*val
并且使用它会导致未定义的行为。 C编译器的大多数实现都会给你一个程序,它会指向一个看似随机的内存地址,而且很幸运,你在scanf(" %s", val);
中使用它并不会导致分段错误。
但这不是你所描述的行为的原因(输入的第一个字符串被第二个字符串覆盖)。原因是:
scanf(" %s", val);
时,它都会写入相同的内存地址,因为val
从未获得指向的新地址。pTop -> data = a;
不会复制字符串。它只是使pTop -> data
指向与a
相同的内存地址。解决方案是每次要获取新字符串时,为val
提供一个新地址(例如malloc()
返回的地址)。或者甚至更好,让push()
通过更改:
pTop -> data = a;
为:
size_t size = strlen(a) + 1;
pTop -> data = malloc(size);
if (pTop -> data) {
memcpy(pTop -> data, a, size);
} else {
// handle error. E.g. exit(1)
}
(或者,如果你正在为POSIX系统编程,那就是这个:
pTop -> data = strdup(a); // Remember to check for error
)。
请记住:
free()
所有这些字符串。scanf()
不会向val
写入超出其余空间的内容。 答案 2 :(得分:0)
你似乎没有使用malloc为字符串分配内存。 所以当你退出推送功能时,堆栈上的数据(真实数据)将被删除,不再可访问。 对于struct中的每个指针,你应该使用malloc。
请尝试使用malloc作为字符串。
答案 3 :(得分:0)
好的,这就是我到目前为止所做的事情,以便将字符串正确地推送到堆栈。我的问题是编码是多余的,我认为对于任何类型的大型项目都没有意义。我对C感兴趣,因为我在离开10年后回到了编码状态。我用VB很好地了解Java,javascript并修改了SQL查询。决定回到一切,并希望学习C进出,因为它与其他语言不同,直接与内存位置一起工作。
这是我从上面修改过的代码,你会看到我已经将malloc给了我的char *但是你会看到我有一些重复的代码来推动我的字符串。当我将其更改为int时,浮动我不必使用malloc或null。我可以推动它,当我扫描他们的int
时,它工作正常在我的推送功能中制作malloc时,它会打印以下内容。不知道该怎么办只能让它存储新的字符串,如果我每次在scanf之前在main函数中使用malloc。
当我去printStack()时,四个一个;代码如下
#include <stdio.h> //includes requried.
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
//defining node for stack
typedef struct node{
char *data;
struct node *pNext;
}node;
//defining functions
void push(char* a);
void printStack();
void error(char* msg);
//declaring global variables
node *pTop = NULL; //pointer to top of stack
//main function
int main(int charc, char* argv[]){
char* val = malloc(256);
push("One");
push("Two");
printStack();
printf("Push a new String to the stack: ");
scanf(" %s", val);
push(val);
printStack();
//val = malloc(256); //this doesn't seem proper coding reptitive
printf("Push a new String to the stack: ");
scanf(" %s", val);
push(val);
printStack();
free(val);
} //Memory Leaks maybe?
void push(char* a) {
if (pTop == NULL) {
//stack empty, just set pTop to a new node:
pTop = malloc(sizeof(node));
pTop -> data = a;
pTop -> pNext = NULL;
} else {
//make a new node:
//printf("line46-Pushing: %s\n",a);
node *pNew = malloc(sizeof(node));
pNew -> data = malloc(sizeof(a));
pNew -> data = a;
//assign this node's next pointer to the top node:
pNew -> pNext = pTop;
//this node is the new top of stack:
pTop = pNew;
//free(t);
}
}
void printStack() {
//get temporary pointer:
node *pTemp = pTop;
if (pTemp == NULL) {
error("Print error: stack empty");
return;
}
//walk down the stack, printing each value:
do {
printf("%s ", pTemp -> data);
pTemp = pTemp -> pNext;
} while (pTemp != NULL);
printf("\n");
}
void error(char* msg) {
printf("%s\n", msg);
}
答案 4 :(得分:0)
好的,我知道这不是一个巨大的成就,但我终于得到了我认为逻辑上可行的方法。我真的很感激C专家看看我提出的问题,并指出任何可能在以后引起问题的坏习惯或事情。我感谢大家的帮助。
#include <stdio.h> //includes requried.
#include <stdlib.h>
#include <limits.h>
#include <ctype.h>
#include <string.h>
//defining node for stack
typedef struct node{
char *data;
struct node *pNext;
}node;
//defining functions
void push(char* a);
void printStack();
void error(char* msg);
char* pop();
//declaring global variables
node *pTop = NULL; //pointer to top of stack
//main function
int main(int charc, char* argv[]){
printf("Welcome to fun with stacks to get a list of full commands enter 'HELP'\n");
char* val;
char* usr_chc = malloc(256);
do{
printf("Enter your choice to PUSH, POP, PRINT or EXIT\n");
scanf("%s",usr_chc);
if(strcmp(usr_chc,"PUSH")==0 || strcmp(usr_chc,"push")==0){
val = malloc(256);
printf("Push a new String to the stack: ");
scanf(" %s", val);
push(val);
printStack();
}else if(strcmp(usr_chc,"POP")==0 || strcmp(usr_chc,"pop")==0 ){
pop();
}else if(strcmp(usr_chc,"PRINT")==0 || strcmp(usr_chc,"print")==0){
printStack();
}else if(strcmp(usr_chc,"HELP")==0 || strcmp(usr_chc,"help")==0){
printf("The list of commandds\n POP - to pop the top node off the stack\n PUSH to add new data to the stack \n PRINT - Print the stack data\n EXIT to quit the program\n");
}
}while(strcmp(usr_chc,"EXIT")!=0);
} //Memory Leaks maybe?
void push(char* a) {
if (pTop == NULL) {
//stack empty, just set pTop to a new node:
pTop = malloc(sizeof(node));
pTop -> data = a;
pTop -> pNext = NULL;
} else {
//make a new node:
//printf("line46-Pushing: %s\n",a);
node *pNew = malloc(sizeof(node));
pNew -> data = a;
//assign this node's next pointer to the top node:
pNew -> pNext = pTop;
//this node is the new top of stack:
pTop = pNew;
//free(t);
}
}
void printStack() {
//get temporary pointer:
node *pTemp = pTop;
if (pTemp == NULL) {
error("Print error: stack empty");
return;
}
//walk down the stack, printing each value:
do {
printf("%s ", pTemp -> data);
pTemp = pTemp -> pNext;
} while (pTemp != NULL);
printf("\n");
}
void error(char* msg) {
printf("%s\n", msg);
}
char* pop() {
//is the stack empty?
if (pTop == NULL) {
error("Pop error: stack empty");
return NULL;
} else {
char *retVal = pTop -> data;
//temp pointer to top
node *pTemp = pTop;
//set pTop to next node:
pTop = pTop -> pNext;
//free temp node:
free(pTemp);
return retVal;
}
}