Search for an element in a LinkedList - c

I'm currently creating a linked list of strings that user enters. As of right now I have my linked list working (I just have to free the memory). However, I'm trying to detect for commas in the user input. If there is a comma make the linked list print out a new line, and just ignore the commas.
Any advice?
For example:
Enter a string:
hello,world,how,are,you
The output is currently:
hello,world,how,are,you
The output should be:
hello
world
how
are
you
Here's my current code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
struct Word
{
char* data;
struct Word* next;
};
struct Word* ptr = NULL;
void insert(char c)
{
struct Word* temp = (struct Word*)malloc(sizeof(struct Word));
temp->data = c;
temp->next = NULL;
if (ptr) {
struct Word* temp1 = ptr;
while(temp1->next != NULL) {
temp1 = temp1->next;
}
temp1->next = temp;
} else {
ptr = temp;
}
}
void print() {
struct Word *temp;
temp = ptr;
while(temp != NULL) {
printf("%c", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(int argc, char *argv[])
{
int c;
printf("enter a string\n");
while (((c=getchar())!=EOF) && c!='\n') {
insert((char)c);
}
print(); /*print the list*/
return 0;
}

To print every word in the new line you just have to modify your print statement to check for , character in the linked list.
void print() {
struct Word *temp;
temp = ptr;
char c;
while(temp != NULL) {
if (temp->data == ',') {
printf("\n");
temp = temp->next;
} else {
printf("%c", temp->data);
temp = temp->next;
}
}
printf("\n");
}
This will check if there is a , in the linked list and print a \n to print newline character and move to the next node.
Also you should free your linked list after the program is complete to avoid memory leaks.
void freeData(struct Word* head)
{
struct Word* tmp;
while (head != NULL)
{
tmp = head;
head = head->next;
free(tmp);
}
}
Code link
Just try it out.

Related

Keep printing the last element in the linked list

I created a standard linked list in C. It asks the user to input a number, and program end if user input #. If the user inputs anything else the program will stop.
The problem is that my program runs forever and prints the normal list at first then keeping print the last element of the linked list.
Hope someone could tell me where did I made mistake.
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *list) {
NodeT *p, *temp;
p = list;
while (p != NULL) {
temp = p->next;
free(p);
p = temp;
}
}
void showLL(NodeT *list) {
NodeT *temp = list;
temp = temp->next;
printf("Done. The list is ");
printf("%d", temp->data);
temp = temp->next;
//iterate the entire linked list and print the data
while (temp != NULL) {
printf("-->");
printf("%d", temp->data);
temp = temp->next;
}
}
NodeT *joinLL(NodeT *list, int v) {
NodeT *current = list;
NodeT *head;
head->data = v;
head->next = NULL;
while (current->next != NULL) {
current = current->next;
}
current->next = head;
return head;
}
int main() {
int data;
NodeT *list = NULL;
list = (NodeT *)malloc(sizeof(NodeT));
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
} else {
printf("Enter a number: ");
joinLL(list, data);
while (1 == scanf("%d", &data)) {
printf("Enter a number: ");
joinLL(list, data);
}
showLL(list);
freeLL(list);
}
return 0;
}
I believe the problem is in the joinLL function which add a new node at the end of the linked list.
The problem is you do not allocate elements in joinLL: only a single element in allocated in main().
You should instead always allocate the element in joinLL and update the head pointer from the return value.
Similary, freeLL should take a pointer to head and set it to NULL for consistency.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} NodeT;
void freeLL(NodeT *p) {
while (p != NULL) {
NodeT *temp = p->next;
free(p);
p = temp;
}
}
void showLL(const NodeT *list) {
NodeT *p = list;
printf("The list is ");
if (p == NULL) {
printf("empty");
} else {
printf(" %d", temp->data);
while ((p = p->next) != NULL) {
printf("--> %d", temp->data);
}
}
printf("\n");
}
NodeT *joinLL(NodeT *head, int v) {
NodeT *newp = malloc(sizeof(*p));
NodeT *current;
if (newp == NULL) {
fprintf(stderr, "allocation failure\n");
exit(1);
}
newp->data = v;
newp->next = NULL;
if (head == NULL) {
return newp;
}
for (current = head; current->next != NULL; current = current->next)
continue;
current->next = newp;
return head;
}
int main() {
NodeT *list = NULL;
for (;;) {
int data;
printf("Enter a number: ");
if (scanf("%d", &data) != 1) {
printf("Done. ");
break;
}
list = joinLL(list, data);
}
showLL(list);
freeLL(list);
return 0;
}
Your program keeps running because of a memory access error, you did not allocate memory for your head(you set a pointer, but use it directly without initializing it)
Change to this may solve the problem:
head=(NodeT*)malloc(sizeof(NodeT));
if(NULL==head)
{
// failed : do something...
return NULL;
}
head->data=v;
head->next=NULL;
When I just tested it, I found that there was another problem:
list = (NodeT*)malloc(sizeof(NodeT));
malloc will not be initialize your list, so the value that your list->next initially points to is uncertain.
in c, malloc does not need to be cast.

