By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,949 Members | 1,086 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,949 IT Pros & Developers. It's quick & easy.

Segmentation fault in C code that I need help in identifying the issue

P: 1
Getting a segmentation fault for the following:


/*
*
* Linked lists and an editor buffer
*/

/* A doubly-linked node structure.
*/
struct node {
char data;
struct node*next;
struct node*prev;

};

/* Your buffer structure ought to include at least two things:
* (1) Some form of a linked list using your node structure;
* (2) A pointer to of the of the nodes in your list to represent the current
* insertion point.
*/

struct buffer {
struct node*insert; //pointer for the buffer where we add or delete an element
struct node*front;
struct node*back;
int size;


};

/* A structure that is used to represent the buffer contents as two strings:
* - left: the string to the left of the insertion mark;
* - right: the string to the right of the insertion mark.
*
* You may not change the definition of this structure.
*/
struct buffer_contents {
// The contents of the buffer to the left of the insert mark.
char *left;

// The contents of the buffer to the right of the insert mark.
char *right;
};

#include <stdbool.h>
#include <stdlib.h>
#include <string.h>

#include "comp211.h"
#include "hw9.h"

//ASSERT
//need to have assert at the beginning and the end of each function
//1.to check the the buffer is a valid buffer -> linear
//2. to make sure the after we do something to the buffer that it is still a valid buffer
bool buf_ok(struct buffer *buf){
if (buf->front==NULL && buf->back==NULL){
return true; //if both the front and back are null then it is linear
}
struct node *slow=buf->front;
struct node *fast=buf->front;

while (fast->next !=NULL && fast->next->next != NULL){ //checks if the spot after fast or two spots after fast is not pointing to NULL so that we dont get a seg. fault if fast tries to move after the first NULL
slow=slow->next; //increment slow to the next node
fast= fast->next->next; //increment fast to teh next node
if (slow==fast){ //if slow and fast are at same node then slow has caught up to fast and the linked list is not linear
return false; //not linear
}
}
return true; //else it is linear
}


struct buffer *empty(void) {
struct buffer *buf=malloc(sizeof(struct buffer));
//create a the buffer using dummy head nodes -> this will help in the future so we dont get errors if we try to point to "nothing"
buf->size=0;

buf->front=malloc(sizeof(struct node));
buf->front->prev=NULL; //nothing will be before the head
buf->back=malloc(sizeof(struct node));
buf->back->next=NULL; //back is the last thing in the list so nothing will follow it
//want front and back to esseintly point to eachother
buf->front->next= buf->back; //since the list only has dummy head nodes and no real content front has to point to back since there is nothing inbetween
buf->back->prev= buf->front; //the link right behind back is front..nothing inbetween because the list is empty
buf->front->data='\0'; //need to start off empty value
buf->back->data='\0'; //need an empty value
buf->insert= buf->back; //have insert point to back since we will insert the first character at the end of the list

return buf;
assert(buf_ok(buf));
}

/* insert(buf, c) inserts c to the left of the insertion point of buf. After
* the insertion, the insert mark is to the right of c.
*/
void insert(struct buffer *buf, char c) {
assert(buf_ok(buf));
struct node *new=malloc(sizeof(struct node));
new->data=c; //insert character
new->next=buf->insert; //assigning the new nodes pointer to insert since insert will be "pushed"" to the right
new->prev=buf->insert->prev; //the previous pointer of new will now point to what the previous pointer of insert use to point to
buf->insert->prev->next=new; //the node that use to point to insert will now point to the new node
buf->insert->prev=new; //inserts previous pointer will now point to new
buf->size++; //increment the size since a new node has been added
assert(buf_ok(buf));
}

/* delete_left(buf) deletes the character to the left of the insert mark. If
* there is no character to the left of the insert mark, this function has no
* effect.
*/
void delete_left(struct buffer *buf) {
assert(buf_ok(buf));
struct node *temp= buf->insert->prev; //a temporary holder for the element we are going to delete
buf->insert->prev= buf->insert->prev->prev; //we need insert to point to the node before the one we are going to delete since the element it currently points to will be gone
temp->prev->next=temp->next; //need to reassign the next pointer of the node before the node being deleted
free(temp);
buf->size--;
assert(buf_ok(buf));
}

