storing an array as a linked list in C - 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;
}

Related

Input Char in Doubly Linkedlist C

This is my code:
struct Node{
int data;
char nim[12];
struct Node *next, *prev;
};
struct Node *head, *tail;
void init(){
head = NULL;
tail = NULL;
}
int isEmpty(struct Node *h){
if(h==NULL)
return 1;
else
return 0;
}
void addData(char *nimI){
struct Node *baru;
baru = malloc(sizeof *baru);
baru->nim = malloc(12 * sizeof(char));
strcpy(baru->nim, nimI);
baru->next = NULL;
baru->prev = NULL;
if(isEmpty(head)==1){
head=baru;
tail=baru;
}else{
tail->next=baru;
baru->prev=tail;
tail = baru;
}
printList(head);
}
int main()
{
char nimI[12];
printf("NIM : ");
scanf("%[^\n]#", &nimI);
fflush(stdin);
addData(nimI);
}
I want to input char in my doubly linked list, but it's error.
error :
assigment to expression with array type (error in baru->nim = malloc(12 * sizeof(char));)
You don't need to allocate the memory of an array, so it's worthless to write:
baru->nim = malloc(sizeof(char) * 12);
This statement is only possible when char[12] -> *char. Thanks to #kalyum, but honestly, I figured out this myself just a few moments ago.
Here's the minimal version of the program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Node {
int data;
char *nim; // Changed num[12] -> *num
};
void addData(char *nimI) {
struct Node *baru = malloc(sizeof *baru);
baru->nim = malloc(sizeof(char) * 12); // Now this will work
strcpy(baru->nim, nimI); // Copying nimI into baru->nim pointer
printf("%s\n", baru->nim); // Displaying the result
}
int main(void) {
char nimI[12] = "Hello there";
// Passing nimI[] (equivalent to *nimI when passed)
addData(nimI);
return 0;
}
This outputs:
Hello there

Inserting nodes in a linked list in decreasing order - C

I have to make a list that arrange the people in decreasing order of their number('no' for my program). I tryed to make it by modifying the addNode function but I got no result(peoples do not arrange by their number). This is my code:
Header code:
#ifndef __EX__
#define __EX__
typedef struct Person{
char name[10];
float no;
struct Person *pNext;
} NODE, *pNODE, **ppNODE;
void addNode(ppNODE, pNODE);
void travers(pNODE, unsigned int*);
#endif
Functions folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
void addNode (ppNODE ppPrim, pNODE p){
pNODE q = (pNODE)malloc(sizeof(NODE));
assert(q!=NULL);
printf("Add name: \n");
scanf("%s", &q->name);
printf("\nAdd no: ");
scanf("%f", &q->no);
if (p == NULL || q->no < p->no) {
q->pNext = *ppPrim;
*ppPrim = q;
} else {
q->pNext = p->pNext;
p->pNext = q;
}
return;
}
void travers(pNODE pPrim, unsigned int *pLen){
*pLen = 0;
pNODE tmp = pPrim;
while (tmp != NULL){
puts (tmp->name);
fprintf(stdout, " no %.2f\n", tmp->no);
tmp = tmp->pNext;
(*pLen)++;
}
return;
}
Main folder:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <math.h>
#include <string.h>
#include "EX.h"
int main(){
unsigned int len;
pNODE prim = NULL;
int i;
for (i=0; i<=1; i++){
addNode(&prim, prim);
addNode(&prim, prim->pNext);
}
travers(prim, &len);
return 0;
}
When you insert a new node to the list, you must traverse the list until you find a suitable place to insert it. Your code takes a second argument, which isn't really needed and causes confusion, and only looks at that.
The code to insert a code q at the end of a list that is defined by its head is:
Node *prev = NULL;
Node *p = *head;
while (p) {
prev = p;
p = p->pNext;
}
q->pNext = p;
if (prev == NULL) {
*head = q;
} else {
prev->pNext = q;
}
You can get rid of keeping track of the previous node and the distinction between inserting at the head and inserting after that by traversing the list with a pointer to node pointer:
Node **p = &head;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
In this concise code, p holds the address of the head at first and the address of the pNext pointer of the previous node. Both can be updated via *p.
You can now use this code to traverse only as far as the numbers associated with each node are smaller than the one of the node to insert. here's a complete program:
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef struct Node Node;
void addNode(Node **p, const char *name, float no);
void travers(Node *pPrim, unsigned int *pLen);
struct Node {
char name[10];
float no;
Node *pNext;
};
void addNode(Node **p, const char *name, float no)
{
Node *q = malloc(sizeof(*q));
assert(q != NULL);
snprintf(q->name, sizeof(q->name), "%s", name);
q->no = no;
while (*p && (*p)->no < q->no) {
p = &(*p)->pNext;
}
q->pNext = *p;
*p = q;
}
void traverse(const Node *pPrim, unsigned int *pLen)
{
*pLen = 0;
while (pPrim != NULL) {
fprintf(stdout, "%-12s%.2f\n", pPrim->name, pPrim->no);
pPrim = pPrim->pNext;
(*pLen)++;
}
}
int main()
{
unsigned int len;
Node *prim = NULL;
addNode(&prim, "Alice", 0.23);
addNode(&prim, "Bob", 0.08);
addNode(&prim, "Charlie", 0.64);
addNode(&prim, "Dora", 0.82);
traverse(prim, &len);
printf("\n%u entries.\n", len);
return 0;
}
Things to node:
I've used Node * and Node ** instead of the typedeffed pNODE and ppNODE. In my opinion using the C pointer syntax is clearer.
You should separate taking user input from adding a node.
In your code you shouldn't pass the address of the char array when scanning a string, just the char array. (It happens to work, but it isn't correct. The compiler should warn you about that.)

