A linked list to alphabetize strings - c

In the lab work I am doing, it is supposed to allow a user to input strings into a linked list one by one until the user doesn't input a string. At this point the program will then compare each string by the first letter, alphabetize them, and then display them.
I know I have to use strcmp to compare two strings at a time, I've tried to understand this but it is just so complicated.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define StringLengthMAX 80
struct node_link
{
//char node_string[StringLengthMAX];
int num;
struct node_link *next;
};
int compare_node(struct node_link *b1, struct node_link *b2)
{
//strcmp(*b1, *b2);
if (b1 -> num < b2 -> num)
{
return -1;
}
if (b1 -> num == b2 -> num)
{
return 0;
}
if (b1 -> num > b2 -> num)
{
return 1;
}
}
struct node_link *add_node(struct node_link *list, struct node_link *node)
{
struct node_link *cur_node=list;
//case 1 : When list->num > node->num
if (compare_node(list, node) == 1)
{
node -> next = list;
list = node;
return list;
}
// case 2
while(cur_node->next != NULL)
{
if (compare_node(cur_node->next,node) == 1)
{
node -> next = cur_node -> next;
cur_node->next = node;
break;
}
else
{
cur_node = cur_node -> next;
}
}
// case 3 : node->next is the greatest
if (cur_node -> next == NULL)
{
cur_node->next = node;
}
return list;
}
void display_newlist(struct node_link *head)
{
struct node_link *node=head;
while(node != NULL)
{
printf("%d", node->num);
node = node->next;
printf(" ");
}
}
int main()
{
int a;
struct node_link *head;
struct node_link *node;
node = (struct node_link*)malloc(sizeof(struct node_link));
node->num = a;
node->next = NULL;
head = node;
do
{
puts("Please enter any number of integers, end inputs with a ZERO (0): ");
scanf("%d", &a);
node = (struct node_link*)malloc(sizeof(struct node_link));
node->num = a;
node->next = NULL;
head = add_node(head,node);
}while(a != 0);
display_newlist(head);
return 0;
}

You can do that by this way
1- Replace that int num with any array of character
2- in compare function try to compare elements of the char array using strcmp function then return values according to that from compare() function.
3- Replace evry num by array of character variable

Related

C - How to print a string element in a pointer to struct?

I'm relearning linked list data structure and I stumbled upon this problem.
#include <stdlib.h>
#include <stdio.h>
struct Node{
char url[50];
struct Node *next;
};
typedef struct Node Node;
void add_url(Node * h, Node * c, Node * n){
Node * temp;
temp = malloc(sizeof(Node));
printf("\nType or paste your URL: ");
scanf("%s", temp->url);
if(h == NULL){
h = temp;
h->next = NULL;
c = h;
}else{
c->next = temp;
c = c->next;
n = c->next;
}
}
int main(){
Node * h = NULL; // head
Node * c; // current
Node * n; // next
add_url(h, c, n);
printf("%s", h->url);
return 0;
}
Why is the output NULL? How exactly do you get a string input from a pointer to struct?
Here is a possible solution. I have added some checks to avoid segmentation fault (access violation), buffer overflow in scanf, initialized variables and the function now returns the new head (Could instead return current node).
#include <stdlib.h>
#include <stdio.h>
struct Node {
char url[50];
struct Node* next;
};
typedef struct Node Node;
Node *add_url(Node** h, Node** c, Node** n) {
Node* temp;
if ((h == NULL) || (c == NULL) || (n == NULL))
return NULL;
if ((temp = malloc(sizeof(Node))) == NULL)
return NULL;
printf("\nType or paste your URL: ");
if (scanf("%50s", temp->url) != 1)
return NULL;
if (*h == NULL) {
temp->next = NULL;
*h = temp;
*c = *h;
}
else {
(*c)->next = temp;
*c = temp;
*n = temp;
}
return *h;
}
int main() {
Node* h = NULL; // head
Node* c = NULL; // current
Node* n = NULL; // next
if (add_url(&h, &c, &n) == NULL) {
perror("add_url failed: ");
return 1;
}
printf("%s", h->url);
return 0;
}

Reversing an array of linked list recursively isn't reversing all nodes in order

