Linked Lists and binary data in C - c

I'm trying to write a simple C code for the following function:
Given an encoding for the letters a-d:
'a'->00, 'b'->01, 'c'->10, 'd'->11,
and a node in a linked-list defined as:
typedef struct listNode{
unsigned char data;
struct listNode* next;
}ListNode;
typedef struct list{
ListNode* head;
ListNode* tail;
}List;
where head points to the first node of the list, and the tail to the last one.
I need to write a function char* SumList(List arr[], int n), which returns a string which contains all the encoded letters in all the nodes of all lists in arr in row.
This is what I wrote so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int isBitISet(char, int);
typedef struct listNode {
unsigned char data;
struct listNode* next;
} ListNode;
typedef struct list {
ListNode* head;
ListNode* tail;
} List;
int isBitISet(char ch, int i) {
char mask;
mask=1<<i;
return (mask & ch);
}
int totalNodes(List arr[], int n) {
int i;
int counter=0;
for (i=0; i<n; ++i) {
ListNode* head= arr[i].head;
while (head!=NULL) {
counter++;
head=head->next;
}
}
return counter;
}
char* whatToadd(char data) {
int a, b;
a=isBitISet(data, 0);
b=isBitISet(data, 1);
char* result;
result=(char *) calloc(2, sizeof(char));
if ((a!=0) && (b!=0))
result="d";
else if ((a!=0) && (b==0))
result="b";
else if ((a==0) && (b!=0))
result="c";
else
result="a";
return result;
}
char* SumLists(List arr[], int n) {
char* final;
int nodes=totalNodes(arr, n);
final= (char*) calloc(nodes, sizeof(char)); //how would I know the final length?//
int i;
for (i=0; i<n; ++i) {
ListNode* head= (arr[i].head);
while (head!=NULL) { //Why do I need a tail?//
char* result;
result=whatToadd(((head->data)&(00000011)));
strcat(final, result);
free(result);
result=whatToadd(((head->data)&(00001100))>>2);
strcat(final, result);
free(result);
result =whatToadd(((head->data)&(00110000))>>4);
strcat(final,result);
free(result);
result=whatToadd(((head->data)&(11000000))>>6);
strcat(final,result);
free(result);
head=head->next;
}
}
return final;
}
int main() {
.....
free(final);
...
}
Probably, Tail has given from some reason- but (1)- can't I run on the lists the way I did? without using the tail? and if not, how should I use it?
(2)- Do I need to free result the way I did each time I get a new result from whatToAdd?
I'm new to C, trying to work it by myself, I would really appricate tips and corrections. Thanks a lot.

Do I need to free result the way I did each time I get a new result from whatToAdd?
No, as the address of a string literal is being returned. Don't calloc() memory for result as it is unrequired. Change the return value of whatToadd() to const char*, as string literals are read-only.
Just to clarify, the following does not copy "d" into result:
result="d";
but instead makes result point to the address of the string literal "a": it is a pointer assignment. If you wanted to copy into result you could do either:
strcpy(result, "d");
*result = 'd'; *(result + 1) = 0;
in which case you would free() the returned pointer.
Only pass a pointer to free() if it is the result of a previous call to calloc(), malloc() or realloc() and has not already been free()d.

Related

How to swap char value of nodes of linkedlist in C?

I am trying to bubble sort linkedlist based on int value which I hold in char array.
I know that I need to do following steps;
void bubbleSort(struct Node *start)
{
int swapped, i;
struct Node *ptr1;
struct Node *lptr = NULL;
/* Checking for empty list */
if (start == NULL)
return;
do
{
swapped = 0;
ptr1 = start;
while (ptr1->next != lptr)
{
if (ptr1->data > ptr1->next->data)
{
swap(ptr1, ptr1->next);
swapped = 1;
}
ptr1 = ptr1->next;
}
lptr = ptr1;
}
while (swapped);
}
and
/* function to swap data of two nodes a and b*/
{
int temp = a->data;
a->data = b->data;
b->data = temp;
}
but as I said above I have created a struct with char value;
struct nodeForLinkedList
{
char frequency[STRING_LEN]; **// Purpose of this is to hold int value from text file.**
struct nodeForLinkedList *next;
};
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp = a->frequency;
a->frequency = b->frequency; // atoi(b->frequency) or strtol
b->frequency = temp;
}
here I could use atoi function to get int value from char array. atoi function help me to get int value from 'frequency' array
But I don't know how to change a->frequency value with b->frequency value.
Any help would be appreciated
Thanks in advance
The simplest solution is to use one of the string or memory copying functions from the library:
#include <string.h>
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp[sizeof(a->frequency)];
strcpy(temp, a->frequency);
strcpy(a->frequency, b->frequency);
strcpy(b->frequency, temp);
}
The above use of strcpy assumes that the frequency member contains a null-terminated string. You could use memcpy to copy the whole array regardless of null-termination:
#include <string.h>
void swap(struct nodeForLinkedList *a, struct nodeForLinkedList *b)
{
char temp[sizeof(a->frequency)];
memcpy(temp, a->frequency, sizeof(temp));
memcpy(a->frequency, b->frequency, sizeof(temp));
memcpy(b->frequency, temp, sizeof(temp));
}

