Making strcpy function with linked list in c - c

I was making my own strcpy function using linked list but couldn't get how to do.
Without using linked list it could be like this
char* cp2014strcpy(char * dest_ptr, const char * src_ptr) {
char* strresult = dest_ptr;
if((NULL != dest_ptr) && (NULL != src_ptr)) {
while (NULL != src_ptr) {
*dest_ptr++ = *src_ptr++;
}
*dest_ptr = NULL;
}
return strresult;
}
but I couldn't get how to make strcpy using linked list.

#include <stdio.h>
#include <stdlib.h>
typedef struct node {
char ch;
struct node *next;
} LL_str;
LL_str *LL_new(char ch){
LL_str *s = malloc(sizeof(*s));//check omitted
s->ch = ch;
s->next = NULL;
return s;
}
LL_str *s_to_LL(const char *s){
LL_str *top, *curr;
if(!s || !*s)
return NULL;
curr = top = LL_new(*s);
while(*++s){
curr = curr->next = LL_new(*s);
}
return top;
}
LL_str *LL_strcpy(const LL_str *s){//LL_strdup ??
LL_str *top, *curr;
if(!s)
return NULL;
curr = top = LL_new(s->ch);
s=s->next;
while(s){
curr = curr->next = LL_new(s->ch);
s=s->next;
}
return top;
}
void LL_println(const LL_str *s){
while(s){
putchar(s->ch);
s = s->next;
}
putchar('\n');
}
void LL_drop(LL_str *s){
if(s){
LL_drop(s->next);
free(s);
}
}
int main(int argc, char *argv[]){
LL_str *s = s_to_LL("Hello world!");
LL_str *d = LL_strcpy(s);
LL_println(d);
LL_drop(s);
LL_drop(d);
return 0;
}

if((NULL != dest_ptr) && (NULL != src_ptr)) --> this is correct
while (NULL != *src_ptr) --> this is wrong.
Please check the data type carefully. Don't mix up variable and pointer-to-variable

Related

Program sorts the data in the wrong way