I cannot create a linked list in C

Basically for my assignment I need to implement code to do Huffman coding. For that I need to take input as a string and then create a list of characters and their frequencies. I need to create a new node when there is a new character. I have tried doing it in C with no result. When I try to print my linked list I simply cannot get any output. I believe I have failed in creating the list from the start.
My C code is below:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
struct node {
char character;
int frequency;
struct node *next;
}head;
struct node *insert(int frequency, char character) {
struct node *newNode = malloc(sizeof(struct node));
newNode->character = frequency;
newNode->character = character;
return newNode;
}
void create_freq_list(struct node *initial, int str_size, char str[]) {
int i;
struct node *temp;
bool has_node;
for (i = 0; i < str_size; i++) {
temp = initial;
has_node = false;
while (temp->next != NULL) {
if (temp->character == str[i]) {
has_node = true;
temp->frequency++;
}
temp = temp->next;
}
if (has_node == false) {
while (temp->next != NULL) {
temp = temp->next;
if (temp->next == NULL) {
temp->next = insert(0, str[i]);
}
}
}
}
}
int main() {
struct node *temp;
char str[100];
gets_s(str, 100);
create_freq_list(&head, 100, str);
temp = &head;
while (temp->next != NULL) {
printf("'%c' : %d", temp->character, temp->frequency);
temp = temp->next;
}
getch();
exit(0);
}
There are multiple issues in your code:
Your handling of the head node is incorrect: head should be defined as a node * and you should pass its address to create_freq_list().
There is a typo in the insert() function: newNode->character = frequency;
You should not iterate on characters of the string beyond the null terminator.
The output loop is incorrect: it should iterate while (head), not while (head->next). As coded, the initial node is output but meaningless and the last node is ignored.
Here is a modified version:
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char character;
int frequency;
struct node *next;
};
struct node *insert(int frequency, char character) {
struct node *newNode = malloc(sizeof(struct node));
if (newNode != NULL) {
newNode->frequency = frequency;
newNode->character = character;
}
return newNode;
}
void create_freq_list(struct node **headp, const char str[]) {
for (int i = 0; str[i]; i++) {
struct node **tailp = *headp;
struct node *temp;
while ((temp = *tailp) != NULL) {
if (temp->character == str[i]) {
temp->frequency++;
break;
}
tailp = &temp->next;
}
if (temp == NULL) {
*tailp = insert(1, str[i]);
}
}
}
int main() {
struct node *head = NULL;
char str[100];
gets_s(str, 100);
create_freq_list(&head, str);
for (struct node *temp = head; temp != NULL; temp = temp->next) {
printf("'%c': %d\n", temp->character, temp->frequency);
}
getch();
return 0;
}
Note that it is much simpler to use an array with 256 elements to compute the character frequencies.
May I propose a variant, using macros of the excellent <sys/queue.h>
This is not a standard include, but every well packaged system should have it.
Well, it's probably less pedagogical than coding linked-list by hands, but it's more secure ;-)
Have a look at man queue (or man LIST_INIT) to see features.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/queue.h>
typedef LIST_HEAD(listhead, entry) nodes_t;
typedef struct entry {
char character;
int frequency;
LIST_ENTRY(entry) entries;
} node_t;
void insert(nodes_t *list, char character) {
node_t *newNode = malloc(sizeof(node_t));
if (newNode != NULL) {
newNode->frequency = 1;
newNode->character = character;
LIST_INSERT_HEAD(list, newNode, entries);
}
}
node_t *get_node(nodes_t *list, char character) {
node_t *n;
LIST_FOREACH(n, list, entries)
if (n->character == character)
return n;
return NULL;
}
void create_freq_list(nodes_t *list, const char str[]) {
node_t *n;
for (int i = 0; str[i]; i++) {
n = get_node(list, str[i]);
if (n == NULL)
insert(list, str[i]);
else
n->frequency++;
}
}
void print_list(nodes_t *list) {
node_t *n;
LIST_FOREACH(n, list, entries)
printf("'%c': %d\n", n->character, n->frequency);
}
int main(int argc, char* argv[]) {
nodes_t list;
if (argc != 2) {
fprintf(stderr, "Usage: %s <string>\n", argv[0]);
return -1;
}
LIST_INIT(&list);
create_freq_list(&list, argv[1]);
print_list(&list);
return 0;
}

Something wrong with strcmp?

