I'm doing a project for school in which I have to create a program that plays go fish. In which a deck of cards is in a doubly linked list. I read the cards from a file in the function Addcard. I have a function to print the cards and a function that is supposed to shuffle the cards. I have ot use the parameters of the struct to implement the cards. I sometimes see the error "detected source and destination buffer overlap" when I run the shuffle function, sometimes not. When the error comes up it says Thread 1: signal SIGABRT next to a string copy function. I believe it has something to do with the buffer size of some kind of allocated memory being too small, but I don't really know how to fix it. Any help would be more then appreciated. Here is an excerpt of the code I have written.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <time.h>
typedef struct card_s{
char suit[7];
int value;
struct card_s *next, *previous;
}card;
int rand_gen(int count){
double frac;
frac = (double)rand()/((double)RAND_MAX+1);
return floor(count * frac); //random number in [0, count]
}
void addCard(card *p, card **hl, card **hr, FILE *inp){
card *temp; // pointer to a node_t
temp = (card *)malloc(sizeof (card)); // new node creation
fscanf(inp, "%d", &temp->value);
fscanf(inp, "%s", temp->suit);
if (*hl == NULL){ // if left head is null, i.e., list is empty
temp->previous = NULL;
temp->next = NULL;
*hl = temp;
*hr = temp;
}
else if (p->next == NULL){ // if adding at the end of list
temp->previous = p;
temp->next = NULL;
p->next = temp;
*hr = temp;
}
else{ // if adding to the middle of the list
temp->next = p-> next;
temp->previous = p;
p->next = temp;
temp->next->previous = temp;
}
}
void Print(card **headl) { //this function prints from left to right only
card *temp;
temp = (*headl);
while(temp != NULL) {
printf("|");
printf("%d", temp->value);
if(strcmp(temp->suit,"hea")==0) {
printf("♥");
}
if(strcmp(temp->suit,"clu")==0) {
printf("♣");
}
if(strcmp(temp->suit,"spa")==0) {
printf("♠");
}
if(strcmp(temp->suit,"dia")==0) {
printf("♦");
}
printf("|");
//printf("%s ", temp->suit);
temp = temp->next;
}
}
void Print1(card **headl) { //this function prints from left to right only
card *temp;
temp = (*headl);
while(temp != NULL) {
for(int i = 0; i < 13; i++) {
printf("|");
if(temp->value == 11){
printf("J");
}
else if(temp->value == 12) {
printf("Q");
}
else if(temp->value == 13) {
printf("K");
}
else if(temp->value == 14) {
printf("A");
}
else {
printf("%d", temp->value);
}
if(strcmp(temp->suit,"h")==0) {
printf("♥");
}
if(strcmp(temp->suit,"c")==0) {
printf("♣");
}
if(strcmp(temp->suit,"s")==0) {
printf("♠");
}
if(strcmp(temp->suit,"d")==0) {
printf("♦");
}
printf("|");
//printf("%s ", temp->suit);
temp = temp->next;
}
printf("\n");
}
}
void swap(card *pt, int i, int j) {
card *temp;
temp = (card *)malloc(sizeof(card));
card *temp1 = pt, *temp2 = pt; //creates temperaries that start from the head left
for(int x = 0; x < i; x++) { //counts the number of nodes until i
temp1 = temp1->next;
}
for(int x = 0; x < j; x++) { //counts the number of nodes until j
temp2 = temp2->next;
}
temp->value = temp1->value; //swaps the information not the nodes
strcpy(temp->suit,temp1->suit);
temp1->value = temp2->value;
strcpy(temp1->suit, temp2->suit);
temp2->value = temp->value;
strcpy(temp2->suit, temp->suit);
}
int main(void) {
FILE *inp = NULL;
inp = fopen("cards.txt", "r");
srand((int)time(NULL));
card *headl = NULL, *headr = NULL;
for(int i = 0; i < 52; i++) {
addCard(headr, &headl, &headr, inp);
}
if(inp == NULL) {
printf("No file found");
return -1;
}
printIntro();
printf("\n");
Print1(&headl);
printf("\n");
printf("\n");
for(int i = 0; i <= 45; i++) { //does the swap function swap number times
swap(headl, rand_gen(52), rand_gen(52));
}
Print1(&headl);
return(0);
}
You have an error message saying "detected source and destination buffer overlap", near a string copy function, which copies data from a source to a destination...
Are there any instances of strcpy where the source and dest might point to the same memory?
I see these two lines:
card *temp1 = pt, *temp2 = pt; //creates temperaries that start from the head left
//advance `temp1` `i` times, and `temp2` `j` times
...
strcpy(temp1->suit, temp2->suit);
What happens when i and j are the same value?
Related
This is written in C.
I'm trying to take user input and use it to create/add to a linked list, which I point to with struct Node *dict; Everything is accomplished using global memory.
Creating a new linked list works fine, but when the user tries to add to the linked list, it overwrites the extant linked list.
Here's my code for adding to the list (words is an array of nodes to be appended to the list):
if (dict == NULL) { // If previous list does not exist, global dict pointer should point to node array
dict = words;
} else { // Else find end of current linked list and point it to the new list
struct Node *head = dict;
while (head->next != NULL) {
head = head->next;
}
head->next = words;
}
When I create a list with the words "apple orange peach," for example, when I print the list, I get the output "apple orange peach." But then when I add "pear" to the list, "apple orange peach" is overwritten and I only see the output "pear," instead of "apple orange peach pear."
EDIT:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
//// GUI Stuff ////
void drawDashedLine() {
for (int i = 0; i < 30; i++) {
printf("-");
}
printf("\n");
}
void drawDottedLine() {
for (int i = 0; i < 30; i++) {
printf(".");
}
printf("\n");
}
void drawArrowLine() {
for (int i = 0; i < 30; i++) {
printf(">");
}
printf("\n");
}
void drawStarLine() {
for (int i = 0; i < 30; i++) {
printf("*");
}
printf("\n");
}
struct Node {
int length;
char word[5];
struct Node * next;
};
// Pointer to global linked list dictionary
struct Node *dict;
struct Node *newDict;
void printDict() {
drawDottedLine();
struct Node * head = dict;
while (head != NULL) {
printf("%s\n", head -> word);
head = head -> next;
}
drawDottedLine();
return;
}
void alphabetizeDict() { // Bubble sort
//printf("%p --- %p\n", dict, dict->next);
struct Node * head = dict;
if (head == NULL) {
return;
}
struct Node * ptr2 = NULL;
int swapped = 1;
while (swapped) {
swapped = 0;
head = dict;
while (head -> next != ptr2) {
char * temp1 = strdup(head -> word);
char * temp2 = strdup(head -> next -> word);
strupr(temp1);
strupr(temp2);
if (strcmp(temp1, temp2) > 0) {
char temp[5];
strcpy(temp, head -> word);
strcpy(head -> word, head -> next -> word);
strcpy(head -> next -> word, temp);
swapped = 1;
}
head = head -> next;
}
ptr2 = head;
}
return;
}
void createDict() {
// To hold the string entered by the user
char str[5000];
// Holds 1000 words, each up to 5 characters long (4 plus a NULL char)
char newString[1000][5];
printf("\n");
drawArrowLine();
printf("Enter word(s): \n");
fgets(str, sizeof str, stdin);
int i, j, ctr;
j = 0;
ctr = 0; // ctr to iterate through words, j to iterate through letters
for (i = 0; i <= (strlen(str)); i++) {
if (str[i] == ' ' || str[i] == '\0') { // This is whitespace. add null character to terminate string. Start next word
newString[ctr][j] = '\0';
ctr++;
j = 0;
} else { // Else add letter to string
newString[ctr][j] = str[i];
j++;
}
}
for (int i = 0; i < ctr; i++) {
struct Node n;
n.length = strlen(newString[i]);
int c = 0;
char sub[5];
// Only use word's first four letters
while (c < strlen(newString[i]) && c < 4) {
sub[c] = newString[i][c];
c++;
}
sub[c] = '\0';
strcpy(n.word, sub);
n.next = NULL;
if (dict == NULL) {
dict = &n;
} else {
n.next = dict;
dict = &n;
}
}
// alphabetizeDict();
printf("Word(s) added succesfully\n");
drawArrowLine();
printf("\n");
return;
}
void destroyDict() {
printf("Starting new dictionary......\n");
while (dict != NULL) {
struct Node * temp = dict;
dict = dict -> next;
temp -> next = NULL;
}
}
void caseInsensSearch(char * searchTerm) {
for (int i = 0; searchTerm[i]; i++) {
searchTerm[i] = tolower(searchTerm[i]);
}
struct Node * head = dict;
int index = 0;
while (head != NULL) {
char lowercaseWord[5];
for (int i = 0; head -> word[i]; i++) {
lowercaseWord[i] = tolower(head -> word[i]);
}
if (strcmp(lowercaseWord, searchTerm) == 0) {
printf("Found %s at index %i\n", head -> word, index);
drawDashedLine();
return;
}
head = head -> next;
index++;
}
printf("Sorry, I couldn't find %s in your dictionary.\n", searchTerm);
drawDashedLine();
return;
}
void caseSensSearch(char * searchTerm) {
struct Node * head = dict;
int index = 0;
while (head != NULL) {
if (strcmp(head -> word, searchTerm) == 0) {
printf("Found %s at index %i\n", head -> word, index);
drawDashedLine();
return;
}
head = head -> next;
index++;
}
printf("Sorry, I couldn't find %s in your dictionary.\n", searchTerm);
drawDashedLine();
return;
}
void search() {
int isSens;
drawDashedLine();
printf("Enter 1 for Case sensitive\n2 for case insensitive\n");
drawDashedLine();
scanf("%d", & isSens);
while (isSens < 1 || isSens > 2) {
printf("Please enter a number between 1 and 2:\n");
scanf("%d", & isSens);
}
drawDashedLine();
printf("Enter a word to search for:\n");
char searchTerm[5];
scanf("%s", searchTerm);
searchTerm[4] = '\0';
if (isSens == 1) {
caseSensSearch(searchTerm);
} else {
caseInsensSearch(searchTerm);
}
}
int promptUser() {
drawStarLine();
printf("1) Search for a word\n2) Add word(s)\n3) Print dictionary\n4) Start new dictionary\n5) Exit\n");
drawStarLine();
printf("\nEnter a number between 1 and 5:\n");
int choice;
scanf("%1d", & choice);
while (choice < 1 || choice > 5) {
printf("Please enter a number between 1 and 5:\n");
scanf("%d", & choice);
}
return choice;
}
int main() {
for (;;) {
int choice = promptUser();
fflush(stdin);
if (choice == 1) {
search();
} else if (choice == 2) {
createDict();
} else if (choice == 3) {
printDict();
} else if (choice == 4) {
destroyDict();
} else if (choice == 5) {
return 0;
}
}
return 1;
}
I've spent some time diagnosing this problem for you. The problem statement is bizarre... An array of words could be sorted (even with library qsort()) and grow to the fill the array to the brim, but you claim this must use both a linked list and a global "object pool" that is not dynamically allocated...
Here's some code I've compiled BUT NOT TESTED...
It should be simple to follow and expand to accommodate your requirements.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node { // use 'typdef'. Less typing
char word[5]; // VERY SHORT WORDS guaranteed
struct Node *next;
} Node_t;
Node_t dict[ 1000 ]; // global data space
int nextNode = 0;
void printDict() { // traverse LL outputting value(s)
for( Node_t *pn = dict; pn; pn = pn->next )
puts( pn->word );
}
void addNode( char *data ) {
if( nextNode + 1 >= sizeof dict/sizeof dict[0] )
return; // Fixed size cannot grow.
Node_t *pn = &dict[ nextNode ];
strcpy( pn->word, data ); // "apple" WON'T fit
nextNode++;
//EDIT:
// This is not correct.
// See code block below for correction
if( nextNode +1 >= sizeof dict/sizeof dict[0] )
pn->next = NULL;
else
pn->next = &dict[ nextNode ];
}
void createDict() {
char str[5000]; // one lo-o-o-ong input string of short words
printf( "Enter word(s): \n" );
fgets( str, sizeof str, stdin );
// chop words on spaces (or tabs) and store to LL
for( char *cp = str; ( cp = strtok( cp, " \t" ) ) != NULL; cp = NULL )
addNode( cp );
}
void destroyDict() { // super simple!
memset( dict, 0, sizeof dict );
nextNode = 0;
// return; // Do not need those return(s) before final closing brace.
}
80% of any problem is the clear understanding of what the problem is to begin with.
EDIT: Realising the code must 'straddle' both array and LL, the above was not exactly correct. Below is the necessary fix to conform with a LL having a NULL next pointer at its 'tail' node.
void addNode( char *data ) {
if( nextNode + 1 >= sizeof dict/sizeof dict[0] )
return; // Fixed size cannot grow.
strcpy( dict[ nextNode ].word, data ); // "apple" WON'T fit
if( nextNode ) // at node 1 or greater
dict[ nextNode - 1 ].next = &dict[ nextNode ];
nextNode++;
}
try this
if (dict == NULL) { // If previous list does not exist, global dict pointer should point to node array
dict = words;
} else { // Else find end of current linked list and point it to the new list
struct Node *head = dict;
while (head->next != NULL) {
head = head->next;
}
struct Node *ptr = NULL;
ptr->length = strlen(word);
strcpy(ptr->word, sub);
ptr->next = NULL;
head->next = ptr;
}
currently working on a program to create a poker game. Right now I'm trying to get the deck of cards to print. It's not printing anything, and instead of exiting with code zero when I run it, it exits with code -104356 or something like that. I'm using two functions, one to make the cards, and the other to print them, and I'm not sure where the problem is.
my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct card_s {
char suit;
int face;
struct card_s* next;
} card;
card* createCard(int n);
void printCard(card* head);
int main(void) {
card* first = NULL;
first = createCard(52);
printCard(first);
free(first);
return(0);
}
card * createCard(int n) {
int i = 0;
card* head = NULL;
card* tmp = NULL;
card* p = NULL;
for (i = 0; i < n; i++) {
tmp = (card*)malloc(sizeof(card));
tmp->face = rand() % (10 + 1 - 1) + 1; //this is supposed to generate a random number between 1 and 10
tmp->suit = "CDHS"[rand() % 4]; //this is supposed to generate a random letter C, D, H, or S
tmp->next = NULL;
if (head == NULL) {
head = tmp;
}
else {
p = head;
while (p != NULL) {
p = p->next;
}
p->next = tmp;
}
}
return(head);
}
void printCard(card * head) {
card* p = head;
while (p->next != NULL) {
printf("%d%s\n", p->face, p->suit);
p = p->next;
}
return;
}
In this code snippet
else {
p = head;
while (p != NULL) {
p = p->next;
}
p->next = tmp;
}
after the while loop the pointer p is equal to NULL. So the next statement
p->next = tmp;
invokes undefined behavior.
You need at least to rewrite the loop like
while (p->next != NULL) {
p = p->next;
}
But in any case such an approach is inefficient. It is better to write
if (head == NULL) {
head = tmp;
p = head;
}
else {
p->next = tmp;
p = p->next;
}
Also within the function printCard the last element of the list is not outputted due to the condition in the while loop
while (p->next != NULL) {
Also you may not use the conversion specifier %s with an object of the type char as you are doing
printf("%d%s\n", p->face, p->suit);
The function can be written like
void printCard( const card *head )
{
for ( ; head != NULL; head = head->next )
{
printf("%d%cn", head->face, head->suit);
}
}
Others have already pointed out the potential issues with your implementation of the linked list, so I will chip in with a somewhat different point.
You might want to store your deck of cards in a linked list--I don't know your implementation, so whether that is a good idea or not, I cannot say, but it can certainly make sense--but this doesn't mean that you have to allocate each card separately or initialise them one by one. You can create a deck of cards as an array and still chain them up with pointers.
If you do that, you can allocate and free them as a whole, and you avoid the irritating special case when you wish to prepend/append to an empty list. You can have all your cards at once, and then chain them up.
Such an approach might also make it easier to shuffle the cards. With an array, you can easily create a random permutation, and then chain the cards up based on that. Permuting a linked list can be a little harder.
As I said, I don't know the application, so I have no idea if this good or bad advice, but I have put some example code below.
#include <stdio.h>
#include <stdlib.h>
#define DECK_SIZE 52
struct card
{
char suit;
char const *face;
struct card *next;
};
struct card *alloc_deck(void)
{
static char const *suite = "CDHS";
static char const *face[] = {
"A", "2", "3", "4", "5", "6",
"7", "8", "9", "10", "J", "Q", "K",
NULL};
struct card *deck = malloc(DECK_SIZE * sizeof *deck);
struct card *card = deck;
for (char const *s = suite; *s; s++)
{
for (char const **f = face; *f; f++)
{
*card = (struct card){
.suit = *s,
.face = *f,
.next = card + 1 // point to next card
};
card++;
}
}
// last card should point to zero
(card - 1)->next = NULL;
return deck;
}
void print_card_list(struct card *deck)
{
for (struct card *card = deck; card; card = card->next)
{
printf("%s%c\n", card->face, card->suit);
}
}
void print_deck_array(struct card *deck)
{
for (int i = 0; i < DECK_SIZE; i++)
{
printf("%s%c\n", deck[i].face, deck[i].suit);
}
}
struct card *shuffle(struct card *deck)
{
static int perm_init;
static int perm[DECK_SIZE];
if (!perm_init)
{
perm_init = 1;
for (int i = 0; i < DECK_SIZE; i++)
{
perm[i] = i;
}
}
// permute indices
for (int i = DECK_SIZE - 1; i >= 0; --i)
{
int j = rand() % (i + 1);
int temp = perm[i];
perm[i] = perm[j];
perm[j] = temp;
}
// chain up the cards
for (int i = 0; i < DECK_SIZE - 1; i++)
{
deck[perm[i]].next = &deck[perm[i + 1]];
}
deck[perm[DECK_SIZE - 1]].next = NULL; // terminate chain
return &deck[perm[0]]; // return first in chain
}
int main(void)
{
struct card *deck = alloc_deck();
printf("Allocated list:\n");
print_card_list(deck);
printf("\n");
printf("Allocated array:\n");
print_deck_array(deck);
printf("\n");
struct card *card = shuffle(deck);
printf("Shuffled deck:\n");
print_card_list(card);
printf("\n");
card = shuffle(deck);
printf("Second shuffled deck:\n");
print_card_list(card);
printf("\n");
free(deck); // free deck as a whole
return 0;
}
I'm working on a program that takes an input of numbers from stdin and computes the median of the sequence and prints it out as a float. I'm currently getting an infinite loop in the function
len(struct node *)
at the for loop and I'm not sure why.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
float *val;
struct node *next;
};
int len(struct node *list) {
int i = 0;
struct node *temp = list;
for (i = 0; temp != NULL; i++) {
temp = temp->next;
}
return i;
}
float median(int size, struct node list) {
struct node temp = list;
int i = 0;
if (size == 1) {
return *temp.val;
} else
if (size == 2) {
return (*(temp.val) + *(temp.next->val)) / 2;
} else {
if (size / 2 == 1) {
for (i = 3; i != (size / 2) - 1; i++) {
temp = *(temp.next);
}
return *temp.val;
} else {
for (i = 3; i != (size / 2); i++) {
temp = *(temp.next);
}
return (*(temp.val) + *(temp.next->val)) / 2;
}
}
}
int main() {
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while ((err = scanf("%f", &temp)) != EOF) {
if (err < 1) {
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = &temp;
tmpnode->next = list;
list = tmpnode;
}
size = len(list);
if (size == 0) {
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
return 0;
}
Edit: I've fixed the infinite loop, but now I'm getting a segfault at temp = *(temp.next) in median(). Do I need to allocate for temp?
You created only one node and assigned next of the node to itself, so this is cause of the infinite loop.
Create new nodes and link them in the input loop.
Assigning address of temp to all nodes is also not good.
Your main() function should be like this:
int main(void){
struct node *tmpnode;
tmpnode = malloc(sizeof(struct node));
if(tmpnode == NULL){
perror("malloc 1");
return 1;
}
tmpnode->next = NULL;
struct node *list = NULL;
list = tmpnode;
float temp = 0;
int err = 0;
int size = 0;
while((err = scanf("%f", &temp)) != EOF){
if(err < 1){
fprintf(stderr, "Error: non-integer character inputted\n");
return 1;
}
tmpnode->val = malloc(sizeof(float));
if(tmpnode->val == NULL){
perror("malloc 2");
return 1;
}
*tmpnode->val = temp;
tmpnode->next = malloc(sizeof(struct node));
if(tmpnode->next == NULL){
perror("malloc 3");
return 1;
}
tmpnode = tmpnode->next;
tmpnode->val = NULL;
tmpnode->next = NULL;
}
size = len(list);
if(size == 0){
fprintf(stderr, "Error: no inputs found");
return 1;
}
printf("%f\n", median(size, *list));
/* code to free the list should be here */
return 0;
}
(I gave input 1 2 3 4 5 and this program's output was 1.500000, which might be wrong)
If you're looking for the median you would have to arrange the nodes in order and get the number that is in the middle.If the number of nods is even and there is no middle you should add the two middlemost numbers and divide them by two.
Is the sequence in order? If not you're miscalculating the median.
Supposing the sequence is in order.
I didn't really understand the usefulness of this statement
if(size/2 == 1)
Maybe you're trying to see if the size is odd. In that case you should do:
> if(size%2 == 1)
Why the list is probably looping might be due to this
for(i = 3; i != (size/2); i++){
temp = *(temp.next);
}
Suppose you pass a 5 to the function size/2=2 (decimal part is lost), so it'll keep on going until an overflow occurs and it actually reaches 2, making your program most probably seg_fault in the process.
Start from i=0, because even though you started from 3 your current node is not the third one but the FIRST ONE.
Good luck hope this helps!!!!
This is my push function
void push(struct Map *map, struct Location location){
struct Node *temp = map->front;
temp->loc = location; //this line causes the error
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
free(temp);
}
and I am getting this error
==2301== Invalid write of size 8
==2301== at 0x401148: push (3146.c:239)
==2301== by 0x400DE7: findEntrance (3146.c:164)
==2301== by 0x400820: main (3146.c:55)
==2301== Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2301==
I am doing a breadth first search on a grid of characters arranged to be a maze. I have been having trouble getting no memory leaks so I have finally found that using malloc helps, but I don't understand why I cannot do this data assignment without a segfault
The alternative is to not free it and have memory leaks, which I don't think is an acceptable solution. Where is my logic wrong?
Below this is the whole program
#include <stdio.h>
#include <stdlib.h>
struct Location;
struct Map;
struct Node;
//function names seem to self describe
void pathFinder(struct Map*);
void findEntrance(struct Map*);
void readInMap(struct Map*);
void printMap(struct Map*);//to screen
/* Q funcs */
void pop(struct Map*);
void push(struct Map*, struct Location);
struct Location {// simple location type
int x;
int y;
};
struct Node {//standard linked list node
struct Location loc;
struct Node *next;
};
struct Map { //variable size encompassing array, and dimension variables
char arr[100][100];
int xLength;//dimensions
int yLength;
int complete;
struct Node *rear;//Q pointers
struct Node *front;
struct Node *currLoc; //temp for BFS
struct Location entrance;
};
int main(){
struct Map map;//the one map to rule them all
map.xLength = 0;//map dimensions
map.yLength = 0;
map.front = NULL; // queue pointers init
map.rear = NULL;
map.currLoc = NULL;
map.entrance.x = 0;
map.entrance.y = 0;
map.complete = 0;
readInMap(&map);
findEntrance(&map);//start off by finding where to start
pathFinder(&map); // problem solver method
printMap(&map);
free(map.front);
free(map.rear);
free(map.currLoc);
return 0;
}
void pathFinder(struct Map *map){
int x;//should be the entrance already pushed from findEntrance
int y;
int done = 0;
struct Location temp;
temp.x = 0;// temp for pushing locations that are adjacent 0's
temp.y = 0;
while(map->front != NULL){
map->currLoc = map->front;//currLoc is just a copy so that we can pop the map location of currLoc from Q
pop(map);// pop so it cant be used twice in this loop
x = map->currLoc->loc.x;
y = map->currLoc->loc.y;
temp.x = 0;
temp.y = 0;
if(map->arr[y][x] == '0'){//protection of 1 values from replacement
map->arr[y][x] = 'X';//replace the array position loc w x
}
if(map->arr[y][x] == '0'){//protection of 1 values from replacement
map->arr[y][x] = 'X';//replace the array position loc w x
printf("test\n");
}
/* find adjacent 0's */
if((y < map->xLength)&&(map->arr[y+1][x] == '0')){
temp.x = x;
temp.y = y+1;
push(map, temp);
}
if((x < map->xLength)&&(map->arr[y][x+1] == '0')){
temp.x = x+1;
temp.y = y;
push(map, temp);
}
if((y > 0)&&(map->arr[y-1][x] == '0')){
temp.x = x;
temp.y = y-1;
push(map, temp);
}
if((x > 0)&&(map->arr[y][x-1] == '0')){
temp.x = x-1;
temp.y = y;
push(map, temp);
}
if((x == 0)||(x == map->xLength)||(y == 0)||(y == map->yLength)){ //then its not on the edge
if((x != map->entrance.x)&&(y != map->entrance.y)){
map->front = NULL;
map->complete++;
}
}
}
}
void findEntrance(struct Map *map){
struct Location entrance;
int done = 0;
int y=0;//index of current row depth
int x=0;//index of current column depth
if (done == 0){
for (x=0;x<=map->xLength;x++){ // top row
if (map->arr[y][x] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(y=0;y<=map->yLength;y++){//down the right side
if (map->arr[y][map->xLength] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(x;x>=0;x--){//bottom row RtoL
if (map->arr[map->yLength][x] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
if (done == 0){
for(y;y>=0;y--){//up the left side
if (map->arr[y][0] == '0') {
entrance.x = x;
entrance.y = y;
done = 1;
}
}
}
map->entrance = entrance;
push(map, map->entrance);
}
void readInMap(struct Map *map){
FILE *fptr;
char c;
char file_name[20];
int i,j;
int rows;
int cols;
int x,y;
printf("Size\n");
printf("Rows:");
scanf("%i", &rows);
printf("Columns:");
scanf("%i", &cols);
map->xLength = cols-1; //[y][xLength]
map->yLength = rows-1; //[yLength][x]
for (x=0;x<100;x++){
for (y=0;y<100;y++){
map->arr[x][y] = '1';//whole array is 1
}
}
printf("Type in the name of the file containing the Field\n");
scanf("%s",file_name);
fptr=fopen(file_name, "r");
for (i = 0; i <= map->xLength; i++){
for (j = 0; j <= map->yLength; j++){
c=fgetc(fptr); //handles new line character and spaces
while ( !((c == '1') || (c =='0')) ) {
c=fgetc(fptr);
}
map->arr[i][j] = c;
}
}
printf("\n");
fclose(fptr);
}
void printMap(struct Map *map){
int y;//index of current row depth
int x;//index of current column depth
for (x=0;x<=map->xLength;x++){
for (y=0;y<=map->yLength;y++){//current pos (x,y)
printf("%c", map->arr[x][y]);
}
printf("\n");
}
if(map->complete != 0){
printf("\n An exit to the maze was found that is not the entrance\n");
}else{
printf("\n No exit was found \n");
}
}
void pop(struct Map *map){
if (map->front != NULL){//if not empty
if (map->front == map->rear){
map->rear = NULL;//if the line length is 1, empty it
map->front = NULL;
}else{
map->front = map->front->next;//next in line
}
}else{
map->rear = NULL;//empty out the queue
map->front = NULL;
}
}
void push(struct Map *map, struct Location location){
struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
temp->loc = location;
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
free(temp);
}
When the Map is empty, both front and rear are NULL. So temp->loc is dereferencing a NULL pointer.
You need to malloc the new node and add that to the list. Additionally, you don't want to free here, as that deallocates the memory that you just added to the list.
void push(struct Map *map, struct Location location){
struct Node *temp = malloc(sizeof(struct Node));
temp->loc = location;
temp->next = NULL;
if(map->rear == NULL) { // if queue empty
map->front = temp; // First NODE
map->rear = map->front;
}else{// if there is stuff in the queue
map->rear->next = temp;
map->rear = temp;
// Insert End
}
}
In pop is where you want to deallocate the memory:
void pop(struct Map *map){
struct Node *temp = map->front;
if (map->front != NULL){//if not empty
if (map->front == map->rear){
map->rear = NULL;//if the line length is 1, empty it
map->front = NULL;
}else{
map->front = map->front->next;//next in line
}
free(temp);
}else{
map->rear = NULL;//empty out the queue
map->front = NULL;
}
}
I'm writing a programme that needs to transverse threw 64 linked lists. (each node having one integer variable named val) it needs to compare each node and if the val is equal to another val in any other node of any list it must record it.
i've written a function that transverse threw the lists but after it prints the results that they equal it crashes, my function looks like this (n = 64):
void scanlist(int n)
{
int i = 0;
int j = 0;
for(i=0; i < n; i++)
{
struct node *temp; //Declare temp
temp = heads[i]; //Assign Starting Address to temp
int x = i++;
struct node *temp2; //Declare temp2
temp2 = heads[x]; //Assign Starting Address to temp2
while(temp != NULL)
{
if(temp->val == temp2->val)
{
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2 = temp2->next;
continue;
}
else if(temp->val != temp2->val)
{
temp2 = temp2->next;
continue;
}
else if(temp2 == NULL)
{
temp = temp->next;
temp2 = heads[x];
continue;
}
}
}
}
my linked list code looks like this:
struct node
{
int val;
struct node *next;
} ;
struct node* heads[64]; // array with the roots of the lists
struct node* currs[64]; // array holding pointers to current positions in list
struct node* create_list(int val, int listNo){
struct node *ptr = (struct node*)malloc(sizeof(struct node));
ptr->val = val;
ptr->next = NULL;
heads[listNo] = currs[listNo] = ptr;
return ptr;
}
void setup_list_array(int n){
int i;
for(i=0; i<n; i++)
{
heads[i] = NULL;
currs[i] = heads[i];
}
}
thanks for any help in advance, hope i was clear.
First, a few small comments on the 'Question' code:
void scanlist(int n)
{
int i = 0;
int j = 0;
It appears that 'j' is unused.
for(i=0; i < n; i++)
Perhaps it would be more efficent to this to
for(i=0; i < (n-1); i++)
This will avoid referencing the last 'heads[]', due to it being already compared.
{
struct node *temp; //Declare temp
temp = heads[i]; //Assign Starting Address to temp
int x = i++;
Perhaps 'i' is incremented in order to initialize 'x' to 'i + 1'; however, this statement is equivelant to 'x=i; i=i+1;', which does not appear to me helpful.
struct node *temp2; //Declare temp2
temp2 = heads[x]; //Assign Starting Address to temp2
Due to the previously stated mis-initialization of 'x', 'temp' and 'temp2' now point to the same 'head[]' element.
while(temp != NULL)
{
if(temp->val == temp2->val)
{
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2 = temp2->next;
continue;
}
else if(temp->val != temp2->val)
The 'else' statement can be omitted here. if '(temp->val == temp2->val)' [above] evaluates to 'TRUE', the 'continue' statement will cause program flow back to the top of the loop.
In addition, the statement 'if(temp->val != temp2->val)' can be omitted due to it will always evaluate to 'TRUE'
{
temp2 = temp2->next;
continue;
}
else if(temp2 == NULL)
Due to this 'else' statement, if either of the above 'if' statements evaluate to 'TRUE', this code will not be executed. This appears to be a flaw.
{
temp = temp->next;
temp2 = heads[x];
continue;
}
}
}
}
Below, another way to implement this method (included comments describe what is going on).
void scanlist(
int n
)
{
int i;
/* Iterate the list heads. */
for(i=0; i < (n-1); ++i)
{
struct node *temp = heads[i]; // Declare temp and assign Starting Address
/* Iterate primary list nodes. */
while(temp)
{
int j;
/* Iterate list heads to compare */
for(j=i+1; j < n; ++j)
{
struct node *temp2 = heads[j]; //Declare temp2 and assign Starting Address
/* Iterate list nodes to compare */
while(temp2)
{
if(temp->val == temp2->val)
printf("theyre on the same line, %d = %d \n", temp->val, temp2->val);
temp2=temp2->next;
}
}
}
temp=temp->next;
}
return;
}