I have to wirte a project for school, here is Program description
As can you see in the program description i have to sort the books by labels. Right now for some reason books that do not belong to specific label are printed under that label. For exemple Plato is printed under medival
I cannot find where did I made a mistake, I will be grateful for any help.
Here is my code:
#define _CRT_SECURE_NO_WARNINGS
#define _CRTDBG_MAP_ALLOC
#include <stdlib.h>
#include <crtdbg.h>
#include <stdio.h>
#include <string.h>
typedef struct BOOK Book;
struct BOOK
{
char *author;
char *title;
Book *next;
};
typedef struct LABEL Label;
struct LABEL
{
char *text;
Label *next;
Book *books;
};
void clear(Label** head);
void addLabel(Label **head, Label *elem);
void addBook(Book **head, Book **elem);
void readFromFile(char *fileName, char *outputFileName, Label *Ihead);
void saveBooks(FILE *file, Book *head);
void saveLabels(FILE *file, Label *Ihead);
void saveToFile(char *fileName, Label *Ihead);
void ComandConsole(int argc, char* argv[], int* fileinput, int* fileoutput);
Label* checkIfExists(Label **head, char *labelText);
Label* checkIfExists(Label **head, char *labelText)
{
Label *tmp = *head;
while (tmp != NULL)
{
if (strcmp(labelText, tmp->text) == 0)
return tmp;
tmp = tmp->next;
}
return NULL;
}
void addLabel(Label **head, Label *elem)
{
Label *temp = NULL;
if ((temp = checkIfExists(head, elem->text)) == NULL)
{
if (*head == NULL)
{
*head = elem;
return;
}
temp = *head;
while (temp->next != NULL)
temp = temp->next;
temp->next = elem;
}
else
addBook(&(temp->books), &(elem->books));
}
void addBook(Book **head, Book **elem)
{
Book *pom = *head;
if (strcmp(pom->author, (*elem)->author) > 0)
{
(*elem)->next = (*head)->next;
*head = *elem;
*elem = pom;
(*head)->next = *elem;
return;
}
while (pom->next != NULL && (strcmp((*elem)->author, pom->author) > 0))
pom = pom->next;
(*elem)->next = pom->next;
pom->next = *elem;
}
void readFromFile(char *fileName, char *outputFileName, Label *head)
{
FILE* input;
if ((input = fopen(fileName, "r")) == NULL)
{
printf("Reading failed!\n");
exit(1);
}
char buf[255];
while (fgets(buf, sizeof buf, input) != NULL)
{
Book *ksiazka = (Book*)malloc(sizeof(Book));
ksiazka->next = NULL;
char *store = strtok(buf, ";");
char * autor = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(autor, store);
ksiazka->author = autor;
store = strtok(NULL, ";");
char * tytul = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(tytul, store);
ksiazka->title = tytul;
store = strtok(NULL, "\n");
char * label = (char*)malloc(sizeof(char)*strlen(store) + 1);
strcpy(label, store);
char *tmp = strtok(label, ",\n");
while (tmp != NULL)
{
Label *newLabel = (Label*)malloc(sizeof(Label));
newLabel->books = NULL;
newLabel->next = NULL;
char *labelText = (char*)malloc(sizeof(char)*strlen(tmp) + 1);
strcpy(labelText, tmp);
newLabel->text = labelText;
newLabel->books = ksiazka;
addLabel(&head, newLabel);
tmp = strtok(NULL, ",\n");
}
}
saveToFile(outputFileName, head);
fclose(input);
}
void clear(Label** head)
{
while (*head != NULL)
{
Label* cur = *head;
*head = (*head)->next;
Book* a = cur->books;
while (a != NULL)
{
Book* b = a;
a = a->next;
free(b->author);
free(b->title);
free(b);
}
free(cur->text);
free(cur);
}
}
void saveBooks(FILE *file, Book *head)
{
Book *tmp = head;
while (tmp != NULL)
{
fprintf(file, "%s, %s\n", tmp->author, tmp->title);
tmp = tmp->next;
}
fprintf(file, "\n");
}
void saveLabels(FILE *file, Label *head)
{
Label *tmp = head;
while (tmp != NULL)
{
fprintf(file, "%s:\n", tmp->text);
if (tmp->books != NULL)
{
saveBooks(file, tmp->books);
}
tmp = tmp->next;
}
}
void saveToFile(char *fileName, Label *head)
{
FILE *output;
if ((output = fopen(fileName, "w")) == NULL)
{
printf("Writing failed!\n");
exit(1);
//clear(&head);
}
else
{
saveLabels(output, head);
}
//clear(&head);
fclose(output);
}
void ComandConsole(int argc, char* argv[], int* fileinput, int* fileoutput)
{
int i;
for (i = 1; i < argc; i++)
{
if (argv[i][0] == '-')
switch (argv[i][1])
{
case 'i':
{
i++;
if (i == argc) break;
*fileinput = i;
}
break;
case 'o':
{
i++;
if (i == argc) break;
*fileoutput = i;
}
break;
default:
{
printf("Wrong parameter");
} break;
}
}
}
int main(int argc, char* argv[])
{
int fileinputname = 0;
int fileoutputname = 0;
ComandConsole(argc, argv, &fileinputname, &fileoutputname);
if (fileinputname == 0 || fileoutputname == 0)
{
printf("Wrong parrametes");
getchar();
return 1;
}
Label *head = NULL;
readFromFile(argv[fileinputname], argv[fileoutputname], head);
_CrtDumpMemoryLeaks();
return 0;
}

Stack in C: why do i have memory leaks?