/* delete_right(buf) deletes the character to the right of the insert mark. If
* there is no character to the right of the insert mark, this function has no
* effect.
*/
void delete_right(struct buffer *buf) {
assert(buf_ok(buf));
buf->insert= buf->insert->next; //moving the insert point to the right of the node we want to delete and then we are going to esseintly delete left.
struct node *temp= buf->insert->prev;// the node we now want to delete is to the left of insert
buf->insert->prev=buf->insert->prev->prev;//we need insert to point to the node before the one we are going to delete since the element it currently points to will be gone
temp->prev->next=temp->next; //need to reassign the next pointer of the node before the node being deleted
free(temp);
buf->size--;
assert(buf_ok(buf));
}

/* move_left(buf) moves the insert mark one character to the left. If there is
* no character to the left of the insert mark, this functdion has no effect.
*/
void move_left(struct buffer *buf) {
if (buf->insert->prev != buf->front){
buf->insert= buf->insert->prev;
}
assert(buf_ok(buf));
}

/* move_right(buf) moves the insert mark one character to the right. If there
* is no character to the right of the insert mark, this functdion has no
* effect.
*/
void move_right(struct buffer *buf) {
if(buf->insert != buf->back){
buf->insert= buf->insert->next;
}
assert(buf_ok(buf));
}

/* set(buf, n) sets the insert mark so that it is to the left of the n-th
* character. Characters are 0-indexed, so set(buf, 0) sets the insert mark to
* the beginning of the buffer. n may be equal to the length of the buffer; in
* this case, the insert mark is set to the right of the last character.
*
* Pre-condition: 0 <= n <= len(buf).
*/
void set(struct buffer *buf, int n) {
//if n is less than the first index or bigger than the last then just return since it is outof bounds so insert should just stay where it currently is
if(n<0||n > buf->size){
return;
}
//place the insert mark at the firt index
buf->insert= buf->front->next;

//if i is equal to zero or less then the nth character
for (int i=0; i<n; i++){
buf->insert=buf->insert->next; //moving insert foward
} //i is going to be starting at 0 where insert is and then go through the list until it is less than n and then we will place the insert there since the insert has to be placed to the left of the nth character
for(int i=0; i==n; i++){
n=buf->size;
buf->insert= buf->insert->next; //if n is the lenght of buf then the insert needs to be to teh right of n.
}

assert(buf_ok(buf));
}

/* contents(buf) = c, where c->left is the string to the left of the insert
* mark and c->right is the string to the right of the insert mark.
*/
struct buffer_contents *contents(struct buffer *buf) {
assert(buf_ok(buf));
/* calloc initializes memory to 0 */
//going to use variable i to count the size of the list until we reach insert mark

struct buffer_contents* cnt = calloc(buf->size, sizeof(struct buffer_contents));
struct node *temp= malloc(sizeof(struct node));
temp=buf->front->next; //starting at the beingnning of the buffer...->next because we dont want to include the dummy head node
int sizeL=0;
int sizeR=0;

while(temp != buf-> insert){
temp = temp -> next;
sizeL++;
}

while(temp != NULL){
temp=buf->insert->next;
temp = temp -> next;
sizeR++;
}



cnt->left = calloc(sizeL, sizeof(char)); //sizeL is size left of insert
cnt->right = calloc(sizeR, sizeof(char)); //sizeR is the size of the list from insert til the back

//left side up until insertion point
while (temp != buf-> insert){ //up until we reach the insert mark
temp=buf->front->next;
cnt->left=&temp->data;//put all the values to the left of insert into this new string
temp= temp->next;
}
while(temp!=buf->insert->prev && temp!=buf->back){ //right side inlcuding insertion point
temp=buf->insert;
cnt->right=&temp->data;
temp=temp->next;
}
return cnt;
assert(buf_ok(buf));
}
Nov 24 '17 #1
Share this Question
Share on Google+
1 Reply


weaknessforcats
Expert Mod 5K+
P: 9,197
I'm not sure how this works.

Usually I see a linked list handler where you pass data only and the handler does the list maintenance:

Expand|Select|Wrap|Line Numbers
  1. LinkedList thelist;
  2. LinkedList* listptr = &theList;
  3.  
  4. AddToEnd(15, listptr);
  5. AddToFront(20, listptr);
  6. InsertBefore(25, listptr);
  7. InsertAfter(30, listptr);
  8. etc...
  9.  
and you are done.

You would get your buffer by unloading the list to a buffer:

Expand|Select|Wrap|Line Numbers
  1. char* str;
  2. ConvertToString(str, listptr);
  3. etc....
  4.  
  5. free(str);
  6.  
To debug your code place a breakpoint at the beginning of each function then start execution using your debugger. When you are certain a function is correct, remove the breakpoint. When all breakpoints have been removed, the code should be working.
Nov 26 '17 #2

Post your reply

Sign in to post your reply or Sign up for a free account.