String input by linked list - c

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

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

Cannot get input from user to work in place of manual strings entered in code

I am trying to get a program to run that basically takes an input string and sends it through some code and sorts it using linked lists alphabetically. I have figured out how to make this work using manual (in the actual code) text input, but I cannot get it to work when I am trying to take input from the user.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct llist {
char *value;
struct llist *next;
};
int compare (struct llist *one , struct llist *two)
{
return strcmp(one->value, two->value);
}
void add(struct llist **pp, char *value, int (*cmp)(struct llist *l, struct llist *r)) {
struct llist *new;
new = malloc(sizeof(*new));
new->value = value;
for ( ; *pp != NULL; pp = &(*pp)->next) {
if (cmp(*pp, new) > 0 ) break;
}
new->next = *pp;
*pp = new;
}
void display(struct llist *ptr) {
for (; ptr != NULL; ptr = ptr->next) {
printf("%s\n", ptr->value);
}
}
int main(void) {
struct llist *root = NULL;
char string;
printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");
string = getchar();
while (string != 10){
add(&root,&string, compare);
string = getchar();
}
display(root);
return 0;
}
looking in the main function I'm quite certain it has something to do with getchar and the fact that it reads characters in as ints, but I can't figure out how to fix this, the output is just a bunch of empty lines. but when the while loop is removed and the strings are entered like below in main, it works fine? why is this so?
int main(void) {
struct llist *root = NULL;
char string;
printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");
add(&root,"t", compare);
add(&root,"h", compare);
add(&root,"i", compare);
add(&root,"s", compare);
add(&root,"m", compare);
add(&root,"y", compare);
add(&root,"t", compare);
add(&root,"e", compare);
add(&root,"x", compare);
add(&root,"t", compare);
display(root);
return 0;
}
the output is now
e
h
i
m
s
t
t
t
x
y
which is correct,
Can anyone help me?
When you write "t" in the example, you get the address of an array. That address is different for each value you pass to add. However, the address of string does not change, and you are setting new->value to the same thing each time you call add. Instead of new->value = value, try new->value = *value (and all of the associated changes necessary).
There are not too many changes needed. Note that terminating after a single string of input is not very nice behavior. A good exercise would be to write a destructor that tears down the string after the first line and then sorts the next. Another nice exercise would be to sort arguments if any are passed, reading stdin if no arguments are given.
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
struct llist {
char value; /* CHANGE */
struct llist *next;
};
typedef int (*compar)( struct llist *one , struct llist *two );
int
compare( struct llist *one , struct llist *two )
{
return tolower( one->value ) > tolower( two->value ); /* CHANGE */
}
void *
xmalloc( size_t s )
{
void *v = malloc( s );
if( v == NULL ) {
perror( "malloc" );
exit( EXIT_FAILURE );
}
return v;
}
void
add( struct llist **pp, char value, compar cmp ) /* CHANGE */
{
struct llist *new;
new = xmalloc( sizeof *new ); /* Check for errors */
new->value = value; /* CHANGE the type of value above */
for( ; *pp != NULL; pp = &(*pp)->next ) {
if( cmp( *pp, new ) > 0 )
break;
}
new->next = *pp;
*pp = new;
}
void
display( struct llist *ptr )
{
for( ; ptr != NULL; ptr = ptr->next ) {
putchar( ptr->value ); /* CHANGE */
}
putchar( '\n' );
}
int
main( void )
{
struct llist *root = NULL;
char string;
while( (string = getchar()) != '\n' ) { /* Optional CHANGE (1) */
add( &root,string, compare );
}
display(root);
return 0;
}
/*
* (1) Using "'\n'" instead of 10 is necessary for readability,
* portability, and sanity of future maintainers.
*
* Writing getchar() only once is cleaner.
*/
With your hard coded entry code you are passing in string's to add while in your user input code you are only passing in a pointer to a single character. A char* is not necessarily a string in C, it may point to a string, but it doesn't have to.
In C a string is a buffer of characters that ends with a null zero, the character '\0' (which is usually just the value 0). When you are using getchar your are passing a pointer to a character - and that character does not have a null zero after it, so it is not a valid C string.
If you want to keep your code using getchar you need to use a buffer that will store a null zero after that character. You can do that will a small array as below:
int main(void) {
struct llist *root = NULL;
char string[2];
string[1] = '\0'; // Ensure that we have a null terminated string
printf("Please enter a string to be sorted alphabetically and displayed with a character count: ");
string[0] = getchar();
while (string != '\n'){
add(&root,string, compare);
string[0] = getchar();
}
display(root);
return 0;
}
Cleaned-up a few things
1) As #shf301 siad, need to pass a string, not just a pointer to a single char.
2) Need to create copies of the string - notice strdup.
3) While loop should break on '\n and EO and maybe '\0. getchar() returns an int for a reason: EOF and 0 to UCHAR_MAX (e. g. 255).
4) Should free() resources at the end - not shown.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
// In case you library does not have strdup() ...
char *strdup(const char *s) {
if (s == NULL) return NULL;
size_t siz = strlen(s) + 1;
char *y = malloc(siz);
if (y != NULL) {
memcpy(y, s, siz);
}
return y;
}
struct llist {
char *value;
struct llist *next;
};
int compare(struct llist *one, struct llist *two) {
return strcmp(one->value, two->value);
}
void add(struct llist **pp, char *value,
int(*cmp)(struct llist *l, struct llist *r)) {
struct llist *new;
new = malloc(sizeof(*new));
new->value = strdup(value);
for (; *pp != NULL; pp = &(*pp)->next) {
if (cmp(*pp, new) > 0)
break;
}
new->next = *pp;
*pp = new;
}
void display(const struct llist *ptr) {
for (; ptr != NULL; ptr = ptr->next) {
printf("%s\n", ptr->value);
}
}
int main(void) {
struct llist *root = NULL;
char string[2];
string[1] = '\0';
printf("Please enter a string to be sorted alphabetically"
" and displayed with a character count: ");
int ch;
while ((ch = getchar()) != EOF && ch != '\n' && ch != '\0') {
string[0] = ch;
add(&root, string, compare);
}
display(root);
return 0;
}

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