just revising C here. I just ran valgrind and it turns out i have memory leaks in my program, even though i free the memory i allocate. What am i missing?
stack.c:
#include <stdlib.h>
#include <stdio.h>
#include "stack.h"
struct node {
int element;
Node *next;
};
struct stack {
Node *tos;
};
Stack *stack_create() {
Stack *S;
if ((S = (Stack *)malloc(sizeof(Stack))) != NULL)
S->tos = NULL;
return S;
}
void stack_destroy(Stack *S) {
Node *temp = S->tos;
while (S->tos != NULL) {
temp = S->tos;
free(S->tos);
S->tos = temp->next;
}
free(S);
}
void push(Stack *S, int element) {
Node *N;
if ((N = (Node *)malloc(sizeof(Node))) != NULL) {
N->element = element;
N->next = (S->tos == NULL) ? NULL : S->tos;
S->tos = N;
}
}
int pop(Stack *S) {
Node *tos = S->tos;
S->tos = tos->next;
return (int) tos->element;
}
int peek(Stack *S) {
return (int) S->tos->element;
}
void to_string(Stack *S) {
Node *cursor = S->tos;
while (cursor != NULL) {
printf("[%d] ", cursor->element);
cursor = cursor->next;
}
printf("\n");
}
int main()
{
Stack *S;
S = stack_create();
push(S, 5);
push(S, 6);
push(S, 4);
push(S, -55);
to_string(S);
printf("Pop %d\n", pop(S));
printf("Pop %d\n", pop(S));
to_string(S);
stack_destroy(S);
return 0;
}
the actual problem is your Pop kills the node, but it doesn't free it
Node* node_destroy(Node* n)
Node* next;
if(n == NULL) return NULL;
next = n->next;
free(n);
return next;
}
int stack_pop(Stack *s) {
int element;
if(s == NULL || s->tos == NULL) return 0; // no really good result you can give
element = s->tos->element;
s->tos = node_destroy(s->tos);
return element;
}
then you can do
void stack_destroy(Stack *S) {
while (S->tos != NULL) {
s->tos = node_destroy(s->tos);
}
free(S);
}
The problem is in your destroy method. You free S->tos which temp refers to. Then you use temp->next.
set temp to S->tos->next.
The problem is with your destory:
void stack_destroy(Stack *S) {
Node *temp = S->tos;
while (S->tos != NULL) {
temp = S->tos;
free(S->tos);
S->tos = temp->next;
}
free(S);
}
Temp is pointing to S->tos from:
temp = S->tos;
But then you immediately free it after:
free(S->tos);
Then when you call the temp->next; temp is already freed.
Try this:
void stack_destroy(Stack *S) {
Node *temp; //Also, no need to assign here from the original (you assign to it immediately within the while)
while (S->tos != NULL) {
temp = S->tos->next; //You need to get the pointer to node "next" before you free S->tos
free(S->tos);
S->tos = temp;
}
free(S);
}
EDIT1: Per Keith Nicholas - See here for his elegant solution
Pop also does not free the node you extract the element from:
old:
int pop(Stack *S) {
Node *tos = S->tos;
S->tos = tos->next;
return (int) tos->element;
}
new:
int pop(Stack *S) {
Node *tos = S->tos;
int element = tos->element;
S->tos = tos->next;
free(tos);
return element;
}

pointer called by reference doesnt work

Hi i have a problem with the next code which i had posted before here, but yesterday i was working on my computer and all of the sudden the screen froze and when i restarted it my code was gone!! it was erased, so i had to start over. The code had to search a codop in a linked list, but it doesnt work, i keep getting the message "CODOP NOT FOUND", i thought that the problem was in the calling of pointers as pass by value, so i called it by reference but it doesnt work either, if someone could tell me how to solve it i would apreciate it a lot
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct node
{
char *instruction;
struct node *next;
}COD;
void printList(COD *head);
void SearchEndLine(FILE *hc12);
void listTABOP(COD **head);
COD *lastElement(COD **head);
COD *createNode(char *ins);
void insertEnd(char *ins,COD *last);
char *Operands_Table(FILE *hc12);
COD *searchCodop(COD *head,char *codop);
void Remove(char *c);
int main()
{
COD *head = NULL,*found = NULL;
char *codop = "BLE";
listTABOP(&head);
printList(head);
if((found = searchCodop(head,codop)) == NULL)
{
printf("CODOP NOT FOUND\n");
printf("%s\n",codop);
}
return 0;
}
void SearchEndLine(FILE *hc12)
{
int car;
while((car = fgetc(hc12))!= '\n')
;
}
void Remove(char *c)
{
char *ptr;
if(((ptr = strchr(c,'\n'))!= NULL)||((ptr = strchr(c,'\t'))!= NULL)||((ptr = strchr(c,' '))!= NULL))
*ptr = '\0';
}
void listTABOP(COD **head)
{
int car;
FILE *hc12;
COD *last = NULL;
char *ins;
if((hc12 = fopen("Tabla_OP.txt","r"))!= NULL)
{
while((car = fgetc(hc12))!= EOF)
{
if(car != '\t')
{
ins = Operands_Table(hc12);
if(*head == NULL)
*head = createNode(ins);
else
{
last = lastElement(head);
insertEnd(ins,last);
}
}
else
SearchEndLine(hc12);
}
}
else
printf("No se pudo abrir el archivo");
}
COD *lastElement(COD **head)
{
COD *ptr;
ptr = *head;
while(ptr->next != NULL)
ptr = ptr->next;
return ptr;
}
char *Operands_Table(FILE *hc12)
{
int car,lon = 0,pos;
char *c;
fseek(hc12,-1,SEEK_CUR);
pos = ftell(hc12);
do
{
car = fgetc(hc12);
lon++;
}while(car != '\t');
fseek(hc12,pos,SEEK_SET);
c = (char*)calloc((lon+1),sizeof(char));
fgets(c,lon+1,hc12);
Remove(c);
SearchEndLine(hc12);
return c;
}
COD *searchCodop(COD *head,char *codop)
{
COD *ptr;
for(ptr = head;ptr != NULL;ptr = ptr->next)
{
if(ptr->instruction == codop)
return ptr;
}
return NULL;
}
void insertEnd(char *ins,COD *last)
{
last->next = createNode(ins);
last->next->next = NULL;
last = last->next;
}
COD *createNode(char *ins)
{
int s;
COD *x;
x = (COD*)malloc(sizeof(COD));
s = strlen(ins);
x->instruction = (char*)malloc((s+1)*sizeof(char));
strcpy(x->instruction,ins);
x->next = NULL;
return x;
}
void printList(COD *head)
{
COD *ptr;
for(ptr = head;ptr != NULL;ptr = ptr->next)
printf("\n%s\n",ptr->instruction);
}
The problem is with this line:
if(ptr->instruction == codop)
it compares address of strings not strings themselves.
Use strcmp or something like that instead.

