c pointer to pointer memory allocation - c

I am a noob in c, and i have this code that doesnt work properly because some bad memory allcoation i make for a char** pointer. Could you please help? Thx a lot in advance.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node_t {
struct tuple_t *tuple; //Entrada na lista
struct node_t *next; //o node seguinte da lista
};
struct tuple_t {
long timestamp; /* instante de criacao do tuplo*/
int n_fields; /* numero de campos deste tuplo */
char **fields; /* array com campos do tuplo */
/* 4 + 4 + 4 bytes?? */
};
char ** split_str(char [], char **, const char *);
struct node_t *node_create(void *node_data){
struct node_t *node = NULL;
node = (struct node_t *)malloc(sizeof(struct node_t));
if(!node){
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = (struct tuple_t *)malloc(sizeof(struct tuple_t));
if(!node->tuple){printf("Erro ao criar o node->tuple\n"); free(node); return NULL;}
node->tuple->fields = (char ** )malloc(strlen((char *) node_data) * sizeof(char *));
if(!node->tuple->fields){ printf("Erro ao criar o node->tuple->node_fields\n"); free(node->tuple); free(node); return NULL; }
char **array;
const char *sep=" ";
char *s = (char *)node_data;
char arr[strlen(s)];
int i = 0;
while(arr[i++]=s[i]);
array = split_str(arr,array, sep);
i = 0;
while(array[i]){
node->tuple->fields[i] = (char *)malloc((strlen(array[i])) * sizeof(char));
if(!node->tuple->fields[i]){
printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
return NULL;
}
node->tuple->fields[i] = array[i];
// printf("array[i]=%s\n",array[i]);
// printf("node->tuple->fields[i]=%s\n",node->tuple->fields[i]);
i++;
}
node->tuple->n_fields = i;
node->tuple->timestamp = 0L;
node->next = NULL;
return node;
}
char** split_str(char writablestring[],char **array, const char *sep ){
array = malloc(strlen(writablestring) + 1);
if(! array){printf("Erro ao alocar memoria para o array em split\n"); return NULL;}
char *token = strtok(writablestring, sep);
int i=0;
while(token != NULL)
{
array[i] = malloc(strlen(token)+1);
if(!array[i])
return NULL;
array[i] = token;
token = strtok(NULL, " ");
i++;
}
return array;
}
int main(int argc, char** argv)
{
void * n_data = "hello 123 ploc";
struct node_t * node = node_create(n_data);
printf("node->num_fields=%d\n", node->tuple->n_fields);
int i=0;
while( node->tuple->fields[i] ){
printf("node->tuple->fields[%d]=%s\n",i,node->tuple->fields[i]);
i++;
}
return 0;
}
End code.

Your split_str() function returns pointers into writablestring, which is the array arr in node_create(). You then copy these pointers into node->tuple->fields[i] - but the arr array won't exist after the node_create() function exits - so those pointers will no longer be valid. Instead, you need to copy the returned string into the memory that you have allocated (this also shows how you can use a for() loop in place of your while(), and you also need to free the memory that was allocated in split_str()):
for (i = 0; array[i]; i++) {
node->tuple->fields[i] = malloc(strlen(array[i]) + 1);
if (!node->tuple->fields[i]){
printf("Erro ao alocar memoria em node_create() para node->tuple->fields[i]\n");
return NULL;
}
strcpy(node->tuple->fields[i], array[i]);
}
free(array);
Additionally, your code assumes that the array returned by split_str() will be terminated by a NULL, but the function does not ensure this. The function has numerous other problems (incorrect size passed to malloc(), memory leak caused by unnecessary malloc()) - so you need to fix it, too:
char **split_str(char writablestring[], const char *sep)
{
char **array = malloc(strlen(writablestring) * sizeof array[0]);
if(!array) {
printf("Erro ao alocar memoria para o array em split\n");
return NULL;
}
char *token = strtok(writablestring, sep);
int i;
for (i = 0; (array[i] = token) != NULL; i++) {
token = strtok(NULL, " ");
}
return array;
}
(Note that array does not need to be passed as a parameter - it's being immediately overwritten anyway, so I turned it into a local variable).
Once you've done this, you might notice that there's really no reason to allocate array in split_str(), only to copy its contents to node->tuple->fields and then free it. You might as well pass the array node->tuple->fields to split_str() and have it write directly into it. It could then return the number of strings allocated - that would look like:
int split_str(char [], char **, const char *);
struct node_t *node_create(void *node_data)
{
struct node_t *node = NULL;
char *s = node_data;
size_t slen = strlen(s);
node = malloc(sizeof *node);
if (!node) {
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = malloc(sizeof *node->tuple);
if (!node->tuple) {
printf("Erro ao criar o node->tuple\n");
free(node);
return NULL;
}
node->tuple->fields = malloc(slen * sizeof node->tuple->fields[0]);
if (!node->tuple->fields) {
printf("Erro ao criar o node->tuple->node_fields\n");
free(node->tuple);
free(node);
return NULL;
}
char arr[slen + 1];
strcpy(arr, s);
int i = split_str(arr, node->tuple->fields, " ");
node->tuple->n_fields = i;
node->tuple->timestamp = 0L;
node->next = NULL;
return node;
}
int split_str(char writablestring[], char **array, const char *sep)
{
char *token = strtok(writablestring, sep);
int i;
for (i = 0; token != NULL; i++) {
array[i] = malloc(strlen(token) + 1);
if (!array[i]) {
printf("Erro ao criar o array[i]\n");
break;
}
strcpy(array[i], token);
token = strtok(NULL, " ");
}
return i;
}

Try something like this instead:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct tuple_t
{
long timestamp; /* instante de criacao do tuplo*/
int n_fields; /* numero de campos deste tuplo */
char** fields; /* array com campos do tuplo */
};
struct node_t
{
struct tuple_t* tuple; //Entrada na lista
struct node_t* next; //o node seguinte da lista
};
char** split_str(const char *, const char *, int *);
void node_destroy(struct node_t*);
struct node_t* node_create(char* node_data)
{
struct node_t* node = (struct node_t *) malloc(sizeof(struct node_t));
if(!node)
{
printf("Erro ao criar um node!\n");
return NULL;
}
node->tuple = (struct tuple_t *) malloc(sizeof(struct tuple_t));
if(!node->tuple)
{
printf("Erro ao criar o node->tuple\n");
node_destroy(node);
return NULL;
}
node->tuple->timestamp = 0L;
node->tuple->fields = split_str(node_data, " ", &(node->tuple->n_fields));
if(!node->tuple->fields)
{
printf("Erro ao criar o node->tuple->node_fields\n");
node_destroy(node);
return NULL;
}
node->next = NULL;
return node;
}
void node_destroy(struct node_t* node)
{
if(node)
{
if(node->tuple)
{
if(node->tuple->fields)
{
for(int i = 0; i < node->tuple->n_fields; ++i)
free(node->tuple->fields[i]);
free(node->tuple->fields);
}
free(node->tuple);
}
free(node);
}
}
char** split_str(const char* str, const char* sep, int* found)
{
if (found) *found = 0;
int len = strlen(str);
char** array = (char**) malloc(len * sizeof(char*));
if(!array)
{
printf("Erro ao alocar memoria para o array em split\n");
return NULL;
}
++len;
char* writablestring = (char*) malloc(len);
if(!array)
{
printf("Erro ao alocar memoria para writeablestring em split\n");
free(array);
return -1;
}
strncpy(writablestring, str, len);
char* token = strtok(writablestring, sep);
int i = 0;
while(token)
{
len = strlen(token) + 1;
array[i] = (char*) malloc(len);
if(!array[i])
{
printf("Erro ao alocar memoria para o array item em split\n");
free(writeablestring);
for(int j = 0; j < i; ++j)
free(array[j]);
free(array);
return NULL;
}
strncpy(array[i], token, len);
++i;
token = strtok(NULL, sep);
}
free(writeablestring);
if(found) *found = i;
return array;
}
int main(int argc, char** argv)
{
char* n_data = "hello 123 ploc";
struct node_t* node = node_create(n_data);
if(node)
{
printf("node->tuple->n_fields=%d\n", node->tuple->n_fields);
for(int i = 0; i < node->tuple->n_fields; ++i)
printf("node->tuple->fields[%d]=%s\n", i, node->tuple->fields[i]);
node_destroy(node);
}
return 0;
}

Related

List vector print does not work

I'm doing a hash table, where I have a one vector with a list inside each node of it. But when I go to print it does not appear the items that are within the list, and if I try to put more than one element in the list, it gives segmentation failure in the second. Below is the code and the result:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
enum erro {
semErro = 0, posInv = 1, listaCheia = 2, listaVazia = 3, existe = 4, naoExiste = 5
};
typedef struct no{
char nome[100];
char telefone[20];
struct no *prox;
} nodo;
typedef struct{
int tamanho;
nodo *inicio;
} lista;
typedef struct {
int tamanhoTabelaHash;
int colisoes;
lista* vetor;
} tabela;
///////////////////Chamada de Funções///////////////////
lista *novaLista();
tabela *criaTabela(int tam);
int insereTabela(tabela *tabela, char *entraNome, char *entraTelefone);
int insereNoInicioI(lista *lista,char *entraNome, char *entraTelefone);
int hash1(char *entraNome, int tam);
void imprime(lista *lista);
void imprimeTabela(tabela *tabela);
///////////////////Funções Lista///////////////////
void imprime(lista *lista){
int i;
nodo *no; //<<<<<Possível local do erro>>>>>
puts("Lista: \n");
for (i = 0; i < lista->tamanho; i++) {
printf("Nome: %s Telefone: %s\n",no->nome,no->telefone);
no=no->prox;
}
}
lista *novaLista(){
lista *l = (lista*)malloc(sizeof(lista));
l->tamanho=0;
l->inicio=NULL;
return l;
}
int insereNoInicioI(lista *lista,char *entraNome, char *entraTelefone){
nodo *novo=(nodo *)malloc(sizeof(nodo));
strcpy(novo->nome,entraNome);
strcpy(novo->telefone,entraTelefone);
novo->prox = lista->inicio;
lista->inicio = novo;
lista->tamanho++;
return semErro;
}
tabela *criaTabela(int tam) {
if( tam < 1 ) return NULL;
tabela *table = (tabela *)malloc(sizeof(tabela));
table->tamanhoTabelaHash = tam;
table->colisoes = 0;
for (int i = 0; i < 10; i++) {
table[i].vetor = NULL;
}
return table;
}
void imprimeTabela(tabela *tabela) {
int i;
printf("\nTabela: \n");
for (i = 0; i < tabela->tamanhoTabelaHash ; i++) {
printf("\nindice[%d]:", i);
if(tabela[i].vetor!=NULL){
imprime(tabela[i].vetor);
}
}
}
int insereTabela(tabela *tabela, char *entraNome, char *entraTelefone){
int pos = 0;
pos = hash1(entraNome,10000);//Função que retorna uma posição( no caso 8 para o primeiro nome e 6 para o segundo e terceiro
}
if(tabela[pos].vetor==NULL){
lista *list = novaLista();
tabela[pos].vetor = list;
}
nodo *novo=(nodo *)malloc(sizeof(nodo));
insereNoInicioI(tabela[pos].vetor, entraNome, entraTelefone);
return semErro;
}
int main(){
setlocale(LC_ALL, "Portuguese");
tabela *table = criaTabela(10);
char nome[100] = "Maria Cláudia Feliz";
char telefone[20] = "(53)98401-8583";
char nome1[100] = "Everton Almeida";
char telefone1[20] = "(53)90000-8583";
char nome2[100] = "Everton Almeida";
char telefone2[20] = "(53)90000-8583";
insereTabela(table,nome,telefone);
insereTabela(table,nome1,telefone1);
insereTabela(table,nome2,telefone2);
imprimeTabela(table);
return semErro;
}
Resultado:
Tabela:
indice[0]:
indice[1]:
indice[2]:
indice[3]:
indice[4]:
indice[5]:
indice[6]:Lista:
Nome: Telefone: //<<<<Deveria imprimir o nome e telefone>>>>
Nome: Telefone: //<<<<Deveria imprimir o nome e telefone>>>>
indice[7]:
indice[8]:Lista:
//<<<<Deveria imprimir o nome e telefone>>>>
Falha de segmentação(imagem do núcleo gravada)
If you can help, thank you.
You have at least one serious problem here:
tabela *criaTabela(int tam) {
if (tam < 1) return NULL;
// you allocate space for 1 tabela
tabela *table = (tabela *)malloc(sizeof(tabela));
table->tamanhoTabelaHash = tam;
table->colisoes = 0;
// but here you write to 10 tabelas ....
for (int i = 0; i < 10; i++) {
table[i].vetor = NULL;
}
return table;
}
You if you write to 10 tabelas, you should allocate space for 10 tabelas:
tabela *table = (tabela *)malloc(sizeof(tabela) * 10);
The code in your answer yields in undefined bahaviour. In other works it may appear to work. Google "undefined bahaviour".
There may be more problems elsewhere in your code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <locale.h>
enum erro {
semErro = 0, posInv = 1, listaCheia = 2, listaVazia = 3, existe = 4, naoExiste = 5
};
typedef struct no{
char nome[100];
char telefone[20];
struct no *prox;
} nodo;
typedef struct{
int tamanho;
nodo *inicio;
} lista;
typedef struct {
int tamanhoTabelaHash;
int colisoes;
lista* vetor;
} tabela;
///////////////////Chamada de Funções///////////////////
lista *novaLista();
tabela *criaTabela(int tam);
int insereTabela(tabela *tabela, char *entraNome, char *entraTelefone);
int insereNoInicioI(lista *lista,char *entraNome, char *entraTelefone);
int hash1(char *entraNome, int tam);
void imprime(lista *lista);
void imprimeTabela(tabela *tabela);
///////////////////Funções Lista///////////////////
void imprime(lista *lista){
int i;
nodo *no = lista-> inicio;
puts("Lista: \n");
for (i = 0; i < lista->tamanho; i++) {
printf("Nome: %s Telefone: %s\n",no->nome,no->telefone);
no=no->prox;
}
}
lista *novaLista(){
lista *l = (lista*)malloc(sizeof(lista));
l->tamanho=0;
l->inicio=NULL;
return l;
}
int insereNoInicioI(lista *lista,char *entraNome, char *entraTelefone){
nodo *novo=(nodo *)malloc(sizeof(nodo));
strcpy(novo->nome,entraNome);
strcpy(novo->telefone,entraTelefone);
novo->prox = lista->inicio;
lista->inicio = novo;
lista->tamanho++;
return semErro;
}
tabela *criaTabela(int tam) {
if( tam < 1 ) return NULL;
tabela *table = (tabela *)malloc(sizeof(tabela)*10);
table->tamanhoTabelaHash = tam;
table->colisoes = 0;
for (int i = 0; i < 10; i++) {
table[i].vetor = NULL;
}
return table;
}
void imprimeTabela(tabela *tabela) {
int i;
printf("\nTabela: \n");
for (i = 0; i < tabela->tamanhoTabelaHash ; i++) {
printf("\nindice[%d]:", i);
if(tabela[i].vetor!=NULL){
imprime(tabela[i].vetor);
}
}
}
int hash1(char *string, int tam) {
int tamanho = strlen(string);
unsigned soma = 0;
for (int i = 0; i < tamanho; i++) {
soma = soma * 251 + string[i];
}
return soma % tam;
}
int insereTabela(tabela *tabela, char *entraNome, char *entraTelefone){
int pos = 0;
pos = hash1(entraNome,10);
if(tabela[pos].vetor==NULL){
lista *list = novaLista();
tabela[pos].vetor = list;
}
nodo *novo=(nodo *)malloc(sizeof(nodo));
insereNoInicioI(tabela[pos].vetor, entraNome, entraTelefone);
return semErro;
}
int main(){
setlocale(LC_ALL, "Portuguese");
tabela *table = criaTabela(10);
char nome[100] = "Maria Cláudia Feliz";
char telefone[20] = "(53)98401-8583";
char nome1[100] = "Everton Almeida";
char telefone1[20] = "(53)90000-8583";
char nome2[100] = "Everton Almeida";
char telefone2[20] = "(53)90000-8583";
insereTabela(table,nome,telefone);
insereTabela(table,nome1,telefone1);
insereTabela(table,nome2,telefone2);
imprimeTabela(table);
return semErro;
}
Resultado:
indice[0]:
indice[1]:
indice[2]:Lista:
Nome: Everton Almeida Telefone: (53)90000-8583
indice[3]:
indice[4]:
indice[5]:Lista:
Nome: Everton Telefone: (53)90000-8583
indice[6]:
indice[7]:
indice[8]:Lista:
Nome: Maria Cláudia Feliz Telefone: (53)98401-8583
indice[9]:
Thanks to all comments THIS IS THE CODE WORKING, but I have one more doubt, because the name clause goes wrong if the setlocale (LC_ALL, "Portuguese");

Error ! null list

I have a problem, my code is executing option 3 only the first time, if I go back to the menu and try again appears nulla. Case 3 is to list a list of names in alphabetical alphabetical order and reverse order (InsertOrd 0 / InsertDec 1);
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <locale.h>
#define N 10000
typedef struct Lista {
char *data;
struct Lista *next;
} Lista;
//Ordem Crescente
struct Lista *InsertOrd(struct Lista *head, const char *data) {
struct Lista *newp;
struct Lista *tmp;
char *new_data;
/* aloca o novo item */
newp = ((struct Lista*)malloc(sizeof(struct Lista)));
new_data = strdup(data);
//strdup aloca memória na pilha.
if (newp == NULL || new_data == NULL) {
fprintf(stderr, "out of memory");
return NULL;
}
newp->data = new_data;
newp->next = NULL;
/* check if element should be inserted at the head */
if (head == NULL || strcmp(new_data, head->data) < 0) {
newp->next = head;
head = newp;
} else {
/* otherwise find the point of insertion */
tmp = head;
while (tmp->next && strcmp(new_data, tmp->next->data) >= 0) {
tmp = tmp->next;
}
newp->next = tmp->next;
tmp->next = newp;
}
return head;
}
//Ordem decrescente
struct Lista *InsertDec(struct Lista *head, const char *data) {
struct Lista *newp;
struct Lista *tmp;
char *new_data;
/* aloca o novo item */
newp = ((struct Lista*)malloc(sizeof(struct Lista)));
new_data = strdup(data);
//strdup aloca memória na pilha.
if (newp == NULL || new_data == NULL) {
fprintf(stderr, "out of memory");
return NULL;
}
newp->data = new_data;
newp->next = NULL;
/* verificar o elemento deve ser inserido na cabeça*/
if (head == NULL || strcmp(new_data, head->data) < 0) {
newp->next = head;
head = newp;
} else {
/* caso contrário, encontre o ponto de inserção */
tmp = head;
while (tmp->next && strcmp(new_data, tmp->next->data) <= 0) {
tmp = tmp->next;
}
newp->next = tmp->next;
tmp->next = newp;
}
return head;
}
void liberar(struct Lista *filmes)
{
while (filmes != NULL) {
struct Lista *next = filmes->next;
free(filmes->data);
free(filmes);
filmes = next;
}
}
void escrever(struct Lista * film,struct Lista * filmes)
{
for (film = filmes; film != NULL; film = film->next) {
printf("\n Nome: %s", film->data);
}
}
int main()
{
struct Lista *filmes;
struct Lista *film;
FILE *arq;
char linha[600];
int opcao;
/* insert the items */
filmes = NULL;
/* open the file */
arq = fopen("asd.txt", "r");
if (arq == NULL) {
printf("Ocorreu um erro!");
return 1;
}
do{
printf("\n1- Listar todos os atores da lista em ordem alfabetica e alfabetica reversa");
printf("\n2- Listar todos os filmes de um determinado ator em ordem cronologica.");
//\n Os filmes que não tiverem a informação de ano são mostrados em último lugar
printf("\n3- Listar todos os filmes em ordem alfabetica e alfabetica reversa");
printf("\n4- Inserir novo filme");
printf("\n5- Remocao de filmes");
printf("\n6-SAIR DO PROGRAMA");
printf("\n");
scanf("%d",&opcao);
if(opcao<1 || opcao>6){
printf("\nO numero que voce digitou eh invalido!\n Por favor tente novamente.\n");
}
switch(opcao)
{
case 1:
break;
case 2:
break;
case 3:
printf("\n Voce gostaria de listar em ordem alfabetica ou alfabetica reversa (0/1) :");
int op;
scanf("%d",&op);
if(op!=0 && op!=1)
{
printf("\n Voce precisa digita o numero 1 ou 0 apenas!\n");
}
switch(op){
case 0:
while (fgets(linha, sizeof linha, arq)) {
char *p = strtok(linha, ",");
filmes = InsertOrd(filmes, p);
}
fclose(arq);
escrever(film,filmes);
liberar(filmes);
break;
case 1:
while (fgets(linha, sizeof linha, arq)) {
char *p1 = strtok(linha, ",");
filmes = InsertDec(filmes, p1);
}
fclose(arq);
escrever(film,filmes);
liberar(filmes);
break;
}
break;
case 4:
break;
case 5:
break;
case 6:
printf("\nSaindo do programa...");
break;
}
}while(opcao!=6);
// escrever(film,filmes);
/* free the list */
while (filmes != NULL) {
struct Lista *next = filmes->next;
free(filmes->data);
free(filmes);
filmes = next;
}
return 0;
}
The first time I run either option 1 or 0 of case 3 works but then this appears:
You have only one
arq = fopen("asd.txt", "r");
and you have several
fclose(arq);
Option 3 (both cases) does
while (fgets(linha, sizeof linha, arq))
// ...
fclose(arq);
So next time you use option 3 - it fails.
I suggest that instead of fclose in those options, you add rewind before reading.
Please test your code step by step as you build it.

Malloc and Realloc crash in C?

i have to do with my friend a program in C for my school.
The problem is, when i would malloc a pointer, it doesn't work, and the application will crashed.
But not in debug mod. In debug mod, it works.
This is a part of my code:
#include <bplus.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define LOG "log.txt"
#define LOGIDX "log.idx"
struct event {
time_t nb;
char *username;
int type;
char *message;
};
struct eventlist {
struct event event;
struct eventlist *nextelem;
};
struct eventlist *getEventList(time_t date);
void insert(struct eventlist *list, struct eventlist *event);
struct event getEventFromString(char *str);
char *getLine(FILE *file);
int file_exists(const char *fname);
char *dechiffrer(const char *pChaineChiffree);
int main(void) {
time_t timenow = time(NULL);
struct tm *tm = gmtime(&timenow);
tm->tm_hour = 0;
tm->tm_min = 0;
tm->tm_sec = 0;
time_t time = mktime(tm);
struct eventlist *list = getEventList(time);
return 0;
}
struct eventlist *getEventList(time_t date) {
int end = 0;
FILE *file = NULL;
char str[20];
char *line = NULL;
char *uncode = NULL;
ENTRY e;
IX_DESC faddress;
struct eventlist *list = NULL; // Liste a retourner
struct event *event = NULL; // Contient l'evenement
struct eventlist *templist = NULL; // Contient l'evenement a mettre dans list
// On ouvre / crée le fichier .idx
if (file_exists(LOGIDX))
open_index(LOGIDX, &faddress, 0);
else
make_index(LOGIDX, &faddress, 0);
// On ouvre le fichier de log
if ((file = fopen(LOG, "rb")) != NULL) {
// On met dans e.key le temps
sprintf(str, "%d", (int) date);
strcpy(e.key, str);
if (find_key(&e, &faddress)) { // Si la clé existe
fseek(file, e.recptr, SEEK_SET); // On se positionne
line = getLine(file); // On récupère la ligne
while (!feof(file) && !end) { // Boucle principale
printf("\ngetEventList 1");
if (line != NULL) {
uncode = dechiffrer(line); // On déchiffre la ligne
printf("\ngetEventList 2");
event = (struct event *) malloc(sizeof(struct event *) * 1); // On alloue de la place
printf("\ngetEventList 3");
if (event) {
*event = getEventFromString(uncode); // On la transforme en structure
printf("\ngetEventList 4");
if (event->nb < date + 86400) {
templist = (struct eventlist *) malloc(sizeof(struct eventlist *) * 1);
printf("\ngetEventList 5");
if (templist) {
templist->event = *event;
templist->nextelem = NULL;
printf("\ngetEventList 6");
if (list == NULL)
list = templist;
else
insert(list, templist);
printf("\ngetEventList 7");
line = getLine(file); // On récupère la ligne
printf("\ngetEventList 8");
} else {
list = NULL;
end = 1;
}
} else
end = 1;
} else {
list = NULL;
end = 1;
}
} else
end = 1;
}
} else { // Sinon, on affiche un message
list = NULL;
printf("\nErreur: Clé non trouvée !");
}
fclose(file);
} else {
list = NULL;
printf("\nErreur lors de l'ouverture du fichier !");
}
return list;
}
void insert(struct eventlist *list, struct eventlist *event) {
struct eventlist *temp = list;
struct eventlist *lasttemp = NULL;
printf("\n(%s %s)", temp->event.username, event->event.username);
while (temp->nextelem != NULL && stricmp(temp->event.username, event->event.username)) {
temp = temp->nextelem;
}
lasttemp = temp;
while (temp != NULL && !stricmp(temp->event.username, event->event.username)) {
lasttemp = temp;
temp = temp->nextelem;
}
event->nextelem = temp;
lasttemp->nextelem = event;
}
struct event getEventFromString(char *str) {
struct event event;
event.nb = 0;
event.type = 0;
event.username = NULL;
event.message = NULL;
int time;
int type;
char *username = (char *) malloc(sizeof(char *) * strlen(str));
char *message = (char *) malloc(sizeof(char *) * strlen(str));
if (sscanf(str, "%d %d %s %[^\n]s", &(time), &(type), username, message)) {
event.nb = (time_t) time;
event.type = type;
event.username = username;
event.message = message;
}
return event;
}
char *getLine(FILE *file) {
char *line = NULL;
unsigned char c;
int end = 0;
int ln = 0;
printf("\ngetLine 1");
line = (char *) malloc(sizeof(char *) * 1);
printf("\ngetLine 2");
if (line != NULL) {
while(!feof(file) && !end) {
c = fgetc(file);
if (c != '\n' && c != '\r') {
printf("\nDEBUG: %c %d %s", c, ln, line);
line = (char *) realloc(line, sizeof(char *) * (ln + 2));
if (line != NULL) {
line[ln++] = c;
line[ln] = '\0';
} else
end = 1;
} else
end = 1;
}
line[ln] = '\0';
}
if (line[0] == '\0' || line[1] == '\0')
line = NULL;
return line;
}
int file_exists(const char *fname) {
FILE *file;
int returncode = 0;
if ((file = fopen(fname, "r"))) {
fclose(file);
returncode = 1;
}
return returncode;
}
char *dechiffrer(const char *pChaineChiffree) {
char *dechiff;
unsigned char car;
unsigned int i;
dechiff = malloc(strlen(pChaineChiffree) + 1);
for (i = 0; pChaineChiffree[i] != '\0'; i++) {
car = pChaineChiffree[i];
car = (car & 0x0F) << 4 | (car & 0xF0) >> 4;
// car -= 0x55;
dechiff[i] = car;
}
dechiff[i] = '\0';
return dechiff;
}
I think it's a bufferoverflow, but i don't know where is the problem, and why it's bugged.
The crash occured in this malloc:
printf("\ngetLine 1");
line = (char *) malloc(sizeof(char *) * 1);
printf("\ngetLine 2");
Please help me
Thanks
0ddlyoko
EDIT:
Ok i've found the problem, it was with all my sizeof(XXX *), i've just changed this to sizeof(XXX).
Thanks !

Sorting Simple Linked List - C

[UPTATED WITH ANSWER AT THE END] I tried many things but I still don't know how I can do any sorting with a simple linked list. It should be sorted like the number saved on each node goes from the lower till the higher one. What can I do?
I'm not allowed to sort the numbers as I save then on the list. The sorting must be made after the list is complete.
the code isn't completely ready yet
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#define pi 3.14159265359
#define N 50
typedef struct lista{
char palavra[N];
int repeticao;
struct lista *prox;
} Lista;
Lista* lista_cria(){
return NULL;
}
int vazia(Lista *LISTA){
if(LISTA->prox == NULL) return 1;
else return 0;
}
void insere(Lista **lis, char *s){
Lista* novo = (Lista*) malloc (sizeof(Lista));
strcpy(novo->palavra, s);
novo->prox = NULL;
while (*lis)
lis = &(*lis)->prox;
*lis = novo;
}
Lista* retira(Lista* lis, char *s){
Lista* ant = NULL;
Lista* p = lis;
while(p != NULL && (strcmp(s, p->palavra) != 0)){
ant = p;
p = p->prox;
}
if(p == NULL) return lis;
if(ant == NULL) lis = p->prox;
else ant->prox = p->prox;
free(p);
return lis;
}
void imprimir_lista(Lista* lis){
Lista* p;
for(p = lis; p != NULL; p = p->prox)
printf("%s ", p->palavra);
printf("\n \n");
}
int busca(Lista* lis, char *s){
Lista *p;
int cont = 0;
for(p = lis; p != NULL; p = p->prox){
if(strcmp(p->palavra, s) == 0) cont++;
}
return cont;
}
Lista* repeticao(Lista* lis, int i){
Lista *p;
char s[50];
int cont;
printf("\n \n Doc%d", i);
for(p = lis; p != NULL; p = p->prox){
strcpy(s, p->palavra);
cont = busca(p, s);
printf(" \n\t %s: %d ", s, cont);
p->repeticao = cont;
}
return lis; /* return p*/
}
void liberar_lista(Lista *lis){
Lista *aux = lis;
while (aux != NULL) {
Lista *aux2 = aux->prox;
free(aux);
aux = aux2;
}
}
float produto_escalar (Lista *lis1, Lista *lis2) {
Lista *aux1 = lis1, *aux2 = lis2;
float resultado=0;
while (aux1 != NULL) {
while (aux2 != NULL) {
if (strcmp(aux1->palavra, aux2->palavra) == 0 ) {
resultado+=(aux1->repeticao*aux2->repeticao);
aux2 = aux2->prox;
break;
}
else {
aux2 = aux2->prox;
}
}
aux1 = aux1->prox;
aux2 = lis2;
}
return resultado;
}
float formula (Lista *lis1, Lista *lis2){
float resultado;
resultado = acos(produto_escalar(lis1, lis2)/(sqrt(produto_escalar(lis1, lis1))*sqrt(produto_escalar(lis2, lis2))));
resultado = (((resultado *50)*4)/pi)-100;
if (resultado<0){
resultado*=-1;
}
return resultado;
}
void checa_plagio (float resultado) {
if (resultado>=50) {
printf("\n O arquivo foi plagiado. \n\t Arquivo é %.3f%% parecido.", resultado);
}
else
printf("\n O arquivo não foi plagiado \n\t Arquivo é %.3f%% parecido.", resultado);
}
int main () {
char arquivo1[] = "doc1.txt", arquivo2[] = "doc2.txt";
char string[50];
double resposta;
FILE *fp1, *fp2;
Lista *lista1, *lista2;
lista1 = lista_cria();
lista2 = lista_cria();
fp1 = fopen (arquivo1, "r+") ;
if (fp1 == NULL) {
printf("\nErro. Não foi possível abrir o arquivo.\n");
return EXIT_FAILURE;
}
while(!feof(fp1)){
fscanf(fp1, "%s[A-Z a-z]", string);
insere(&lista1, string);
}
fclose(fp1);
fp2 = fopen (arquivo2, "r+") ;
if (fp2 == NULL) {
printf("\nErro. Não foi possível abrir o arquivo.\n");
return EXIT_FAILURE;
}
while(!feof(fp2)){
fscanf(fp2, "%s[A-Z a-z]", string);
insere(&lista2, string);
}
fclose(fp2);
/*imprimir_lista(lista1);
imprimir_lista(lista2);*/
lista1 = repeticao(lista1, 1);
lista2 = repeticao(lista2, 2);
resposta = formula (lista1, lista2);
checa_plagio(resposta);
liberar_lista(lista1);
liberar_lista(lista2);
return EXIT_SUCCESS;
}
[UPDATED WITH ANSWER]
THE CODE I USED TO SORT:
#define N 50
#include <stdlib.h>
#include <stdio.h>
typedef struct lista{
char palavra[N];
int repeticao;
struct lista *prox;
} Lista;
Lista* sort (Lista *lis) {
Lista *temp, *empurra;
Lista *aux1, *aux2;
Lista *guarda;
aux1 = NULL;
for (temp = lis; temp != NULL; temp = temp->prox){
aux2 = temp;
for (empurra=temp->prox; empurra != NULL; empurra = empurra->prox){
if (empurra->repeticao < temp->repeticao){
guarda = temp->prox;
temp->prox = empurra->prox;
if(guarda == empurra)
empurra->prox = temp;
else
empurra->prox = guarda;
if(aux2 != temp)
aux2->prox = temp;
if(aux1)
aux1->prox = empurra;
else
lis = empurra;
guarda = temp;
temp = empurra;
empurra = guarda;
}
aux2 = empurra;
}
aux1 = temp;
}
return lis;
}
int main (){
return 0;
}
I think the most learning approach that you can take, it's to think that the linked list is an array. With that approach you can simply, access the elements of the array and apply a sort algorithm (like bubble sort) and when make the swap of the elements using the pointer to the elements. With that would be just a matter to redirect the pointers (to next elements) for the right elements.
Also, pay attention to the particular cases of the sorts (the beginning and the end of list, in this case).
Here's a example:
Suppose that we have the structure for the linked list:
typedef struct list{
int n;
struct list *next;
} List;
And we want to sort the linked list using the int n, a code example would be something like this:
void sort (List * begin) {
List *currentElement, *previousElement;
int swapped = 1;
while (swapped) {
swapped = 1;
while (swapped != 0) {
swapped = 0;
currentElement = begin;
previousElement = NULL; //No previous element in the beginning of the list
while(currentElement->next != NULL) { //Has another element, it's not the end of the list
List *nextElement = currentElement->next;
if(currentElement->n > nextElement->n) {
//swapping the elements
if (previousElement == NULL) { //is the first element
List *auxPtr = nextElement->next;
nextElement->next = currentElement;
currentElement->next = auxPtr;
begin = nextElement; //nextElement is the first element of the list now
}
else {
previousElement->next = nextElement;
currentElement->nextElement->next;
nextElement->next = currentElement;
}
previousElement = nextElement; //The nextElement is 'behind' the currentElement so it should be the previousElement
swapped = 1; // a swap was made
//The elements where swapped so currentElement is already in the 'position' of the next element, there is no need to upload it value
}
else { // there is no need to swap, just walk foward in the list
previousElement = currentElement;
currentElement = nextElement;
}
}
}
}
}
I used a simple bubble sort for the sorting

Problems with this stack implementation

where is the mistake?
My code here:
typedef struct _box
{
char *dados;
struct _box * proximo;
} Box;
typedef struct _pilha
{
Box * topo;
}Stack;
void Push(Stack *p, char * algo)
{
Box *caixa;
if (!p)
{
exit(1);
}
caixa = (Box *) calloc(1, sizeof(Box));
caixa->dados = algo;
caixa->proximo = p->topo;
p->topo = caixa;
}
char * Pop(Stack *p)
{
Box *novo_topo;
char * dados;
if (!p)
{
exit(1);
}
if (p->topo==NULL)
return NULL;
novo_topo = p->topo->proximo;
dados = p->topo->dados;
free(p->topo);
p->topo = novo_topo;
return dados;
}
void StackDestroy(Stack *p)
{
char * c;
if (!p)
{
exit(1);
}
c = NULL;
while ((c = Pop(p)) != NULL)
{
free(c);
}
free(p);
}
int main()
{
int conjunto = 1;
char p[30], * v;
int flag = 0;
Stack *pilha = (Stack *) calloc(1, sizeof(Stack));
FILE* arquivoIN = fopen("L1Q3.in","r");
FILE* arquivoOUT = fopen("L1Q3.out","w");
if (arquivoIN == NULL)
{
printf("Erro na leitura do arquivo!\n\n");
exit(1);
}
fprintf(arquivoOUT,"Conjunto #%d\n",conjunto);
while (fscanf(arquivoIN,"%s", p) != EOF )
{
if (pilha->topo == NULL && flag != 0)
{
conjunto++;
fprintf(arquivoOUT,"\nConjunto #%d\n",conjunto);
}
if(strcmp(p, "return") != 0)
{
Push(pilha, p);
}
else
{
v = Pop(pilha);
if(v != NULL)
{
fprintf(arquivoOUT, "%s\n", v);
}
}
flag = 1;
}
StackDestroy(pilha);
return 0;
}
The Pop function returns the string value read from file.
But is not correct and i don't know why.
You're not allocating any storage for the strings pointed to by dados - you're just re-using one string buffer (p) and passing that around, so all your stack elements just point to this one string.

Resources