I have an array of linked list which I am trying to reverse recursively. When I call the function to reverse it will not reverse all of the nodes but rather a couple of the nodes.
The reverse function appears to be deleting the first node (base case) and filling its spot with the last node (end of sub case). I think that the problem lies in the calling of the for loop within the reverse_nodes function however that doesn't seem to fix it.
Here is some output..
pre-reverse function:
-----
group 0
alice, 2
-----
group 1
martin, 4
-----
group 2
keanu, 6
-----
group 3
miles, 8
post - reverse function
-----
group 0
miles, 8
-----
group 1
martin, 4
-----
group 2
keanu, 6
-----
group 3
miles, 8
I am trying to get it to reverse to that it reads: 8,6,4,2
Please note I have only included relevant code blocks such as the struct architecture, the head/tail construction, the deletion of all nodes prior to reading in the binary file, reading binary file to nodes, and the main function. Can I get some help figuring out what in the reverse function is causing it to not completely reverse? Thank for your time. See code below!
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
char name[20];
int size;
struct node *next;
}node;
node* head[4]={NULL,NULL,NULL,NULL};
node* tail[4]={NULL,NULL,NULL,NULL};
void wipe_nodes()
{
int i;
node *p=NULL;
for(i=4; i>0; i--)
{
p=head[i];
if(p == NULL)
{
printf("Nodes are clear!\n");
}
while(p != NULL)
{
delete_party(p->name, p->size); // cant call name and size
p = p -> next;
}
}
}
void bin_to_list(char *filename)
{
FILE *fp;
int ret;
fp = fopen(filename, "rb");
if (fp == NULL)
{
printf("Null file!\n");
return;
}
node temp;
//temp = (node *)malloc(sizeof(node));
while((ret = fread(&temp, sizeof(node), 1, fp) > 0))
{
printf("%s %d", temp.name, temp.size);
if(temp.size == 0)
{
printf("\nThat is not a valid command. Party not added!\n");
}
if(temp.size >= 1 && temp.size <= 2)
{
add_party(0, temp.name, temp.size);
}
else if(temp.size >= 3 && temp.size <= 4)
{
add_party(1, temp.name, temp.size);
}
else if(temp.size >= 5 && temp.size <= 6)
{
add_party(2, temp.name, temp.size);
}
else if(temp.size >= 7)
{
add_party(3, temp.name, temp.size);
}
}
fclose(fp);
return;
}
void reverse_nodes(node *p, node *q)
{
int i;
for(i=0; i<4; i++)
{
//node *p=head[i];
if(p == NULL)
{
printf("Error, no nodes!\n");
return;
}
if (p->next == NULL)
{
printf("LOL, only one node! Can't reverse!\n");
head[i] = p;
}
else
{
reverse_nodes(p->next, p);
}
p->next = q;
return;
int main(int argc, char *argv[])
{
int x, i;
read_to_list(argv[1]);
bin_to_list(argv[2]);
while (1)
{
fflush(stdin);
printf("\n\nEnter 1 to add a party\nEnter 2 to remove a party\nEnter 3 for the list of the party\nEnter 4 to change party size.\nEnter 5 to quit (write to .txt file).\nEnter 6 to read from bin file.\nEnter 7 to reverse the list.\n\n");
scanf("%d",&x);
char name[20];
int size;
switch(x)
{
case 1:
printf("\nParty Name: ");
scanf("%s", name);
printf("\nParty Size: ");
scanf("%d", &size);
if(size == 0)
{
printf("\nThat is not a valid command. Party not added!\n");
}
if(size >= 1 && size <= 2)
{
add_party(0, name, size);
}
else if(size >= 3 && size <= 4)
{
add_party(1, name, size);
}
else if(size >= 5 && size <= 6)
{
add_party(2, name, size);
}
else if(size >= 7)
{
add_party(3, name, size);
}
break;
case 2:
printf("\nSize of party to delete: ");
scanf("%i", &size);
delete_party(NULL, size);
break;
case 3:
list_parties();
break;
case 4:
change_partysize(name, size);
break;
case 5:
write_to_file(argv[1]);
write_to_bin(argv[2]);
exit(0);
break;
case 6:
wipe_nodes();
bin_to_list(argv[2]);
break;
case 7:
for(i=0; i<4; i++)
{
reverse_nodes(head[i], NULL);
}
break;
default:
continue;
}
}
}
#include<stdio.h>
#include<stdlib.h>
/* Link list node */
struct Node
{
int data;
struct Node* next;
};
/* Function to reverse the linked list */
static void reverse(struct Node** head_ref)
{
struct Node* prev = NULL;
struct Node* current = *head_ref;
struct Node* next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*head_ref = prev;
}
/* Function to push a node */
void push(struct Node** head_ref, int new_data)
{
/* allocate node */
struct Node* new_node =
(struct Node*) malloc(sizeof(struct Node));
/* put in the data */
new_node->data = new_data;
/* link the old list off the new node */
new_node->next = (*head_ref);
/* move the head to point to the new node */
(*head_ref) = new_node;
}
/* Function to print linked list */
void printList(struct Node *head)
{
struct Node *temp = head;
while(temp != NULL)
{
printf("%d ", temp->data);
temp = temp->next;
}
}
/* Driver program to test above function*/
int main()
{
/* Start with the empty list */
struct Node* head = NULL;
push(&head, 20);
push(&head, 4);
push(&head, 15);
push(&head, 85);
printf("Given linked list\n");
printList(head);
reverse(&head);
printf("\nReversed Linked list \n");
printList(head);
getchar();
}
Your reverse_nodes function is just setting the next member of the node, not the current node, so when it gets to the end of the list, it will set the next of the last member to the previous member in the linked list but leave the last member untouched.
This worked for me:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct node
{
char name[20];
int size;
struct node *next;
}node;
node* head;
void reverse_nodes(node ** pphead)
{
node *prev = NULL;
node *current = *pphead;
node *next;
while (current != NULL)
{
next = current->next;
current->next = prev;
prev = current;
current = next;
}
*pphead = prev;
}
void main(void)
{
int i;
node * phead;
head = phead = (node *)malloc(sizeof(node));
phead->size = 0;
for (i = 0; i < 4; i++)
{
node * p;
phead->next = (node *)malloc(sizeof(node));
phead = phead->next;
phead->size = i + 1;
phead->next = NULL;
}
reverse_nodes(&head);
phead = head;
while (phead)
{
printf("%d\r\n", phead->size);
phead = phead->next;
}
}
Edit:
Recursion is usually a bad idea as you could end up blowing the stack - it's always best to try and do what you need to do in a single (or multiple if required) function(s) if possible, which in this case is easily possible.

printing the nodes in linked list in c

here is a program which inserting 2 names 2 paths and 2 duration s into linked list (struct of linked lists) , printing them and swapping between them when the duration of the first node is 8.
but when the program printing the nodes its prints from all of the nodes the name and the path of the last node
please help me
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Frame
{
char *name;
unsigned int duration;
char *path; // may change to FILE*
}*n3;
typedef struct Frame frame_t;
struct Link
{
frame_t *frame;
struct Link *next;
}*n ;
typedef struct Link link_t;
struct Link* insert(struct Link *n3);
void print(struct Link* head, int flag);
void swap(struct Link **head, int value);
#define MAX_PATH_SIZE (256)
#define MAX_NAME_SIZE (50)
int main()
{
struct Link* head = NULL;
int flag = 0;
int num = 0;
char namearray[MAX_NAME_SIZE] = { 0 };
char patharray[MAX_PATH_SIZE] = { 0 };
printf("1\n");
printf("\n");
for (int i = 0; i < 2; i++)
{
printf("Enter a number you want to insert - ");
scanf("%d", &num);
printf("\nEnter the name - ");
scanf("%s", &namearray);
printf("\nEnter the path - ");
scanf("%s", &patharray);
printf("\n");
head = insert(head,num,namearray,patharray);
}
print(head, flag);
swap(&head, 8);
printf("1\n");
system("pause");
return 0;
}
struct Link *insert(struct Link *p, int n, char namearray[MAX_NAME_SIZE], char patharray[MAX_PATH_SIZE]) //insert func
{
struct node *temp;
if (p == NULL) //if the node is empty
{
p = (struct Link *)malloc(sizeof(struct Link)); //gives memory to the node
p->frame = (struct Frame *)malloc(sizeof(struct Frame));
if (p == NULL)
{
printf("Error\n");
}
else
{
printf("The number added to the end of the list\n");
}
p->frame->duration = n; //its runing untill the node item is NULL
p->frame->name = namearray;
p->frame->path = patharray;
p->next = NULL;
}
else
{
p->next = insert(p->next, n , namearray , patharray);/* the while loop replaced by
recursive call */
}
return (p);
}
void print(struct Link* head , int flag)//print func
{
if (head == NULL && flag == 0) //if the node is empty
{
printf("The list is empty\n");
return 1;
}
if (head == NULL && flag != 0) //if the node isnt empty but we are in the NULL (last) item of the node
{
printf("\n");
printf("the nodes of the list printed\n");
return;
}
printf("%d ", head->frame->duration);//prints the currect item
printf("\n");
printf("%s ", head->frame->name);//prints the currect item
printf("\n");
printf("%s ", head->frame->path);//prints the currect item
printf("\n");
print(head->next, ++flag);//calls the func recursevly
return 1;
}
void swap(struct Link **head, int value)
{
while (*head && (*head)->frame->duration != value)
{
head = (*head)->next;
}
if (*head && (*head)->next)
{
struct list *next = (*head)->next->next;
(*head)->next->next = *head;
*head = (*head)->next;
(*head)->next->next = next;
}
}
here is the print :
the print of the program

Linked list and pointers

I'm trying to pass to a pointer my address of the linked list in main,pass it in a function to allocate memory to it and traverse to the next node while keeping the position of the next node without breaking head node.
typedef struct {
int data;
struct node_list *next;
}node_list;
typedef struct {
struct node_list *head;
}list;
void insert_list(node_list **c, int num);
void main()
{
int num;
list *list_odd = (list*)calloc(1, sizeof(list));
node_list *c = &list_odd->head;
while (num != -1)
{
if (num % 2)
insert_list(c, num);
}
}
void insert_list(node_list **c, int num)
{
if (*c == NULL)
{
*c = (node_list*)malloc(sizeof(node_list)); // it allocates the memory in the right place.
(*c)->data = num;
(*c) = (*c)->next; // but this step breaks the starting list pointer
}
else
{
(*c)->next = (node_list*)malloc(sizeof(node_list));
(*c)->data = num;
(*c) = (*c)->next;
}
}
Edit: I may not explained myself, To clarify: If my list points to the start of the linked-list, while I allocate memory to it and then do (*c) = (*c)->next, my head no longer points to the begging. What I'm trying to achieve is having the start of the list and saving the position of the next node.
I'd like to suggest a two-sided singly linked list.
Here is a demonstrative program.
#include <stdlib.h>
#include <stdio.h>
typedef struct node
{
int data;
struct node *next;
} node;
typedef struct list
{
node *head;
node *tail;
} list;
int push_back( list *lst, int data )
{
node *new_node = malloc( sizeof( node ) );
int success = new_node != NULL;
if ( success )
{
new_node->data = data;
new_node->next = NULL;
if ( lst->tail == NULL )
{
lst->tail = lst->head = new_node;
}
else
{
lst->tail = lst->tail->next = new_node;
}
}
return success;
}
void display( list *lst )
{
for ( node *current = lst->head; current != NULL; current = current->next )
{
printf( "%d ", current->data );
}
printf( "\n" );
}
int main( void )
{
list lst = { NULL, NULL };
int data;
while ( scanf( "%d", &data ) == 1 && data != -1 )
{
if ( data % 2 != 0 ) push_back( &lst, data );
}
display( &lst );
return 0;
}
If to enter this sequence of numbers
0 1 2 3 4 5 6 7 8 9 -1
then the output will be
1 3 5 7 9
The complexity of adding a new node to the end of the list is O(1).
What I'm trying to achieve is having the start of the list and saving the position of the next node.
I'm not entirely sure what you're trying to do, so I've made an equivalent program. If you find this way of adding to the list to be too slow, then the program needs to be changed to either keep a {head, tail} pair or add items to the front of the list. From your text it sounds like you're trying to keep the head the same -- so a {head,tail} pair is probably best.
#include <stdlib.h> //added
#include <stdio.h> //added
#include <assert.h>
typedef struct node_list_t { //changed
int data;
struct node_list_t *next; //changed
} node_list;
typedef struct list_t { //gave the struct a tag
node_list *head; //use the typedef name, not the struct name
}list;
void insert_list(list *my_list, int num);
void main()
{
int num = 0; // initialised
list my_list = {0}; // changed to be on stack. Could be calloc'd if you like
node_list* printer;
while (num != 50) //changed limit
{
if (num % 2)
{
// we're just passing in the list
insert_list(&my_list, num);
}
num += 1; //actually incrementing number. :)
}
for (printer = my_list.head;
printer;
printer = printer->next)
{
printf("%d\n", printer->data);
}
}
void insert_list(list *my_list, int num)
{
node_list *c = (node_list*) calloc(1, sizeof(node_list));
c->data = num;
assert(!c->next);
if (!my_list->head)
{
// if the head is not initialised, then make C the head
my_list->head = c;
}
else
{
// otherwise stick it on the end of the list.
node_list *p;
for (p = my_list->head;
p->next;
p = p->next)
{
//do nothing
}
p->next = c;
}
}

anagram detecting using linked lists in c

I'm trying to write a code that'll check 2 words if they are anagrams,using linked lists.To do that,I guess it should receive 2 words from the user and pass every letter they contain to linked list's nodes,and compare the nodes if they have the same letter,if so,remove the same letter from the second word.When the process is done,if the second list is empty,then they are anagrams.Even if 1 letter is not matching,it should return 0,but I don't know how to determine the length of these words,here is what I wrote so far
#include <stdio.h>
#include <stdlib.h>
struct node
{
struct node *prev;
struct node *next;
char data;
};
typedef struct node *NODE,NOD;
NODE last(NODE list)
{
if(list!=NULL)
while(list->next!=NULL)
list=list->next;
NODE lst;
lst=list;
return lst;
}
void insert( char letter, NODE list)
{
NODE nod;
nod=(NODE)malloc(sizeof(NOD));
nod->next=NULL;
nod->prev=NULL;
nod->data=letter;
if(list==NULL)
{
list=nod;
}
else
{
nod->prev=last(list);
last(list)->next=nod;
}
}
Just check that each word has the same number of each letter in it.
int anagrams(const char *a, const char *b) {
int counts[256] = {0};
while (*a) counts[*a++]++;
while (*b) counts[*b++]--;
for (int i = 0; i < 256; i++) {
if (counts[i]) return 0;
}
return 1;
}
Why use linked lists for such an easy problem?
O(N) solution:
Calculate frequencies of every letter for each word and then compare these 2 histograms. If they're equal, then one word can be obtained from another.
If you want to use your linked-list-based solution, then, the length of the word is, indeed:
Length of each input word (they must have the same length) - it can be calculated with a single traversal from the linked list head to the tail.
Amount of removed symbols
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
typedef struct node {
char data;
struct node *prev;
struct node *next;
} NODE;
NODE *newNode(char ch){
NODE *p = malloc(sizeof(NODE));
if(p){
p->data = ch;
p->prev = p->next = NULL;
}
return p;
}
void insert(NODE **list, NODE *node){
if(*list == NULL){
*list = node;
return ;
}
NODE *curr = *list;
while(curr){
if(curr->data >= node->data){//insert sort
if(curr->prev == NULL)
*list = node;
else
curr->prev->next = node;
node->prev = curr->prev;
curr->prev = node;
node->next = curr;
break;
}
if(curr->next == NULL){
curr->next = node;
node->prev = curr;
break;
} else
curr = curr->next;
}
}
NODE *input_word(){
NODE *word=NULL;
int ch;
while(EOF!=(ch=getchar()) && ch != '\n'){
insert(&word, newNode(ch));
}
return word;
}
bool isAnagram(NODE *word1, NODE *word2){
while(word1 && word2){
if(word1->data != word2-> data)
return false;
word1 = word1->next;
word2 = word2->next;
}
return word1 == NULL && word2 == NULL;
}
int main(){
NODE *word1, *word2;
printf("input word : ");
word1 = input_word();
printf("input other word : ");
word2 = input_word();
if(isAnagram(word1, word2))
printf("YES\n");
else
printf("NO\n");
//drop(word1);drop(word2);
return 0;
}

Resources