Problems with removing the last item in a linked list in c

I am just learning c and about linked lists I have some major problems.
I have following code :
#include <stdio.h>
#include <stdlib.h>
struct people {
int age;
char *name;
struct people * next;
};
typedef struct people people;
void count(people array) {
people *current=malloc(sizeof(people));
current = &array;
int count = 0;
while(current){
count++;
printf("name %s\n",current->name);
printf("age %d\n",current->age);
current=current->next;
}
printf("%d\n", count);
free(current);
}
void push(people *array){
people * new=malloc(sizeof(people));
people *last=malloc(sizeof(people));
new->age=300;
new->name="baz";
new->next=NULL;
last=array;
while(last->next){
last=last->next;
}
last->next=new;
// free(new);
}
void pop(people *array){
people * last=malloc(sizeof(people));
last=array;
while(last->next){
//get the last element in the list
last=last->next;
}
// free the last element
free(last);
}
int main(int argc, char** argv) {
people person = {
.name = "foo",
.age = 25
};
person.next = malloc(sizeof (people));
person.next->age = 26;
person.next->name = "bar";
person.next->next = NULL;
//push into the list
push(&person);
//count after pushing
count(person);
//remove last
pop(&person);
//at this count i get just the age 0 but the name was not removed and still counts 3
count(person);
return 0;
}
When I run pop it is supposed to work similar to Array.prototype.pop from Javascript. It behaves really weird the last next has the name "baz" and age 300. After I run this code instead of removing this last struct it just shows the age as 0.
Seems free is not really freeing the pointer allocated with malloc.
example
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct people {
int age;
char *name;
struct people * next;
} people;
people *new_people(const char *name, int age){
people *node = malloc(sizeof(people));
char *copy_name = malloc(strlen(name)+1);
strcpy(copy_name, name);
node->age = age;
node->name = copy_name;
node->next = NULL;
return node;
}
void free_people(people *p){
free(p->name);
free(p);
}
void count(people *array) {
people *current = array;
int count = 0;
while(current){
count++;
printf("name %s\n", current->name);
printf("age %d\n", current->age);
current = current->next;
}
printf("%d\n", count);
}
void push(people **array, people *addNode){
if(*array == NULL){
*array = addNode;
return ;
}
people *last = *array;
while(last->next){
last = last->next;
}
last->next = addNode;
//return length;
}
people *pop(people **array){
if(*array == NULL)
return NULL;
people *last = *array;
people *prev = NULL;
while(last->next){
prev = last;
last=last->next;
}
if(prev != NULL)
prev->next = NULL;
else
*array = NULL;
return last;
}
int main(void) {
people *array = NULL;
push(&array, new_people("foo", 25));
push(&array, new_people("bar", 26));
push(&array, new_people("baz", 300));
count(array);
people *baz = pop(&array);
free_people(baz);
count(array);
people *bar = pop(&array);
free_people(bar);
people *foo = pop(&array);
free_people(foo);//free_people(pop(&array))
return 0;
}
The problem is that, in the void count(people array), current=current->next; would be assigned in the while loop. So you need to make sure last->next shall be assigned to NULL in the pop function.
I modified your pop function to:
void pop(people *array){
people * last=malloc(sizeof(people));
while(array->next){
last=array;
array=array->next;
if(array->next){
//get the last element in the list
last=last->next;
}else{
break;
}
}
last->next=NULL;
array=last;
}
In the pop function, you should assign the address of 'array' to 'last', and then points the 'array' to 'array->next'.
As the program breaks from the while loop, you can do last->next=NULL; and array=last; to make sure the last struct is fine.

Queue of Strings in C

