Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
Here is are the three structures that I'm using and for instance when my program
gets 'the' as the first word, it makes *rt->str = the.
However when the next word is read, the key is equal to to the *rt->str and I don't understand why. I'm a c programmer beginnner and this has really stoppped me in my tracks.
struct node {
char *str;
int occ;
struct node *sibling;
struct node *child;
};
struct node* root;
struct node* getNew(char word[100]) {
struct node *newNode;
newNode = (struct node *)malloc(sizeof(struct node));
newNode->str = word;
newNode->sibling = NULL;
newNode->child = NULL;
newNode->occ = 0;
return newNode;
}
struct node* insert( char key[100], struct node **rt ){
if(*rt == NULL) {
*rt = getNew(key);
printf("This is the key in the root: %s\n", (*rt)->str);
return *rt;
}else{
printf("root word: %s\n", (*rt)->str);
exit(0);
}
struct node *leaf = *rt;
int n = 0;
int i;
char w2[100];
strcpy(w2, key);
printf("root word: %s\n", (*rt)->str);
for(i = 0; i < strlen((leaf)->str); i++) {
printf("%c %c \n", (leaf)->str[i], key[i]);
if((key[0] == (leaf)->str[i])) {
n++;
key = key + 1;
printf("key is: %s \n", key);
}
}
if(key[0] == 0) {
printf("key is empty \n");
}
printf("This is the word after for loop: %s \n", key);
exit(0);
}
This:
newNode->str = word;
doesn't copy the string (as in, the characters that build up the string), it just copies the location of a string, which is an argument. That location will not remain valid when the function exits, so this gives you undefined behavior when you access it later.
C does not support assigning arrays, and arrays are not pointers.
Related
This is my algorithm for adding nodes to a linked list which is in a sorted way for surnames of persons.
Here is the code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct Node {
char Name[1024];
char Surname[1024];
char Telno[1024];
struct Node* next;
};
void Add(struct Node** firstnode, struct Node* NewNode)
{
struct Node* tempo;
//printf("%d",strcmp((*firstnode)->Surname,NewNode->Surname));
if (*firstnode == NULL || (strcmp((*firstnode)->Surname,NewNode->Surname) > 0)) {
NewNode->next = *firstnode;
*firstnode = NewNode;
}
else {
tempo = *firstnode;
while (tempo->next != NULL && strcmp(tempo->Surname,NewNode->Surname) < 0) {
tempo = tempo->next;
}
NewNode->next = tempo->next;
tempo->next = NewNode;
}
}
struct Node* CreateNode(char name[1024], char surname[1024], char telno[1024])
{
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
strcpy(NewNode->Name,name);
strcpy(NewNode->Surname,surname);
strcpy(NewNode->Telno,telno);
NewNode->next = NULL;
return NewNode;
}
void Printlinkedlist(struct Node* head)
{
struct Node* temp = head;
while (temp != NULL) {
printf("%s %s %s\n", temp->Name,temp->Surname,temp->Telno);
temp = temp->next;
}
}
struct Node* head = NULL;
struct Node* temp;
int main()
{
int personcount;
char name[1024],surname[1024],telno[1024];
printf("Please give the count of person:");
scanf("%d", &personcount);
for (int i = 0; i < personcount; i++) {
printf("Please give the name of %d. person:", i + 1);
scanf(" %s", &name);
printf("Please give the surname of %d. person:", i + 1);
scanf(" %s", &surname);
printf("Please give the phone number of %d. person:", i + 1);
scanf(" %s", &telno);
temp = CreateNode(name,surname,telno);
Add(&head, temp);
}
printf("\n -------------- Linkedlist --------------\n");
Printlinkedlist(head);
return 0;
}
The first problem is this: For example, if I enter people's surnames as G, A, L, E, K (So first person's last name will be "G", second person's last name will be "A" etc..), it gives an incorrectly ordered output.
And the second one is: If I delete the comment line characters behind the printf inside the add function, I get a segmentation fault that I don't understand why
Thanks for the answer.
It should first be said that you could, and should, have figured it out yourself by either:
Debugging the program:
On Linux: How Can I debug a C program on Linux?
On Windows: How do you debug a C program on Windows?
Enabling core dumps and analyzing the core file you get when your program crashes; see this explanation.
But, more to the point, let's have a look at (some of) your code:
if (*firstnode == NULL || /* another condition */) {
// do stuff
}
else {
// so *firstnode may be NULL here
tempo = *firstnode;
while (tempo->next != /* some value */ && /* another condition*/ ) {
// do stuff
}
// do stuff
}
See the problem? tempo could get assigned a NULL point, and then de-referenced to get to the next field. That would likely cause a segmentation fault.
So I'm creating a linked list in C and adding some nodes to it that contain information. I have an if else statement where I create the linked list's head and then add nodes to it. The problem is that when I add a new node I seem to lose the old one. Not sure why this is happening or how to fix this.
Edit: I have made some updates to make it a runnable program.
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<stdint.h>
#include<regex.h>
int main(int argc, char argv[]) {
int head=0, i=0;
char tempCourseID[10], tempCourseGrade[10], tempCourseCH[10];
static struct LinkedList {
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
} LinkedList;
static struct LinkedList *first, *savefirst, *headlist;
first = malloc(sizeof ((*first)));
savefirst = first;
headlist = first;
for(i ; i<5; i++){
printf("Enter Course name");
fgets(tempCourseID, sizeof(tempCourseID), stdin);
printf("Enter Course grade");
fgets(tempCourseGrade, sizeof(tempCourseGrade), stdin);
printf("Enter Course credit hours");
fgets(tempCourseCH, sizeof(tempCourseCH), stdin);
//checks to see if linked list head exists
if (head == 0) {
printf("No head has been found.\n");
headlist->CourseName = tempCourseID;
headlist->CourseGrade = tempCourseGrade;
headlist->CourseCreditHours = tempCourseCH;
headlist->next = NULL;
printf("A head has been created\n");
printf("A node has been added\n");
head = 1;
} else {
printf("Ahead already exists\n");
first = malloc(sizeof ((*first)));
first->CourseName = tempCourseID;
first->CourseGrade = tempCourseGrade;
first->CourseCreditHours = tempCourseCH;
first->next = NULL;
savefirst->next = first;
savefirst = first;
printf("A node has been add\n");
head = 1;
}
}
while (headlist != NULL) {
printf(" %s ", headlist->CourseName);
printf(" %s ", headlist->CourseGrade);
printf("%s \n", headlist->CourseCreditHours);
headlist = headlist->next;
}
return 0;
}
You have char tempCourseID[10] and char* CourseName
It is legal to use CourseName = tempCourseID; however tempCourseID is temporary, and so the string will be lost soon. In this case we need to allocate separate memory for CourseName, and then copy the value from tempCourseID
Use instead
CourseName = malloc(strlen(tempCourseID) + 1);//add +1 for null-character
strcpy(CourseName, tempCourseID);
//or
CourseName = strdup(tempCourseID)//shortcut!
There are problem with the linked list. You have too many variables with similar names. A linked list needs only head. You can introduce a temporary variable node for adding new nodes. If you are adding nodes to the tail, then save the last node in the list, lets call it savenode
In this example I removed fgets functions and replaced it with sprintf, that's just to make it easier to run the program and debug. You can put back fgets later.
int main(int argc, char argv[])
{
struct LinkedList
{
char *CourseName;
char *CourseGrade;
char *CourseCreditHours;
struct LinkedList *next;
};
int i;
char tempCourseName[100], tempCourseGrade[100], tempCourseCH[100];
struct LinkedList *head = NULL;
struct LinkedList *node = NULL;
struct LinkedList *savenode = NULL;
for(i = 0; i < 5; i++)
{
sprintf(tempCourseName, "CourseName %d", i);
sprintf(tempCourseGrade, "tempCourseGrade %d", i);
sprintf(tempCourseCH, "tempCourseCH %d", i);
node = malloc(sizeof(*node));
node->CourseName = strdup(tempCourseName);
node->CourseGrade = strdup(tempCourseGrade);
node->CourseCreditHours = strdup(tempCourseCH);
node->next = NULL;
if(head == NULL)
head = node;
//check savenode exists
//this will be the last node (tail) in the existing list
//get it to point to our new node
if(savenode)
savenode->next = node;
//now we have a new tail
savenode = node;
}
//walk through the list
node = head;
while(node)
{
printf("%s, %s, %s\n",
node->CourseName, node->CourseGrade, node->CourseCreditHours);
node = node->next;
}
return 0;
}
I have the following problem: I made this node structure
typedef struct NODE{
struct NODE *sons[1024]; //this array will be used to store children pointers
char name[255];
int leaf;
}NODE;
and this function to create a new node with a given name. The problem is that the first printf shows the right name, the second one doesn't. It seems like the for loop erases the name and I can't explain myself why...
NODE *AllocateNewNode( char *inputname) {
NODE *newnode;
newnode = (NODE *)malloc(sizeof(NODE));
memset(newnode->name, '\0', sizeof(newnode->name));
strcpy(newnode->name, inputname);
printf("node %s created\n", newnode->name); //right name in the output
int i = 0;
for (i = 0; i <= 1024; i++) {
newnode->sons[i] = NULL;
}
newnode->leaf = 1;
printf("node %s created\n", newnode->name); //no name in the output
return newnode;
}
You're writing past the end of your sons array;
Should be for (i = 0; i < 1024; i++) { since there are only 1024 elements in the array 0...1023.
I am implementing a LinkedList with a bunch of ListNodes that are structs which contain some basic information about people. I have two files, one that is main.c, and another that is main.h. Whenever I attempt to print the list by passing the root to a function, I get an error.
Here is main.c:
#include "main.h"
/* Edward Nusinovich
This C file is going to have a LinkedList containing information about people.
The user can interact with it and manipulate the list.
*/
int main(int argc, char **argv){
if(!checkIfValidArguments(argc).value){return -1;}
ListNode *root = askForDetails(1,argv);
ListNode *current = root;
current->next = NULL;
ListNode *temp;
int index = 2;
while(index<argc){
temp = askForDetails(index,argv);
current->next = temp;
current = current->next;
index++;
}
userLoop(root);
return 0;
}
In my main.h file, I have no problem printing attributes of the root parameter in the function "userLoop", but as soon as I pass ListNode *root to "print" or "stuff" I get a seg fault when trying to print its values.
Here is main.h:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define true 1
#define false 0
typedef struct bool{
int value:1;
} boolean;
//this is going to store info about a person
typedef struct people{
char *name;
char *hairColor;
char *eyeColor;
char *age;
struct people *next;
} ListNode;
//using a 1 bit bitfield we have constructed, stores whether or not the user has entered a proper number of inputs
boolean checkIfValidArguments(int numArgs){
boolean validArguments;
if(numArgs>1){validArguments.value=true;}
else{validArguments.value=false; printf("We need some names of people.\n");}
return validArguments;
}
//this will construct a new Person and return him to
ListNode *askForDetails(int personIndex, char **argv){
ListNode toReturn;
char *name = argv[personIndex];
printf("Please enter the hair color, eye color, and age of %s.\n",name);
char *inBuf=malloc(100);
char nextchar=getchar();
int index = 0;
if(nextchar!='\n'){inBuf[index]=nextchar; index++;}
while((nextchar=getchar())!='\n'){
inBuf[index] = nextchar;
index ++;
}
toReturn.name = name;
toReturn.hairColor = strtok(inBuf," ");
toReturn.eyeColor = strtok(NULL," ");
toReturn.age = strtok(NULL,"\n");
ListNode *newNode = malloc(sizeof(ListNode));
newNode = &toReturn;
return newNode;
}
char *getInput(char *message){
printf("%s",message);
char *inBuf = malloc(40);
char nextchar=getchar();
int index = 0;
if(nextchar!='\n'){inBuf[index]=nextchar; index++;}
while((nextchar=getchar())!='\n'){
inBuf[index] = nextchar;
index ++;
}
return inBuf;
}
void addToEnd(ListNode *root){
ListNode *current = root;
char *inBuf = getInput("\nEnter the name of a person who you want to add: \n");
ListNode *toAdd = malloc(sizeof(ListNode));
toAdd = askForDetails(0,&inBuf);
toAdd->name = inBuf;
toAdd->next = NULL;
while((current->next) != NULL){
current = current->next;
}
current->next = toAdd;
}
void print(ListNode *root){
printf("The name is %s.\n",root->name);
/*
ListNode *current = root;
do{
printf("\n%s's hair is %s, their eyes are %s and they are %s years old.\n",current->name,current->hairColor,current->eyeColor,current->age);
current = current->next;
}while(current!=NULL);
*/
}
void remEnd(ListNode *root){
ListNode *current = root;
if(current == NULL){ return; }
}
void addAfter(ListNode *root){
ListNode *current = root;
char *name = getInput("\nWho do you want to add after?\n");
int comparison = 0;
while(current!=NULL&&(comparison = strcmp(name,current->name))!=0){
current = current -> next;
}
if(current==NULL){printf("\nIndividual not found.\n"); return;}
else{
char *newPerson = getInput("What's the name of the person you wish to add? ");
ListNode *toAdd = askForDetails(0,&newPerson);
ListNode *next = current->next;
current -> next = toAdd;
toAdd->next = next;
return;
}
}
void stuff(ListNode *root){
printf("name is %s.\n",root->name);
printf("Root lives at %u.\n",root);
}
void userLoop(ListNode *root){
char input = ' ';
printf("Root lives at %u.\n",root);
while(true){
printf("name is %s.\n",root->name);
if(input!='\n'){
printf("\nWhat would you like to do with your list:\n");
printf("A) Add an element at the end of the list\n");
printf("B) Remove an element from the end of the list\n");
printf("C) Add an element after an element on your list\n");
printf("D) Print your list\n");
printf("E) Quit this program\n\n");
}
input = getchar();
switch(input){
case 'A': addToEnd(root); break;
case 'B': remEnd(root); break;
case 'C': addAfter(root); break;
case 'D': stuff(root); break;
case 'E': return;
}
}
}
When printing the address in memory of root in both functions, I get the same value, so I'm not sure why I am unable to access the values in root in one function instead of the other.
Thank you so much for any help.
You don't seem to quite grasp how the memory model works in C. Your offending piece of code is probably:
ListNode *newNode = malloc(sizeof(ListNode));
newNode = &toReturn;
return newNode;
This returns a pointer to the local variable toReturn, not the malloc'd memory address. You need to copy the data from toReturn into your malloc'd memory space. However, even worse you don't malloc space for each of your strings, so each of your nodes point to the same input buffer. This should work, since you malloc with for every node, however if
you are going to start deleting nodes managing your memory is going to be a little awkward. You also don't make sure there is enough room in your buffer.
I suggest looking at some online resources (or ideally a book) to refresh on how C memory works.
Edit: I did not learn C online, but a quick google search turned up this, which at a quick glance seems to be a decent resource.
I would recommend looking into book list. I used C Programming A Modern Approach.
I'm going to assume you're on a 64 bit system so that pointers are 8 bytes & integers are 4 bytes. Use %p for pointers, not %u
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I decided that I wanted to make a program in C that would take a user input and do things with a hash table... When I go to put in something it gets a segmentation fault at line 32. This being the following:
if (!hashTable[hashIndex].head) {
Rest of code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
struct hash *hashTable = NULL;
int eleCount = 0;
struct node {
int key;
char name[1024];
struct node *next;
};
struct hash {
struct node *head;
int count;
};
struct node * createNode(int key, char *name) {
struct node *newnode;
newnode = (struct node *)malloc(sizeof(struct node));
newnode->key = key;
strcpy(newnode->name, name);
newnode->next = NULL;
return newnode;
}
void insertToHash(int key, char *name) {
int hashIndex = key % eleCount;
struct node *newnode = createNode(key, name);
if (!hashTable[hashIndex].head) {
hashTable[hashIndex].head = newnode;
hashTable[hashIndex].count = 1;
return;
}
newnode->next = (hashTable[hashIndex].head);
hashTable[hashIndex].head = newnode;
hashTable[hashIndex].count++;
return;
}
void deleteFromHash(int key) {
int hashIndex = key % eleCount, flag = 0;
struct node *temp, *myNode;
myNode = hashTable[hashIndex].head;
if (!myNode) {
printf("Word not in hash Table!!\n");
return;
}
temp = myNode;
while (myNode != NULL) {
if (myNode->key == key) {
flag = 1;
if (myNode == hashTable[hashIndex].head)
hashTable[hashIndex].head = myNode->next;
else
temp->next = myNode->next;
hashTable[hashIndex].count--;
free(myNode);
break;
}
temp = myNode;
myNode = myNode->next;
}
if (flag)
printf("Word deleted from Hash Table by the power of Grey Skull\n");
else
printf("Word is not present in hash Table!\n");
return;
}
void searchInHash(int key) {
int hashIndex = key % eleCount, flag = 0;
struct node *myNode;
myNode = hashTable[hashIndex].head;
if (!myNode) {
printf("Searched word not in hash table\n");
return;
}
while (myNode != NULL) {
if (myNode->key == key) {
printf("Key : %d\n", myNode->key);
printf("Name : %s\n", myNode->name);
flag = 1;
break;
}
myNode = myNode->next;
}
if (!flag)
printf("Searched word not in hash table\n");
return;
}
void display() {
struct node *myNode;
int i;
for (i = 0; i < eleCount; i++) {
if (hashTable[i].count == 0)
continue;
myNode = hashTable[i].head;
if (!myNode)
continue;
printf("Key Word\n");
printf("----------------\n");
while (myNode != NULL) {
printf("%-12d", myNode->key);
printf("%-15s", myNode->name);
myNode = myNode->next;
}
}
return;
}
int main() {
int elecount, ch, key, i;
char name[1024],cas[5];
eleCount = 23;
hashTable = (struct hash *)calloc(elecount, sizeof (struct hash));
while (1) {
printf("\nword: Insert word\n#d: word Delete word\n");
printf("#s word: Search for word\n#p: Display hash table\n#Q: Exit\n");
printf("Enter your choice:");
fgets(name, 1023, stdin);
if(sscanf(name,"#d",&cas)==1)
{//delete
i=2;
while("name[i]"!="\n")
{key=key+i;
i++;}
deleteFromHash(key);
}
else if(sscanf(name,"#s",&cas)==1)
{//search
i=2;
while("name[i]"!="\n")
{key=key+i;
i++;}
searchInHash(key);
}
else if(sscanf(name,"#p",&cas)==1)
{//print
display();
}
else if(sscanf(name,"#Q",&cas)==1)
{//Quit
exit(0);
}
else
{//insert
while("name[i]"!="\n")
{key=key+i;
i++;}
name[strlen(name) - 1] = '\0';
insertToHash(key, name);
}
}
return 0;
}
Here is what I see as problems with the posted code:
1) the first parameter to calloc() is not initialized
2) the returned value from calloc is not checked to assure operation was successful
3) the returned value from calloc was cast and it should not be
4) the 'ch' variable is unused
5) this line: while("name[i]"!="\n") should be: while( name[i] != '\n')
6) the returned value form fgets() is not checked to assure successful operation
7) the format strings for the sscanf() statements are using '#' when they should be using '%'
8) variable eleCount not used
9) the struct definitions 'node' and 'hash' need to be before any usage of those definitions
10) the returned value from malloc should not be cast
11) the returned value from malloc is not checked to assure successful operation
12) the lines like this: 'else if(sscanf(name,"#Q",&cas)==1)' are not correct. they should be similar to:
else if(sscanf(name,"#Q",&cas)!=1)
{ // then sscanf failed
perror( "sscanf failed" );
exit( EXIT_FAILURE );
}
// implied else, sscanf successful
....
13) given the input description and the code following the calls to sscanf(), the sscan only needs to be called for a char input '%c'
then a switch statement on that char.
the cases of the switch statement would be the checks for the various commands
for those commands that need a 'name' to operate with, then there needs to be a if( 1 != sscanf( name, " %s", &cas ) )
// handle error
// implied else
// apply command to the input name
14) the array 'cas[]' only has 5 char elements
so if a parameter is greater than 4 characters then there will ve a buffer overrun, resulting in undefined behaviour and can/will lead to a seg fault event.
15) I think this line: 'key=key+i;' is not doing what the OP expects.
16) i think this line: 'insertToHash(key, name);' is not doing what the OP expects
I think I understand what the OP was trying to accomplish, but the posted code is not even close and does not even come close to compiling.
Suggest OP enable all warnings in their compiler, fix the warnings and errors,then do some reasonable debug activity, then if they still are having problems, then repost the question.
As others already said, your calloc in the main function uses the uninitialized variable elecount instead of eleCount. I recommend not using the same name for global and local variables with the only difference being the capitalization. You see why.
Also before you check the .head component you should check the variable itself.
So first check for hashTable, then you do the other check.
Otherwise you might check a components existence at NULL.