Input Char in Doubly Linkedlist C - 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

Related

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.)

How to sort a linkedlist in C programming?

So I am trying to sort a linked list, from small to big based on the name. It sorts it but it is sorting it the reverse or wrong way.
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
//declaring a struct
struct node {
char *name;
int num;
struct node *next;
};
struct node *list=NULL;
/*
* insert()
*/
struct node *insert(char word2[], int val){
struct node *tmp;
tmp = malloc(sizeof(struct node));
if(tmp ==NULL){
fprintf(stderr, "out of memory\n");
exit(1);
}
tmp->name = strdup(word2);
tmp->num = val;
tmp->next = list;
list = tmp;
return tmp;
}//read string
void print(){
struct node *ptr;
for(ptr= list; ptr!=NULL; ptr = ptr->next){
printf(" %s/%d\n", ptr->name, ptr->num);
}//for loop
}//print
void sort(){
struct node *ptr1, *ptr2;
char *tmp;
for(ptr1 = list; ptr1!=NULL; ptr1 = ptr1->next){
for(ptr2 = ptr1->next; ptr2!=NULL; ptr2 = ptr2->next){
if(strcmp(ptr1->name, ptr2->name)>0){
//ptr1->name is "greater than" ptr2->name - swap them
tmp = ptr1->name;
ptr1->name = ptr2->name;
ptr1->name = tmp;
}
}
}
}//sort
int main (){
char buff[81];
int status=0;
int len;
char word1[20];
char word2[20];
int val;
// char word3[20];
while(fgets(buff, 81, stdin)>0){
len = strlen(buff);
if(buff[len-1]!='\n'){
fprintf(stderr,"Error: string line length was too long\n");
exit(1);
}
sscanf(buff, "%s %s %d", word1, word2, &val);
if(strcmp(word1, "insert")==0){
insert(word2, val);
sort();
}else if(strcmp(word1, "print")==0){
print();
}else{
}
}//while loop
return status;
}
This is what my input looks like when I run it.
"insert a 1"
"insert b 2"
"insert c 3"
"print"
output
c/3
b/2
a/1
If have tried changing my sort method condition but it keeps sorting it the wrong way. I can't seem to find the bug. Any help will be greatly appreciated. But my output is supposed to look like this
Desired output
a/1
b/2
c/3
If you sort after every insert you do not need the full bubble-sort, just one round.
void sort()
{
struct node *ptr1 = list;
char *tmpname;
int tmpnum;
while (ptr1->next != NULL) {
if (strcmp(ptr1->name, ptr1->next->name) > 0) {
// swap content in this case, not the nodes
tmpname = ptr1->name;
tmpnum = ptr1->num;
ptr1->name = ptr1->next->name;
ptr1->num = ptr1->next->num;
ptr1->next->name = tmpname;
ptr1->next->num = tmpnum;
}
ptr1 = ptr1->next;
}
}

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;
}

All Nodes in a linked list point to same object