I am trying to edit this program. Right now the users enters symbols and I want to make it work with Strings.
#include <stdio.h>
#include <stdlib.h>
struct Node
{
char data;
struct Node *next;
};
struct queue
{
struct Node *top;
struct Node *bottom;
}*q;
void Write(char x)
{
struct Node *ptr=malloc(sizeof(struct Node));
ptr->data=x;
ptr->next=NULL;
if (q->top==NULL && q->bottom==NULL)
{
q->top=q->bottom=ptr;
}
else
{
q->top->next=ptr;
q->top=ptr;
}
}
char Read ()
{
if(q->bottom==NULL)
{
printf("Empty QUEUE!");
return 0;
}
struct Node *ptr=malloc(sizeof(struct Node));
ptr=q->bottom;
if(q->top==q->bottom)
{
q->top=NULL;
}
q->bottom=q->bottom->next;
char x=ptr->data;
free(ptr);
return x;
}
int main()
{
q= malloc(sizeof(struct queue));
q->top=q->bottom=NULL;
char ch='a';
printf("NOTE: To stop the entry, please enter 'q'!\n\n Enter a String: \n");
while(ch!='q')
{
scanf("%c",&ch);
Write(ch);
}
printf("\nThe entered String:\n\n");
while(q->bottom!=NULL)
{
ch=Read();
printf("%c",ch);
}
printf("\n\n");
system("PAUSE");
return 0;
}
So I am editing it like this (the code below) and I get error "[Error] incompatible types when assigning to type 'char[10]' from type 'char *'"
#include <stdio.h>
#include <stdlib.h>
struct Node
{
char data[10];
struct Node *next;
};
struct queue
{
struct Node *top;
struct Node *bottom;
}*q;
void Write(char x[10])
{
struct Node *ptr=malloc(sizeof(struct Node));
ptr->data=x;
ptr->next=NULL;
if (q->top==NULL && q->bottom==NULL)
{
q->top=q->bottom=ptr;
}
else
{
q->top->next=ptr;
q->top=ptr;
}
}
char Read ()
{
if(q->bottom==NULL)
{
printf("Empty QUEUE!");
return 0;
}
struct Node *ptr=malloc(sizeof(struct Node));
ptr=q->bottom;
if(q->top==q->bottom)
{
q->top=NULL;
}
q->bottom=q->bottom->next;
char x=ptr->data;
free(ptr);
return x;
}
int main()
{
q= malloc(sizeof(struct queue));
q->top=q->bottom=NULL;
char ch][10]='a';
printf("NOTE: To stop the entry, please enter 'q'!\n\n Enter a String: \n");
while(ch!='q')
{
scanf("%c",&ch);
Write(ch);
}
printf("\nThe entered String:\n\n");
while(q->bottom!=NULL)
{
ch=Read();
printf("%c",ch);
}
printf("\n\n");
system("PAUSE");
return 0;
}
I can't solve this problem, so I would love to get some help...
You can't assign to an array, but you can copy to it.
To copy a string use strcpy:
strcpy(ptr->data, x);
Or since you have a limited array, maybe use strncpy:
strncpy(ptr->data, x, sizeof(ptr->data) - 1);
ptr->data[sizeof(ptr->data) - 1] = '\0';
For strncpy it will not add the terminating '\0' character if the source is equal or longer than the specified length, so we have to make sure that the string is properly terminated.

String input by linked list

Is there any way to take a string input(as like we take for any integer) by linked list??
For example:This code is showing run time error:
struct node
{
char c;
struct node *link;
};
while(1)
{
val=getch();
if(val!=10)
add(&a[i],val);
else
break;
}
and I want to take any input string like - "asdfghj", of which string length was not known?
Given that you have a LinkedList-class that acts as an interface to the linked list and that it has the function addNode() that adds a node in a correct manner to the list.
I also assume that what you want to know is how to make every char in the inputted string a node in the linked list and that you know how to manage a linked list.
And assuming you're using C++11
int main()
{
LinkedList list;
string input;
cin >> input;
for(auto i: input)
{
list.addNode(i);
}
}
example for C
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
char c;
struct node *link;
} Node;
typedef struct s_ {
Node *top;
Node *curr;
} String;
Node *Node_new(char ch){
Node *p = calloc(1, sizeof *p);
p->c = ch;
return p;
}
String *String_new(void){
String *p = calloc(1, sizeof *p);
return p;
}
void String_drop(String *s){
Node *p = s->top;
while(p){
s->curr = p;
p = p->link;
free(s->curr);
}
//s->top = s->curr = NULL;
free(s);
}
void String_add(String *s, char c){
if(s->top == NULL){
s->curr = s->top = Node_new(c);
} else {
s->curr = s->curr->link = Node_new(c);
}
}
String *get_string(FILE *fp){
String *s = String_new();
int ch;
while(EOF!=(ch=fgetc(fp)) && ch !='\n'){
String_add(s, (char)ch);
}
return s;
}
void put_string(String *s){
Node *p;
for(p = s->top; p ; p = p->link)
putchar(p->c);
putchar('\n');
}
int main(void) {
String *s = get_string(stdin);
put_string(s);
String_drop(s);
return 0;
}
You can think easily. As You just can declare a string variable instead of char. And after that You can take input normally by creating a struct variable. For example:
#include <bits/stdc++.h>
using namespace std;
struct node
{
string s;
struct node *link;
};
int main(){
node ob;
cin>>ob.s;
cout<<ob.s;
}

Resources