Link Lists and Freeing Memory in C

I was trying to make a simple Link List struct but for some reason when I tested freeing up the data in the LL it would give me an invalid pointer error. Can anyone explain why?
#include <stdio.h>
#include <stdlib.h>
void add();
typedef struct node{
char* data;
struct node* next;
} node;
node** n;
int main(int argv, char** argc){
n = (node**)malloc(sizeof(node*)*10);
int i;
for(i = 0; i < 10; i++){
n[i] = NULL;
}
add();
free(n[0]->data);
return 0;
}
void add(){
char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
n[0] = (node*)malloc(sizeof(node));
n[0]->data = temp;
}
char* temp = (char*)malloc(sizeof(char)*4);
temp = "Meh\0";
Your assignment to temp is the culprit, as that sets it to point to the static character string "Meh\0", which it not yours to free. Your malloc has no effect in this case, as you immediately replace it to point to static data instead. Use memcpy or similar if you want to copy the data into the memory allocated by malloc.

Segmentation Fault (singal 11 sigsegv) with linked list

Was writing a program to practice before with linked lists and pointers before pset5 and am left with two memory errors that i have not been able to remedy.
#include <stdio.h>
#include <stdlib.h>
//define struct for Nodes
typedef struct list
{
int data;
int key;
struct list* next;
}Node;
//function declarations
Node* create(int a, int *counter);
void insert(int a, int *counter);
void delete_list();
void printlist();
//global pointers
Node* Head = NULL;
Node* Current = NULL;
int main()
{
int *keycounter =(int*)malloc(sizeof(int));
int value = 20;
keycounter = 0;
Head=create(value, keycounter);
value = 30;
insert(value, keycounter);
value = 40;
insert(value, keycounter);
printlist();
delete_list();
free(keycounter);
return 0;
}
// VV functions VV
void delete_list()
{
free(Head);
free(Current);
}
Node* create(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr)
{
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
return 0;
}
ptr->data=a;
ptr->key=*counter;
counter++;
return ptr;
}
void insert(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr) {
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
}
ptr->data=a;
ptr->key=*counter;
//point next field to old head
ptr->next=Head;
//assign current node as head of singly linked list
Head=ptr;
counter++;
}
//Thank you guys over at tutorialspoint for this neat idea for testing this.
//https://www.tutorialspoint.com/data_structures_algorithms/linked_list_program_in_c.htm
void printlist()
{
Node* ptr=Head;
printf("TESTING\n");
while(ptr != NULL) {
printf("%p*NODE* KEY:%i VALUE:%i PTR NEXT:%p\n \n", ptr, ptr->key, ptr->data, ptr->next);
ptr=ptr->next;
}
}
Here is my valgrind output:
Still learning so alot of the valgrind output is pretty arcane to me and threads on stack exchange regarding the "signal 11 (SIGSEGV)" error are difficult to comprehend as well.
Also, any tips or advice on my code would be appreciated.
There is a problem in your code. See the below lines:
int main()
{
int *keycounter =(int*)malloc(sizeof(int));
int value = 20;
keycounter = 0; ===> You are setting the pointer to NULL effectively nullifying the effect of your malloc call above
So, in your create function, when you try to access counter, it is leading to NULL pointer dereference
Node* create(int a, int *counter)
{
Node* ptr=malloc(sizeof(Node));
if(!ptr)
{
printf("ERROR-NOT ENOUGH MEMORY\n");
free(ptr);
return 0;
}
ptr->data=a;
ptr->key=*counter; ==> Here it will lead to NULL pointer dereference
If your key member in the struct is just an integer, then no need to pass a pointer (counter is a pointer), you can as well pass an integer and set it.

storing an array as a linked list in C

I'm working in C and am having some trouble. I need to store an array of chars (string) across a linked list. In other words, convert a string to a linked list. Basically, one character per node. For example string, dog\0, rather then storing a null character in the last node it would just point to a null pointer to signify the end of the string…… d->o->g->NULL
An suggestions would be great, thank you
int main(){
char *string;
string = malloc(sizeof(char)*100);
strcpy(string,"cheese");
node *list = NULL;
list = createNode(string[0]);
int i;
for(i=1;i<strlen(string);i++){
// this is where I'm stuck, the first char 'c'is in,
// I'm guessing i wanna loop through and
// store each char in a new node ?
}
return 0;
}
node *createNode(char data){
node *ptr = malloc(sizeof(node));
if (ptr == NULL)
{
return NULL;
}
ptr->data = data;
ptr->next = NULL;
return ptr;
}
Here is how to do this in C:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
node *next;
char data;
};
node *createNode(char data, node *parent) {
node *ptr=(node*)malloc(sizeof(node));
if(ptr==NULL) {
fprintf(stderr, "Memory allocation error.\n");
exit(1);
}
if(parent!=NULL) parent->next=ptr;
ptr->data=data;
ptr->next=NULL;
return ptr;
}
int main() {
char str[]="cheese";
// Store the string to the list
node *first=NULL, *cur=NULL;
for(int i=0, len=strlen(str); i<len; i++) {
cur=createNode(str[i],cur);
if(first==NULL) first=cur;
}
// Now print it out
cur=first;
while(cur!=NULL) {
printf("%c\n", cur->data);
cur=cur->next;
}
_getwch();
return 0;
}
If C++ is OK then here is a working sample:
#include <iostream>
#include <list>
using namespace std;
int main() {
char str[]="cheese", chr;
// Store the string in the list
std::list<char> clist;
for (int i=0, len=strlen(str); i<len; i++)
clist.push_back(str[i]);
clist.push_back('\0');
// Display the list
do {
chr=clist.front();
cout<<chr<<endl;
clist.pop_front();
} while(chr);
_getwch();
return 0;
}

Pointer trouble creating binary trees

I am creating a binary tree from a bitstring in c. ie 1100100 creates a tree:
1
/ \
1 1
I decided to use a recursive function to build this tree however i keep getting the error
Debug assertion failed...
Expression : CrtIsValidHeapPointer(pUserData)
here is a fragment of my code
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
char string[1000];
int i = 0;
void insertRecursivePreorder(Node **node)
{
Node* parent = *node;
if(string[i] == '0')
{
parent = NULL;
i++;
}
else
{
Node *newn = (Node*)malloc(sizeof(Node));
newn->key = string[i];
parent = newn;
i++;
insertRecursivePreorder(&newn->left); //errors occur here
insertRecursivePreorder(&newn->right); //errors occur here
free(newn);
free(parent);
}
}
int main(void)
{
void printTree(Node* node);
Node* root = NULL;
scanf("%s", string);
insertRecursivePreorder(&root);
//... do other junk
}
i was wondering why this error comes about and what i can do to fix it.
The immediate problem is likely to be calling free on a pointer twice. In insertRecursivePreorder, you set parent to newn, and then call free on both. As an example of this, the following program fails (but works if you comment out one of the free(..)s):
#include <stdlib.h>
int main() {
int *a = malloc(sizeof(int)),
*b = a;
free(a);
free(b);
return 0;
}
However, there are several problems with your logic here. You should only call free when you have completely finished with the pointer, so if you are using your tree later you can't free it as you construct it. You should create a second function, recursiveDestroyTree, that goes through and calls free on the tree (from the bottom up!).
And, you probably want *node = newn rather than parent = newn, since the latter is the only one that actually modifies node.
(You could also change your function to return a Node * pointer, and then just go:
root = insertRecursivePreorder();
and
newn->left = insertRecursivePreorder();
newn->right = insertRecursivePreorder();
instead of trying to keep track of pointers to pointers etc.)
(Furthermore, on a stylistic point, using global variables is often bad practice, so you could have your insertRecursivePreorder take int i and char * string parameters and use them instead of global variables.)
The problem was: you were never assigning to the double pointer in 'insertRecursivePreorder', so root always stayed NULL.
#include <stdio.h>
#include <stdlib.h>
typedef
struct Node {
char key;
struct Node *left;
struct Node *right;
} Node;
/* slightly changed the syntax for the str
** ; now '.' indicates a NULL pointer, values represent themselves.
*/
char *string = "12..3.." ;
/* Removed the global index 'i' */
void printTree(Node* node, int level);
unsigned insertRecursivePreorder(Node **pp, char *str);
unsigned insertRecursivePreorder(Node **pp, char *str)
{
unsigned pos =1;
if (!*str) { *pp = NULL; return 0; } /* safeguard for end of string */
if (*str == '.') { *pp = NULL; return pos; }
*pp = malloc(sizeof **pp);
(*pp)->key = *str;
pos += insertRecursivePreorder(&(*pp)->left, str+pos);
pos += insertRecursivePreorder(&(*pp)->right, str+pos);
return pos;
}
void printTree(Node* node, int level)
{
unsigned pos,len;
len = level> 0 ? level : -level;
for (pos =0; pos < len; pos++) putchar (' ');
if (!level) printf ("Root=");
else if (level<0) printf ("Left=");
else printf ("Right=");
if (!node) { printf( "Null\n" ); return; }
printf("Key=%c\n", node->key );
printTree(node->left, -(len+1) ) ;
printTree(node->right, len+1) ;
}
int main(void)
{
Node *root = NULL;
unsigned result = 0;
result = insertRecursivePreorder(&root, string);
printf( "Result=%u\n", result);
printTree(root, 0);
return 0; printTree(root, 0);
}
Output:
Result=7
Root=Key=1
Left=Key=2
Left=Null
Right=Null
Right=Key=3
Left=Null
Right=Null

Resources