The problem is somewhere in here....
char buffer[80];
char *name;
while (1) {
fgets(buffer, 80, inf); //reads in at most 80 char from a line
if (feof(inf)) //this checks to see if the special EOF was read
break; //if so, break out of while and continue with your main
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");//get first token up to space
stock = newStock(name,...)
....
}
I'm working in C with generic linked lists. I made a list implementation that I've tested and know works with chars. I'm trying to add stocks (I created a stock struct) to the linked list, with each node of the linked list holding a stock struct, but when I finish reading in the stocks all of the nodes point to the same struct and I can't figure out why. Here's some snippets of my code
list *list = malloc(sizeof(list));
newList(list, sizeof(stock_t));
while(1) {
...
(read from file)
...
stock_t *stock;
stock = newStock(name, closes, opens, numshares, getPriceF, getTotalDollarAmountF,getPercentChangeF,toStringF);
addToBack(list, stock);
}
Here's the newStock function:
stock_t *newStock(char *name, float closingSharePrice, float openingSharePrice, int numberOfShares, getPrice getP, getTotalDollarAmount getTotal, getPercentChange getPercent, toString toStr) {
stock_t *stock = malloc(sizeof(stock));
stock->stockSymbol = name;
stock->closingSharePrice = closingSharePrice;
stock->openingSharePrice = openingSharePrice;
stock->numberOfShares = numberOfShares;
stock->getP = getP;
stock->getTotal = getTotal;
stock->getPercent = getPercent;
stock->toStr = toStr;
return stock;
}
In a way I see what's wrong. newStock returns a new pointer every time, but it always gets stored in the variable 'stock' which is what every node points to, so it's going to be equal to whatever the last pointer newStock returned was...but I don't see the way around this. I tried having newStock return just a stock_t, and doing addToBack(list, &stock), but that didn't solve the problem either.
Any help would be appreciated!
Here is some code from the list:
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
Here's code from the stock struct:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef float (*getPrice)(void *S);
typedef float (*getTotalDollarAmount)(void *S);
typedef float (*getPercentChange)(void *S);
typedef char *(*toString)(void *S);
typedef struct stock{
char *stockSymbol;
float closingSharePrice;
float openingSharePrice;
int numberOfShares;
getPrice getP;
getTotalDollarAmount getTotal;
getPercentChange getPercent;
toString toStr;
}stock_t;
The generic functions probably seem like overkill but this is for homework (if you couldn't tell already) so we were asked to specifically use them. I don't think that has anything to do with the problem though.
Here are the definitions for those functions anyway
float getPriceF(void *S) {
stock_t *stock = (stock_t*)S;
return stock->closingSharePrice;
}
float getTotalDollarAmountF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice) * (stock->numberOfShares));
}
float getPercentChangeF(void *S) {
stock_t *stock = (stock_t*)S;
return ((stock->closingSharePrice - stock->openingSharePrice)/(stock->openingSharePrice));
}
char *toStringF(void *S) {
stock_t* stock = (stock_t*)S;
char *name = malloc(20*sizeof(char));
//sprintf(name, "Symbol is: %s. ", (stock->stockSymbol));
return stock->stockSymbol;
}
void printStock(void *S) {
char *str = toStringF(S);
printf("%s \n", str);
}
And this is how I'm traversing the list:
typedef void (*iterate)(void *); //this is in the list.h file, just putting it here to avoid confusion
void traverse(list *list, iterate iterator) {
assert(iterator != NULL);
node_t *current = list->head;
while (current != NULL) {
iterator(current->data);
current = current->next;
}
}
And then in my main I just called
traverse(list, printStock);
I can't find any problems with your code (that would cause your problem, anyway - there are places where you don't check the return from malloc() and stuff like that, but those are not relevant to this question). You don't supply the definition of stock_t, so I made a new data struct, and a new couple of functions, otherwise I just copied and pasted the code you provided:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
/* Your code starts here */
typedef struct node {
void *data;
struct node *next;
}node_t;
typedef struct {
int length;
int elementSize;
node_t *head;
node_t *tail;
} list;
void newList(list *list, int elementSize) {
assert(elementSize > 0);
list->length = 0;
list->elementSize = elementSize;
list->head = list->tail = NULL;
}
void addToBack(list *list, void *element) {
node_t *node = malloc(sizeof(node_t));
node->data = malloc(list->elementSize);
node->next = NULL; //back node
memcpy(node->data, element, list->elementSize);
if (list->length == 0) { //if first node added
list->head = list->tail = node;
}
else {
list->tail->next = node;
list->tail = node;
}
list->length++;
}
/* Your code ends here */
/* I made a new struct, rather than stock, since you didn't supply it */
struct mydata {
int num1;
int num2;
};
/* I use this instead of newStock(), but it works the same way */
struct mydata * newNode(const int a, const int b) {
struct mydata * newdata = malloc(sizeof *newdata);
if ( newdata == NULL ) {
fputs("Error allocating memory", stderr);
exit(EXIT_FAILURE);
}
newdata->num1 = a;
newdata->num2 = b;
return newdata;
}
/* I added this function to check the list is good */
void printList(list * list) {
struct node * node = list->head;
int n = 1;
while ( node ) {
struct mydata * data = node->data;
printf("%d: %d %d\n", n++, data->num1, data->num2);
node = node->next;
}
}
/* Main function */
int main(void) {
list *list = malloc(sizeof(list));
newList(list, sizeof(struct mydata));
struct mydata * data;
data = newNode(1, 2);
addToBack(list, data);
data = newNode(3, 4);
addToBack(list, data);
data = newNode(5, 6);
addToBack(list, data);
printList(list);
return 0;
}
which outputs this:
paul#MacBook:~/Documents/src$ ./list
1: 1 2
2: 3 4
3: 5 6
paul#MacBook:~/Documents/src$
demonstrating that you have a 3 node list, with all nodes different and where you'd expect them to be.
Either there is some other problem in code you're not showing, or for some reason you are thinking each node points to the same struct when it actually doesn't.
One possibility is that you have a char * data member in your stock struct. It's impossible to tell from the code you provided, but it's possible that you really are creating different nodes, but they all end up pointing to the same name, so they just look like they're the same. If you're assigning a pointer to name, you should make sure it's freshly allocated memory each time, and that you're not just, for instance, strcpy()ing into the same memory and assigning the same address to each stock struct.
EDIT: Looks like that was your problem. This:
name = (char *) malloc(sizeof(char)*20);
....
name = strtok(buffer, " ");
should be:
name = (char *) malloc(sizeof(char)*20);
....
strcpy(name, strtok(buffer, " "));
Right now, you malloc() new memory and store a reference to it in name, but then you lose that reference and your memory when you overwrite it with the address returned from strtok(). Instead, you need to copy that token into your newly allocated memory, as shown.

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;
}

Resources