I'm trying to fill a char *info inside a struct nodo;
This is struct :
struct nodo {
char *info;
struct nodo *prec;
struct nodo *succ;
};
typedef struct nodo nodo;
And this is whole function :
nodo *q,*t = NULL,*head = NULL;
int i, nodi=0 ;
char *c = a, *k = a;
while ( *c != '\0') {
if (*c == ' ')
nodi++;
c++;
}
for (i = 0; nodi != 0; i++) {
if (i == 0){
head = CreateFirstNodo();
t = head;}
if (i == 1)
q = CreateSecondNodo(head);
else
q = CreateNNodo(head);
nodi--;
}
char *k = a;
int i = 0;
while ( *k != '\0' )
{
if (*k == ' ' )
{
head = head->succ;
i = 0;
}
head->info[i] = *k; // ERROR EXC BAD ACCESS
i++;
k++;
}
return t;
}
k is a char* and should scroll the char[] to which is assigned and should copy any of his values to the proper place in head->info[i] which is char *info in struct
if k hits a space, the nodo goes to the next nodo and the 'i' become 0 again since i need a word filled in each nodo.
BUT this code shows error EXC BAD ACCESS in the marked line.
Here are the 3 CreateNodo functions:
nodo *CreateFirstNodo() {
nodo *q;
q = malloc(sizeof(nodo));
q->prec = NULL;
q->succ = NULL;
return q;
}
nodo *CreateSecondNodo(nodo *head) {
nodo *q;
q = malloc(sizeof(nodo));
q->succ = NULL;
q->prec = head;
head->succ = q;
return q;
}
nodo *CreateNNodo(nodo *head) {
nodo *q;
while (head->succ != NULL) {
head = head ->succ;
}
q = malloc(sizeof(nodo));
q->succ = NULL;
q->prec = head;
head->succ = q;
return q;
EDIT: sorry for lacking code.
You're attempting to dereference an uninitialized pointer, probably (an initialization is not shown).
When you access info[i] what it does is add info + i and use that as an address to find a char. If info has an invalid value (such as NULL), then you get the error you see.
You probably need to initialize info with something like info = malloc(size_i_want), but it's hard to see what you're trying to achieve here.
The reason you get EXC BAD ACCESS is because you never actually allocate memory for info. In your struct nodo you have info defined to be a pointer to a character, but you never have any memory allocated for it.
Depending on how big your input could be you could either do char info[256] (or whatever size you want) or you could calloc the amount of space you want in Createxxxx functions.
Additionally, you really only need one Create function. I would do something like this:
nodo *CreateNodo(nodo *head)
{
nodo *q;
q = calloc(1, sizeof(nodo));
if (q) {
//assume info should be 256 chars
q->info = calloc(256, sizeof(char));
if (!q->info) {
free(q);
return NULL;
}
q->succ = NULL;
q->prec = NULL;
if (head) {
while (head->succ != NULL) {
head = head->succ;
}
q->prec = head;
head->succ = q;
}
return (q);
}
That way you only have 1 function to debug/fix.
Related
i'm having trouble with a farelly simple function, i have to create a linked list with each node storing a character from a string, i made a function for that, however it doesn't seem to do anything at all
this is the function i'm talking about (variable names are in spanish, i'm sorry for that):
struct listaDoble crearMiADN()
{
char miDni[] = "1234";
struct listaDoble listado = crearLista(strlen(miDni));
struct nodo *actual = listado.first;
for(int i = 0; i<strlen(miDni); i++)
{
if(miDni[i] != '\0' && miDni[i] != EOF)
{
actual->tuNombre[0] = miDni[i];
actual->tuNombre[1] = '\0';
actual = actual->next;
}
}
return listado;
}
and this is the function crearLista which works but you will probably need it to understand my code:
struct listaDoble crearLista(int num_nodos)
{
struct listaDoble *result = (struct listaDoble *)malloc(sizeof(struct listaDoble));
if(num_nodos > 0)
{
result->first = (struct nodo *)malloc(sizeof(struct nodo));
result->first->prev = NULL;
struct nodo *actual = result->first;
struct nodo *prev = NULL;
struct nodo *last;
for(int i = 0; i < num_nodos; i++)
{
if(i + 1 != num_nodos)
{
actual->next = (struct nodo*)(malloc)(sizeof(struct nodo));
actual->prev = prev;
actual = actual->next;
prev = actual;
}
else
{
actual->next = NULL;
actual->prev = prev;
last = actual;
}
}
result->last = last;
result->size = num_nodos;
}
else
{
result->first = NULL;
result->last = NULL;
result->size = 0;
}
return *result;
}
Requested in the comments
struct listaDoble
{
struct nodo *first, *last;
int size;
};
now this is how i call the crearMiADN thing
struct listaDoble dni = crearMiADN();
now the expected result would be something like this
NULL<-- [1] <-> [2] <-> [3] <-> [4] --> NULL
however this is what i'm getting
NULL<-- [] <-> [] <-> [] <-> [] --> NULL
i'm not very keen with pointer, my attempt to fixing it was literally trying to put a * somewhere and see if it works (spoiler alert, it doesn't)
so something like this
struct listaDoble dni = *crearMiADN(); //type mismatch
then i tried to fix the type mismatch my doing this
struct listaDoble crearMiADN()
//...//
return *listado;
}
which once again errors out, and now i'm pretty much stuck trying to put a * somewhere random and checking if it compiles and works
You are trying to return local variable. You should allocate that memory block and return pointers. Try again by correcting the code as follows.
struct listaDoble* crearMiADN()
{
char miDni[] = "1234";
struct listaDoble *listado = crearLista(strlen(miDni));
...
return listado;
}
struct listaDoble* crearLista(int num_nodos)
{
struct listaDoble *result = (struct listaDoble *)malloc(sizeof(struct listaDoble));
...
return result;
}
It seems to work,but I want to know if a particular situation would make my algorithm crash.Does anyone have any ideas of hidden particular cases,that my program would not cover?
I know it's not the proper way to sort a list,but this is what I had to do.
struct Student {
float medie;
char nrMatricol[10];
char *nume;
char facltate[6];
};
struct Nod{
Student stud;
Nod* next;
};
Nod* inserareNodEnd(Nod *l,Student st)
{
Nod *nou = (Nod*)malloc(sizeof(Nod));
nou->next = NULL;//NOU->NEXT=0
nou->stud = st;
if (!l) {
//lista este goala
return nou;
}
else
{
//lista contine un nod
Nod *t = l;
while (t->next) {
t = t->next;
}
t->next = nou;
return l;
}
}
Nod * interschimbare(Nod *l, Nod *pred) {
Nod *aux=l;
//Nod *auxPred = pred;
//Nod *auxPredNext =pred->next;
if (pred) {
//caz general
Nod *p, *q, *r;
pred = pred->next;
q = p->next;
r = q->next;
pred->next = q;
p->next = r;
q->next = p;
}
else {
//interschimb noduri 1 cu 2
Nod *p, *q;
p = l->next;
q = p->next;
l->next = q;
l = p;
}
return l;
}
Nod* sortareBubble(Nod* l) {
char dinNou; // flag interschimb noduri
if (!l && !l->next)
return l; //lista trebuie sa contina cel putin 2 noduri
do {
dinNou = 0; // 0 -> ipoteza fara interschimb
Nod *tmp = l, *pred = 0;
while (tmp->next) {
if (tmp->stud.medie > tmp->next->stud.medie) {
l = interschimb(l, pred);
dinNou = 1;
if (pred) {
pred = pred->next;
}
else {
pred = l;
}
}
else {
pred = tmp;
tmp = tmp->next;
}
}
} while (dinNou == 1);
return l;
}
You use dinNou (again) to check whether you need to enter again into the cycle. The cycle is a do-while and dinNou is initialized with 0 and if a change occurs, then it will be modified to 1. Essentially, you do the change until there was no change. You have a mistake leading to an inifite loop at
while (tmp->next);
This will be false if tmp (which was initialized to l) happens to have no next element. Otherwise it will repeatedly ask whether there is a next element and since there is no change, it will always be true, leading to an infinite loop. What you did want in my opinion is to use the block following the while as the operation set to be done while tmp has next. To achieve that, simply remove the semi-colon:
while (tmp->next)
After you do that, inside the loop you check whether the average mark of the current student is greater than the next. If so, then you call interschimbare (swap) and set dinNou to 1. This also seems to be incorrect. If the two neighboring values have to be swapped, then interschimbare of tmp and tmp->next should be called. As a result, you do not really need the pred variable and you will need to set tmp to tmp->next regardless of whether a swap was done or not. Or even better, you can break the loop if a swap occurred.
I have two linked lists that I track using inputFront, inputRear, outputFront & outputRear. My problem arises when I enqueue the data from input into output. Printf prints only the first item from the input. Ex: my input is "a b c", it will only return "a". I'd appreciate the help. Thanks.
struct linked_list{
char *operand;
struct linked_list *next;
};
void enqueue(struct linked_list** queueFront, struct linked_list** queueRear,
char* token);
char* dequeue(struct linked_list** queueFront, struct linked_list** queueRear);
int main(int argc, char *argv[]){
struct linked_list *inputFront = NULL, *inputRear = NULL;
struct linked_list *outputFront = NULL, *outputRear = NULL;
for (int i = 1; i < argc; i++)
enqueue(&inputFront, &inputRear, argv[i]);
for (struct linked_list *p = inputFront; p != NULL; p = p->next)
enqueue(&outputFront, &outputRear, dequeue(&inputFront, &inputRear));
for (struct linked_list *p = outputFront; p != NULL; p = p->next)
printf("%s \n", dequeue(&outputFront, &outputRear));
}
void enqueue(struct linked_list** queueFront, struct linked_list** queueRear,
char* token){
struct linked_list* newNode = (struct linked_list*) malloc(
sizeof(struct linked_list));
newNode->operand = token;
newNode->next = NULL;
if (*queueRear == NULL && *queueFront == NULL){
*queueFront = *queueRear = newNode;
return;
}
(*queueRear)->next = newNode;
*queueRear = newNode;
}
char* dequeue(struct linked_list** queueFront, struct linked_list** queueRear){
if (*queueFront != NULL){
struct linked_list *remv = *queueFront;
char *remOperand = (*queueFront)->operand;
*queueFront = remv->next;
if (remv == (*queueRear))
*queueRear = NULL;
free(remv);
return remOperand;
}
else
return NULL;
}
There are 2 issues with your code. See.
for (struct linked_list *p = inputFront; p != NULL; p = p->next)
enqueue(&outputFront, &outputRear, dequeue(&inputFront, &inputRear));
You are using a pointer p to run through the list, but this pointer is not used inside the loop. The inputFront in the statement must be replaced by this pointer p. This will allow it to run through every element of the loop.
In the dequeue function, you are moving the pointer inputFront (now p). So, if you do p = p-> next in the loop, it will be done twice. This has to be removed.
Fixed code is
for (struct linked_list *p = inputFront; p != NULL; )
enqueue(&outputFront, &outputRear, dequeue(&p, &inputRear));
for (struct linked_list *p = outputFront; p != NULL; )
printf("%s \n", dequeue(&p, &outputRear));
The problem seems to be in your print loop. You let p advance until the end of the list, and you let dequeue retrieve the next (first) item in the list. But dequeue also removes the front from the list. Following the return, the for-loop now also advances p, whose next member has jus been advanced already. Given input a b c, I would expect the output now to be a c. If you take a debugger, you can get some more clues.
Getting some segfault on the following algorithm to add an element to the correct bucket in a hashtable.
My structures are basic:
struct kv {
char* key;
unsigned val;
struct kv* next;
};
struct hashtable {
struct kv** table;
unsigned size;
};
And my buggy function:
struct kv* ht_find_or_put(char* word, unsigned value,
struct hashtablet* hashtable,
unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke = malloc(sizeof (struct kv));
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
if (ke == NULL)
{
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
I know I haven't added yet all the tests (if malloc failed and such) just trying to debug this particular problem...
I'm allocating my table as such:
struct hashtable* hashtable_malloc(unsigned size)
{
struct hashtable *new_ht = malloc(sizeof(struct hashtable));
new_ht->size = size;
new_ht->table = malloc(sizeof(struct kv) * size);
for(unsigned i = 0; i < size; i++)
new_ht->table[i] = NULL;
return new_ht;
}
Any sort of help will greatly be appreciated. I'm only starting to learn.
The first issue is a memory leak, e.g. - you allocate memory using malloc, but than loses the reference to it, as you override the pointer:
// allocate memory
struct kv* ke = malloc(sizeof (struct kv));
// lose the reference
// VVVVVVVVVVV
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
The second issue, which probably causes the segfault, is that you try to de-reference a null pointer:
if (ke == NULL)
{
// ke is NULL, you can't de-reference it
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
The solution will be, IMHO, to allocate and put the new element, only upon failure to find it:
struct kv* ht_find_or_put(char* word, unsigned value, struct hashtablet* hashtable, unsigned (*hash)(char*))
{
unsigned index = hash(word) % hashtable->size;
struct kv* ke;
// first we try to find the node
for (ke = hashtable->table[index]; ke != NULL; ke = ke->next)
{
if (strcmp(ke->key, word) == 0)
return ke;
}
// didn't find it - lets create and put a new one.
if (ke == NULL)
{
ke = malloc(sizeof (struct kv));
// later add a check if the allocation succeded...
ke->key = word;
ke->val = value;
ke->next = hashtable->table[index];
hashtable->table[index] = ke;
}
return ke;
}
Since I didn't want to introduce entirely new code, that would just confuse you, I made the minimal changes to the original code.
I'm trying to merge (alterning) two lists and create a third list without adding new nodes (question here). The code executes without errors or warnings but it seems to not entering into the function AlternateLists(), since is not printing the "Inside the function" string. What do you think it means? Can you give me a quick review and/or an expalanation to my code/problem?
Thanks..
#include <stdio.h>
#include <stdlib.h>
struct nodo {
int inf;
struct nodo *succ;
struct nodo *prec;
};
typedef struct nodo nodo;
nodo *RicercaPosizione( nodo *a, int i );
nodo *Inserisci(nodo *a, int i, int x);
nodo* AlternateLists(nodo* list1, nodo* list2);
void *MostraLista(nodo *a);
int main(){
nodo *lista1=NULL;
nodo *lista2=NULL;
nodo *lista3=NULL;
int numeri[]={1,2,3,4};
int numeri2[]={5,6,7,8};
int i=0;
while(i!=4){
printf("%d",i);
lista1=Inserisci(lista1,i, numeri[i]);
i++;
}
printf("lista1 \n\n");
MostraLista(lista1);
lista2=lista1;
printf("lista2 \n\n");
MostraLista(lista2);
printf("\n\nlista3 \n\n");
lista3=AlternateLists(lista1,lista2);
MostraLista(lista3);
}
nodo* AlternateLists(nodo* l1, nodo* l2){
printf("\n\n Inside the fuction");
// Check if arrays are != NULL
if(!l1 && !l2) return NULL;
if(!l1) return l2;
if(!l2) return l1;
//----------------------
nodo* c1 = l1;
nodo* c2 = l2;
nodo* next;
nodo* next2;
while(c1){
next = c1->succ;
if(c2){ // check to make sure there are still nodes in array2
c1->succ = c2;
next2 = c2->succ;
c2->succ = next;
c2 = next2;
}else{
c1->succ = next;
}
c1 = next;
}
while(c2){ //if there are more nodes in list 2 then there are in list 1
c1->succ = c2;
c2 = c2->succ;
c1 = c2;
}
return l1;
}
//Insert etc
nodo *Inserisci(nodo *a, int i, int x){
nodo *q, *p;
if ( i == 0 ){
q = malloc(sizeof(nodo));
q->succ = a; q->prec = NULL;
q->inf = x;
if (a != NULL)
a->prec = q;
a = q;
} else {
p = RicercaPosizione( a, i-1);
if (p != NULL){
q = malloc(sizeof(nodo));
q->inf = x;
q->succ = p->succ;
q->prec = p;
if ( p->succ != NULL)
p->succ->prec = q;
p->succ = q;
}
}
return a;
}
nodo *RicercaPosizione( nodo *a, int i ){
nodo *p = a;
int j = 0;
while ( j < i && p != NULL){
p = p->succ;
j = j+1;
}
return p;
}
void *MostraLista(nodo *a){
nodo *p = a;
while ( p != NULL ){
printf("%d, ", p->inf);
p = p->succ;
}
printf("\n");
}
Use a debugger:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400810 in AlternateLists (l1=0x601010, l2=0x601010) at demo.c:67
67 c1->succ = c2;
The problem:
while(c1){
...
}
/* At this point c1 is NULL */
while(c2){
c1->succ = c2; /* Boom */
c2 = c2->succ;
c1 = c2;
}
Since you showed some interest in learning to debug, I'll try to answer your question.
If a function that should be entered unconditionally, such as 'AlternateLists' in your code, is not entered, there are some possible reasons:
1) The process crashed before it got to the call. A segfault, or other serious error that comes to the attention of the OS, will terminate your process, usually with an error message of some sort.
2) The process/thread got blocked indefinitely before the call, or asked for such a long sleep that it was effectively blocked. In that case, CPU use for that thread will be 0.
3) The process/thread got stuck in an infinite CPU loop before the call, or a loop so long that it seems infinite. In that case, CPU use for that thread will be 100%.
Found the problem :)
Thanks to everybody for the help!
The problem was when I was trying to copy the list in the main.
printf("lista1 \n\n");
MostraLista(lista1);
lista2=lista1; \\This line was the problem..
printf("lista2 \n\n");
MostraLista(lista2);
printf("\n\nlista3 \n\n");
lista3=AlternateLists(lista1,lista2);
MostraLista(lista3);