can´t find element on a linked list

I have the next code, first i create a list from a file named hc12,and then i search the codop = "BLE" that has to be found on the list, but instead i keep getting the message COULDNT FIND CODOP. i dont know why, the linked list works well.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct nodo
{
char *code;
struct nodo *next;
}COD;
COD *createNodo(char *instruction);
void insertEnd(char *instruction,COD *last);
COD *lastElement(COD *head);
void remove(char *c);
void searchEndofLine(FILE *fd);
void ignoreSpaces(FILE *fd);
void CodopsList(COD *head);
char *OperandsTable(FILE *hc12);
COD *searchCodop(COD *head,char *codop);
int main()
{
COD *head = NULL,*found;
char *codop = "BLE";
CodopsList(head);
if((found = searchCodop(head,codop)) == NULL)
printf("COULDNT FIND CODOP");
else
printf("CODOP FOUND");
return 0;
}
void searchEndofLine(FILE *fd)
{
int car;
while((car = fgetc(fd))!= '\n')
;
}
void ignoreSpaces(FILE *fd)
{
int car;
do
{
car = fgetc(fd);
}while(car == '\t' || car == ' ');
}
void remove(char *c)
{
char *ptr;
if(((ptr=strchr(c,'\n'))!=NULL)||((ptr=strchr(c,'\t'))!=NULL)||((ptr=strchr(c,' '))!=NULL))
*ptr = '\0';
}
void CodopsList(COD *head)
{
int car;
FILE *hc12;
char *instruction;
COD *last;
if((hc12 = fopen("TABOP.txt","r"))!= NULL)
{
while((car = fgetc(hc12))!= EOF)
{
if(car != '\t')
{
instruction = OperandsTable(hc12);
if(head == NULL)
head = createNodo(instruction);
else
{
last = lastElement(head);
insertEnd(instruction,last);
}
}
else
searchEndofLine(hc12);
}
}
else
printf("Error\n");
}
char *OperandsTable(FILE *hc12)
{
int car,lon = 0,pos;
char *c;
fseek(hc12,-1,SEEK_CUR);
pos = ftell(hc12);
do
{
car = fgetc(hc12);
lon++;
}while(car != '\t');
fseek(hc12,pos,SEEK_SET);
c = (char*)calloc((lon+1),sizeof(char));
fgets(c,lon+1,hc12);
remove(c);
searchEndofLine(hc12);
return c;
}
void insertEnd(char *instruction,COD *last)
{
last->next = createNodo(instruction);
last->next->next = NULL;
last = last->next;
}
COD *lastElement(COD *head)
{
COD *ptr;
ptr = head;
while(ptr->next != NULL)
ptr = ptr->next;
return ptr;
}
COD *createNodo(char *instruction)
{
COD *x;
int t;
t = strlen(instruction);
x = (COD*)malloc(sizeof(COD));
x->codigo = (char*)malloc((t+1)*sizeof(char));
strcpy(x->code,instruction);
x->next = NULL;
return x;
}
COD *searchCodop(COD *head,char *codop)
{
COD *ptr;
for(ptr = head;ptr != NULL;ptr = ptr->next)
{
if(ptr->code == codop)
return ptr;
}
return NULL;
}
You should use strcmp instead of comparing two array pointers.
In searchCodop instead of
if(ptr->code == codop)
do
if (!strcmp(ptr->code, codop))
You are calling pointer as pass by value, instead use call by reference. For this, use pointer to pointer. Like that:
In main change
CodopsList(head);
with
CodopsList(&head);
And,
Change function
void CodopsList(COD *head)
with
void CodopsList(COD **head)
In function CodopsList use head as *head