My assignment is to read a file in to a linked list. The file contains a name and a letter indicating what to do with the name, either add or delete from list. The file is in this format:
Kathy a
Beverly a
Chuck a
Radell a
Gary a
Roger d
and so on...
The problem comes when i try to split up the name and the operation. The strcmp() doesn't even recognize the op_code variable in my code. I printed out both the name and the op_code and they print right unless i put a character near the op_code.
Here's my code:
//Tristan Shepherd
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node
{
char name[42];
struct node *next;
};
void printList(struct node *head)
{
struct node *current = head;
while (current)
{
printf("3 %s\n", current->name);
current = current->next;
}
}
void addFront(struct node **head, char *newname)
{
struct node* newnode = (struct node*)malloc(sizeof(struct node));
strcpy(newnode->name, newname);
newnode->next = (*head);
(*head) = newnode;
}
void delete(struct node **head, char *namedelete)
{
struct node* temp = *head, *prev;
if (temp != NULL && temp->name == namedelete)
{
*head = temp->next;
free(temp);
return;
}
while (temp != NULL && temp->name != namedelete)
{
prev = temp;
temp = temp->next;
}
if (temp == NULL) return;
prev->next = temp->next;
free(temp);
}
void readfile(struct node *head)
{
FILE *file = fopen("hw8.data", "r");
char tname[42];
char *tempname = (char*)malloc(42*sizeof(char));
char *op_code = (char*)malloc(1*sizeof(char));
while(fgets(tname, sizeof(tname), file))
{
tempname = strtok(tname, " ");
op_code = strtok(NULL, "\n");
printf("%s\n", tempname);
printf("%s\n", op_code);
if (!strcmp(op_code, "a"))
{
addFront(&head, tempname);
}
else if (!strcmp(op_code, "d"))
{
delete(&head, tempname);
}
}
fclose(file);
printList(head);
}
int main()
{
struct node *head = NULL;
readfile(head);
exit(0);
}
The only issue I see with in readFile() is a memory leak.
char *tempname = (char*)malloc(42*sizeof(char));
char *op_code = (char*)malloc(1*sizeof(char));
should just be
char *tempname;
char *op_code;
strtok() breaks up the string in place, it does not produce a copy of the string, so no need to allocate extra memory.
I do see some issues in delete() however
You should be using strcmp() here instead of ==, like you do in readfile()
if (temp != NULL && temp->name == namedelete)
while (temp != NULL && temp->name != namedelete)
You may also need to initialize prev.
With your code as-is, add seemed to be working fine, and with my changes, delete looks ok.

Doubly linked list delete last C

Im working on a implementation of a doubly linked list. I want the linked list to be limited by some length. When the list becomes longer then delete the last node. Im having some problems here. I want to define tail so that i dont have to search for the end. Here is the implementation i am working on it will allow for a length of 4 then start deleting the last node.
/* Doubly Linked List implementation */
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
struct Node {
char command[1024];
struct Node* next;
struct Node* prev;
};
struct Node* head; //global pointing to head
struct Node* tail; //global pointing to tail
//Creates a new Node and returns pointer to it.
struct Node* GetNewNode(char *line) {
struct Node* newCommand = (struct Node*)malloc(sizeof(struct Node));
int i = 0;
while(line[i] != '\0'){
newCommand->command[i] = line[i];
i++;
}
newCommand->prev = NULL;
newCommand->next = NULL;
return newCommand;
}
//Inserts a Node at head of doubly linked list
void InsertAtHead(char *line) {
struct Node* newCommand = GetNewNode(line);
if(head == NULL) {
head = newCommand;
tail = newCommand;
return;
}
head->prev = newCommand;
newCommand->next = head;
head = newCommand;
}
//Use tail to delete the last node
void deleteLast(){
struct Node* temp = tail;
tail = temp->prev;
free(tail->next);
tail->next = NULL;
}
//Print in reverse orer
void Print() {
struct Node* temp = tail;
while(temp != NULL) {
printf("%s \n",temp->command);
temp = temp->prev;
}
}
int main() {
int numNodes = 0;
char line[1024];
head = NULL;
tail = NULL; // empty list. set head/tail as NULL.
printf("next node: ");
while (fgets(line, 1024, stdin)) {
line[strlen(line)-1] = '\0';
if(numNodes == 4){
numNodes -= 1;
deleteLast();
}
InsertAtHead(line);Print();
numNodes += 1;
printf("next node: ");
}
Print();
}
it seems to be deleting the last node but printing some weird symbols after. Im guessing that its a problem with how i free() but i cant figure it out.
note some of this code is taken from https://gist.github.com/mycodeschool/7429492
Your code looks fine, hoewever, there is an error in copying the command to the node:
while(line[i] != '\0'){
newCommand->command[i] = line[i];
i++;
}
should be:
while(line[i] != '\0'){
newCommand->command[i] = line[i];
i++;
}
newCommand->command[i] = '\0';
(You forgot to terminate the copied command.)
Note also that you must check not to go beyond available space, e.g.:
while(i<1023 && line[i] != '\0'){
newCommand->command[i] = line[i];
i++;
}
newCommand->command[i] = '\0';