Pointers and cstring beginner troubles

I have a problem with the function replace. What I want to accomplish is to replace some special characters, but I haven't written the code yet. So in the replace function we can at this moment just say that the function should print line for line the way I have tried to write. Can someone please correct this function? I can’t really get it
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct list_el {
char *ord;
int num;
struct list_el *prev;
struct list_el *next;
};
typedef struct list_el item;
struct list_el *head, *tail; /*Double linked list that makes it easier to add a element to the end of the FIFO list*/
void addNode(struct list_el *curr);
void readFile();
void print();
void replace();
void random();
void len();
int antE = 0;
int randint(int max)
{
int a = (max*rand()/(RAND_MAX+1.0));
return a;
}
int main(int argc, char *argv[]) {
item *curr;
struct list_el *pa;
if(argc == 3) {
readFile();
}
if(argc == 1) {
printf("Too few arguments, must bee 3");
} else if(strcmp(argv[1], "print") == 0) {
print();
} else if(strcmp(argv[1], "random") == 0) {
random();
} else if(strcmp(argv[1], "replace") == 0) {
replace();
} else if(strcmp(argv[1], "remove") == 0) {
printf("Random kommando kalt");
} else if(strcmp(argv[1], "len") == 0) {
len();
} else {
printf("Not a valid command");
}
if(argc == 3) {
free(curr);
}
}
void addNode(struct list_el *curr) {
if(head == NULL) {
head = curr;
curr->prev = NULL;
} else {
tail->next = curr;
curr->prev = tail;
}
tail = curr;
curr->next = NULL;
}
void readFile()
{
FILE *f = fopen("tresmaa.txt", "r");
if(f == 0) {
printf("Could not open file");
exit(8);
}
item *curr;
if(f != NULL) {
int antE = 0;
head = NULL;
char buffer[300];
while(fgets(buffer, 300-1,f) != NULL) {
curr = (item*)malloc(sizeof(item));
curr->ord = malloc(300);
curr->num = antE;
strcpy(curr->ord, buffer);
antE++;
addNode(curr);
}
}
fclose(f);
}
/*Traverserer listen og printer ut linje for lije
*/
void print()
{
item *curr;
printf("Print text:\n");
for(curr = head; curr != NULL; curr = curr->next) {
printf("%s", curr->ord);
}
}
/*Printer ut en tilfeldig setning
*/
void random()
{
item *curr;
int anum = randint(antE);
for(curr = head; curr != NULL; curr = curr->next) {
if(curr->num == anum) {
printf("Print a random line:\n%s", curr->ord);
}
}
}
void replace()
{
item *curr;
int i;
char tmp[300];
printf("Replace vowels ...\n");
printf("... with vowel 'a'\n");
for(curr = head; curr != NULL; curr = curr->next) {
strcpy(tmp, curr->ord);
for(i = 0; i < strlen(tmp); i++) {
printf("%s", tmp[i]);
}
}
}
void len()
{
item *curr;
long nc;
int i;
nc = 0;
for(curr = head; curr != NULL; curr = curr->next) {
nc += strlen(curr->ord);
}
printf("The text is %d characters long", nc);
}
If you just want to print the lines you can do it without the copying and extra loop:
for(curr = head; curr != NULL; curr = curr->next) {
printf("%s\n", curr->ord);
}
Your current code doesn't work because you tell printf with the %s format that its argument will be a string (aka. a pointer to a zero-terminated sequence of characters), but then you give it a single character, not such a pointer.

Resources