Printing strings in linked lists

So I'm having trouble getting my program to print both the strings I input, or however many you want to put in the list, it always prints out the last string inputted multiple times. I am sorry about all the commented out code, most of it you don't need to read.
#include<stdio.h>
#include<stdlib.h>
struct node{
char *data;
struct node *next;
}*head;
typedef struct node NODE;
// Function prototypes
void append(char myStr[]);
void add( char myStr[] );
//void addafter(char myStr[], int loc);
void insert(char myStr[]);
int delete(char myStr[]);
void display(struct node *r);
int count();
// main function
int main()
{
int i;
struct node *n;
head = NULL;
char myStr[50];
while(1)
{
printf("\nList Operations\n");
printf("===============\n");
printf("1.Insert\n");
printf("2.Display\n");
printf("3.Size\n");
printf("4.Delete\n");
printf("5.Exit\n");
printf("Enter your choice : ");
if(scanf("%d", &i) <= 0)
{
printf("Enter only an Integer\n");
exit(0);
}
else
{
switch(i)
{
case 1:
printf("Enter the name to insert : ");
scanf("%50s", myStr);
insert(myStr);
break;
case 2:
if(head == NULL)
{
printf("List is Empty\n");
}
else
{
printf("Name(s) in the list are : ");
}
display(n);
break;
case 3:
printf("Size of the list is %d\n",count());
break;
case 4:
if(head == NULL)
printf("List is Empty\n");
else
{
printf("Enter the myStrber to delete : ");
scanf("%50s",myStr);
if(delete(myStr))
printf("%s deleted successfully\n",myStr);
else
printf("%s not found in the list\n",myStr);
}
break;
case 5:
return 0;
default:
printf("Invalid option\n");
}
}
}
return 0;
}
// Function definitions
void append(char myStr[])
{
struct node *temp,*right;
temp = (struct node *)malloc(sizeof(struct node));
temp->data = myStr;
right=(struct node *)head;
while(right->next != NULL)
{
right = right->next;
}
right->next = temp;
right = temp;
right->next = NULL;
}
// adding a node to the beginning of the linked list
void add( char myStr[] )
{
struct node *temp;
temp =(struct node *)malloc(sizeof(struct node));
temp->data = myStr;
// only one node on the linked list
if (head == NULL)
{
head = temp;
head->next = NULL;
}
else
{
temp->next = head;
head = temp;
}
}
void insert(char myStr[])
{
int c = 0;
struct node *temp;
temp = head;
if(temp == NULL)
{
add(myStr);
}
else
{
append(myStr);
}
}
int delete(char myStr[])
{
struct node *temp, *prev;
temp = head;
while(temp != NULL)
{
if(temp->data == myStr)
{
if(temp == head)
{
head = temp->next;
head = (*temp).next;
free(temp);
return 1;
}
else
{
prev->next = temp->next;
free(temp);
return 1;
}
}
else
{
prev = temp;
temp = temp->next;
}
}
return 0;
}
void display(struct node *r)
{
r = head;
if(r == NULL)
{
return;
}
while(r != NULL)
{
printf("%s ", r->data);
r = r->next;
if(r == NULL)
{
printf("\nOur linked list is finished!");
}
}
printf("\n");
}
int count()
{
struct node *n;
int c = 0;
n = head;
while(n != NULL)
{
n = n->next;
c++;
}
return c;
}
The problem seems to be that myStr at main function is a char[], so it's content is overritten every time you insert data. Notice that struct node data field is a char*, it's just pointing to myStr address.
Hope this help!
Your program has only one place to write your input, myStr.
With each input, myStr is erased and a something else is written to myStr.
The data member of all of the nodes, points to myStr. myStr will only contain the last input.
The display() function asks each node what is data. data points to myStr so each node prints the contents of myStr. myStr will only contain the last input so all the nodes print the last input.
To fix this, in the add() and append() functions, you need to give the data member some memory by using malloc(). Then copy the contents of myStr to the data member by using strcpy().
temp->data = malloc ( strlen ( myStr) + 1);
strcpy ( temp->data, myStr);
Do this instead of temp->data = myStr;
You will need #include<string.h>
The memory will need to be free()'d in the delete() function.
free(temp->data);
Do this before freeing temp
char *data
that variable from struct is always assigned with the address of myStr as its a pointer it would only show you the value of myStr

Resources