Create a new node for each entry in a .txt file - c

Okay so I've been doing a program which would read elements of a txt file using scanf (cmd input redirection). A new node must be created for every entry in the file and add it at the end of the list. Here's my code so far:
struct Elem{
int Atnum;
char Na[31];
char Sym[4];
};
struct nodeTag {
struct Elem entry;
struct nodeTag *pNext; // pointer to the next node
};
typedef struct nodeTag Node;
The function that would initialize it is this:
Node *
InitializeList(Node *pFirst, int n)
{
int i;
Node *head, *temp = 0;
pFirst = 0;
for (i=0; i<n; i++){
head = (Node *)malloc(sizeof(Node));
scanf("%d", &head->entry.AtNum);
scanf("%s", head->entry.Na);
scanf("%s", head->entry.Sym);
if (pFirst != 0)
{
temp->pNext = head;
temp = head;
}
else
{
pFirst = temp = head;
}
fflush(stdin);
temp->pNext = 0;
}
return pFirst;
}
and lastly, print it
void
Print( Node *pFirst )
{
Node *temp;
temp = pFirst;
printf("\n status of the linked list is\n");
while (temp != 0)
{
printf("%d %s %s", temp->entry.AtNum, temp->entry.Na, temp->entry.Sym);
temp = temp -> pNext;
}
}
Now, I can't get the program to run properly. No run-time errors though but the output seems to be garbage. I've been working for hours for this and I cant' get my head around it. Thank you for your help!

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct Elem
{
int AtNum;
char Na[31];
char Sym[4];
};
struct nodeTag
{
/* entry must be a pointer in order to not lose the values
and/or encounter memory conflicting errors
*/
struct Elem *entry;
struct nodeTag *pNext;
};
typedef struct nodeTag Node;
// insert node at the first location
Node *insertFirst(Node *head, struct Elem *data)
{
Node *node = (Node *) malloc(sizeof(Node));
// fill in data
node->entry = data;
/* point it to old first node
in simple words: "put this node before the head"
*/
node->pNext = head;
// point first to new first node
head = node;
return head;
}
Node *InitializeList(int n)
{
int i;
Node *head = NULL;
struct Elem *data;
for (i = 0; i < n; i++)
{
// allocate memory for the struct Elem of each node
data = (struct Elem*) malloc(sizeof(struct Elem));
scanf("%d", &data->AtNum);
scanf("%s", data->Na);
scanf("%s", data->Sym);
head = insertFirst(head, data);
}
return head;
}
//display the list
void printList(Node *head)
{
Node *ptr = head;
printf("\nStatus of the linked list is:\n");
//start from the beginning
while(ptr != NULL)
{
printf("%d %s %s", ptr->entry->AtNum, ptr->entry->Na, ptr->entry->Sym);
printf("\n");
ptr = ptr->pNext;
}
}
int main(int argc, char *argv[])
{
Node *head;
head = InitializeList(3);
printList(head);
return 0;
}
I hope I didn't come too late! If not, please check this answer as the solution, thanks! :-)

Related

Trying to pass and print string into a linked list

So, I am trying to create a linked List where i take in strings from user then add them to the list and then delete the data at position 2. But i am having trouble with scanf (clarified in the output section) and also in the printing section. Any help would be appreciated.
The code
#include <stdio.h>
#include <stdlib.h>
struct node {
char *data;
char *begin;
char *end;
char *posi;
struct node *link;
};
struct node *add_begin(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = head;
return ptr;
}
struct node *add_end(struct node *head, char *data) {
struct node *ptr = malloc(sizeof(*ptr));
ptr->data = data;
ptr->link = NULL;
if (head == NULL) {
return ptr;
} else {
struct node *temp = head;
while (temp->link != NULL) {
temp = temp->link;
}
temp->link = ptr;
return head;
}
}
void add_at_post(struct node* head, char *data, int pos){
struct node *ptr=head;
struct node *ptr2=malloc(sizeof(struct node));
ptr2->data=data;
ptr2->link=NULL;
pos--;
while(pos !=1){
ptr=ptr->link;
pos--;
}
ptr2->link=ptr->link;
ptr->link=ptr2;
}
void delete_post(struct node* head, int position){
struct node*current= head;
struct node*previous= head;
if(head==NULL){
printf("is empty\n");
}
else if (position==1){
head=current->link;
free(current);
current=NULL;
}
else{
while(position!=1){
previous=current;
current=current->link;
position--;
}
previous->link=current->link;
free(current);
current=NULL;
}
}
int main() {
struct node *head = NULL;
char *data;
printf("Print at begin");
scanf("%s",data);
head = add_begin(head,data);//print at beginning of list
printf("Print at end");
scanf("%s",data);
head = add_end(head, data);//print at end of list
printf("Print at Position 2");
scanf("%s",data);
add_at_post(head,data,2);//print at position 2
delete_post(head,2);
for (struct node *ptr = head; ptr; ptr = ptr->link) {
printf("%s\n", ptr->data);
}
return 0;
}
The Expected Output
Print at begin
xxx
Print at end
yyy
Print at Position 2
ZZZ
xxx
zzz
The output I get. It calls the first scanf but skips the other 2. Then ends the RUN.
Print at begin
xxx
Print at end
Print at Position 2
This code is invalid in many places:
data does not reference valid memory
char *data;
printf("Print at begin");
scanf("%s",data);
you should allocate memory for ptr->data and copy as data may reference the same location on every call.
You do not check result of the malloc

How to print the first node from a linked list of structs?

Below is a Minimal Reproducible Example from my code. What I am doing is that I am inserting data in a list of structs and printing them on the console.
I want to print from each link only the first element that is inserted into each list of structs.
But how is that possible when instead of data in my struct I have:
typedef struct Node
{
int rollnumber, src, dst;
double gentime;
struct Node *next;
} Node;
(rollnumber, src, dst,gentime are the information I am reading from text files, but the reading code is not nessacary, so I wrote it with testdata.)
MINIMAL REPRODUCIBLE EXAMPLE
#include <stdio.h>
#include <stdlib.h>
#define N 10
typedef struct Node
{
int data;
struct Node* next;
} Node;
int push_front(Node** head, int data)
{
Node* new_node = malloc(sizeof(Node));
int success = new_node != NULL;
if (success)
{
new_node->data = data;
new_node->next = *head;
*head = new_node;
}
return success;
}
void output(Node* head)
{
for (Node* current = head; current != NULL; current = current->next)
{
printf("%d ", current->data);
}
}
void display(Node** set, int i)
{
output(set[i]);
putchar('\n');
}
int main(void)
{
int testdata = 1;
Node* link[N] = { 0 };
struct Node* head = NULL;
for (int i = 0; i < N; i++) {
push_front(&link[i], testdata++);
push_front(&link[i], testdata++);
}
for (int i = 0; i < N; i++) {
printf("link[%d]:", i);
display(link, i);
}
}
If you only want to print the first element of each link list, just do not loop in output:
void output(Node* head)
{
printf("%d ", head->data);
}
If I am right you want the first element of the list right ??
If so than the way you are working you are pushing the new node in front of old node, so your first node is now the last in the line, so all you need to do is to iterate the list till Node* next == null, and that node will be your answer
Node *getLastInLine( Node *Head){
Node *ptr;
ptr = Head;
if( ptr == NULL) return NULL;
while(ptr-> next != NULL){
ptr = ptr->next;
}
return ptr;
}

How to change sinlgy linked list to doubly linked list?

I have a program that I am supposed to change it from a singly linked list to a doubly linked list. This means that I use pointer that points to the next node and a pointer that points to previous node.
How do I do this while recycling my previous code. Is there a way to do this with minimum steps involved?
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//declaring structure
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//prototypes
node *create(int n);
void display_recursive(node *n);
int main()
{
int n = 0;
node *head = NULL;
printf("How many entries?\n");
scanf("%d", &n);
//call to create list
head = create(n);
printf("\nThe linked list in order is:\n");
display_recursive(head);
return 0;
}
node *create(int n)
{
node *head = NULL;
node *temp = NULL;
node *p = NULL;
for (int i = 0; i < n; i++)
{
temp = (node*)malloc(sizeof(node));
printf("What is the name of song %d\n", i + 1);
scanf("%s", &temp->songName);
printf("What is the length of song %d (in seconds)?\n", i + 1);
scanf("%d", &temp->songLength);
printf("Is song %d copyrighted?(1 = YES, 0 = NO)\n", i + 1);
scanf("%d", &temp->copyright);
temp->next = NULL;
if (head == NULL)
{
head = temp;
}
else
{
// if not empty, attach new node at the end
p = head;
while (p->next != NULL)
{
p = p->next;
}
p->next = temp;
}
}
return head;
}
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
printf("%d minutes, ",n->songLength);
if (n->copyright == 1)
{
printf("Copyrights\n");
}
else if (n->copyright == 0)
{
printf("No copyrights\n");
}
}
I don't really know how the code should look or what I have to add to achieve a doubly linked list.
You just need a pointer point to previous node
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node;
just like #T1412 said, you need to add a new member to the structure.
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
struct node* prev;
}node
now you need to modify the create() function so that each node's prev pointer is pointing to previous node, and the HEAD node's prev points to NULL.
Similarly, you need to modify all the linked list related functions to incorporate the prev pointer.
1) strongly suggest changing:
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
to:
struct NODE
{
char songName[20];
int songLength;
int copyright;
struct NODE * prev;
struct NODE * next;
};
typedef struct NODE node;
Then wherever in the code that it is linking in a new node, add the necessary statement to set the 'prior' field. Remember that the firs node will contain NULL in the 'prior' field.

Doubly linked list not working

I am trying to sort a doubly linked list in ascending order. I've gone trough the code again and again, and I can't find any logical flaws with it, so I assume the problem is elsewhere. When I try to print the sorted list, the console returns 0 without printing anything (the print function is not to blame, since it has already been tested)
Here is the code I am currrently running:
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
//receives the original head pointer
//returns sorted list's head pointer
Node** SortDate(struct Node** head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )//iterates over the entire list
{
//if the data value of the next node is bigger
if ( i->payload.ano > i->next->payload.ano )
{
//swaps the data value between i and i->next
//SwapNodes was tested and it is working
SwapNodes(i, i->next);
//the current value of i->next (former value of i)
//is compared to all the previous values
//and keeps swapping until a smaller value is found
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
return head;
}//sort
I know there probably are easier ways to sort doubly linked list, but I'm trying to figure out why this one doesn't work.
Thank you in advance!
EDIT:
showing all the involved functions:
#include <stdio.h>
#include <stdlib.h>
typedef struct dados_temp{
float temp;
float incerteza;
char pais[100];
char cidade[100];
float angle;
int hemisferio;
int dia;
int mes;
int ano;
} dados_temp;
typedef struct Node{
dados_temp payload;
struct Node *next;
struct Node *prev;
} Node;
Node * CreateCitiesList();
Node * CreateCountriesList();
Node * Intervalos(struct Node*, int[]);
void PrintBack(struct Node*);
struct Node* CreateNode (dados_temp x)
{
struct Node* NewNode = (struct Node*)malloc(sizeof(struct Node));
NewNode->payload = x;
NewNode->next = NULL;
NewNode->prev = NULL;
return NewNode;
}
}
void Print (struct Node* head)
{
struct Node* temp = head;
while ( temp != NULL)
{
printf("%d-%d-%d \n", temp->payload.ano, temp->payload.mes,
temp>payload.dia);
fflush(stdout);
temp = temp->next;
}
printf("\n");
}
Node* SortDate (struct Node*);
void SwapNodes (struct Node*, struct Node*);
int main(int argc, char* argv[])
{
CreateCountriesList();
}
Node* CreateCountriesList()
{
char linha[150] = {NULL};
char cabecalho[100] = {NULL};
int i = 0;
dados_temp New_Entry;
dados_temp tail;
int *ptr_head_co;
struct Node* head_countries = NULL;
struct Node* Node = NULL;
FILE *inputf;
inputf = fopen("tempcountries_all.csv", "r");
if (inputf == NULL)
{
printf("Nao da pa abrir o fitchas boi");
exit(EXIT_FAILURE);
}
//gets rid of the first line
fgets(cabecalho, 100, inputf);
for (i = 0; i < 577462 ; i++)
{
fgets(linha, 150, inputf);
//scans the date(amongst other things) from file (yyyy-mm-dd)
sscanf(linha, "%d-%d-%d,%f,%f,%[^,]s", &New_Entry.ano,
&New_Entry.mes,&New_Entry.dia, &New_Entry.temp, &New_Entry.incerteza,
&New_Entry.pais);
if (head_countries == NULL)
{
head_countries = CreateNode(New_Entry);
Node = CreateNode(New_Entry);
}
else
{
head_countries = InsertHead(head_countries, New_Entry);
}
}
fclose(inputf);
head_countries = RemoveNodes(Node);
SortDate(head_countries);
Print(head_countries);
return head_countries;
}
Node* SortDate(struct Node* head)
{
struct Node *i, *j;
for( i = head; i != NULL; i = i->next )
{
if ( i->payload.ano > i->next->payload.ano )
{
SwapNodes(i, i->next);
for (j = i->next; j->payload.ano < j->prev->payload.ano;)
{
SwapNodes(j, j->prev);
}
}
}
}//sort
void SwapNodes(struct Node* node1, struct Node* node2)
{
dados_temp temp = node1->payload;
node1->payload = node2->payload;
node2->payload = temp;
}

How to delete nodes of a linked list between two indices?

I have the following linked list implementation:
struct _node {
char *string;
struct _node *next;
}
struct _list {
struct _node *head;
struct _node *tail;
}
I want to make the following function:
void deleteList(struct _list *list, int from, int to) {
int i;
assert(list != NULL);
// I skipped error checking for out of range parameters for brevity of code
for (i = from; i <= to; i++) {
deleteNode(list->head, i);
}
}
// I ran this function with this linked list: [First]->[Second]->NULL
like this deleteNodes(list, 1, 1) to delete the second line and got
[First]->[Second]->NULL but when I run it like this deleteList(list, 0, 1) with this input [First]->[Second]->[Third]->NULL I get a seg fault.
Here is my deleteNode function
void deleteNode(struct _node *head, int index) {
if (head == NULL) {
return;
}
int i;
struct _node *temp = head;
if (index == 0) {
if (head->next == NULL) {
return;
}
else {
head = head->next;
free(head);
return;
}
}
for (i = 0; temp!=NULL && i<index-1; i++) {
temp = temp->next;
}
if (temp == NULL || temp->next == NULL) {
return;
}
Link next = temp->next->next;
free(temp->next);
temp->next = next;
}
I wrote a separate function to delete the head of the linked list if from or to = 0:
void pop(struct _node *head) {
if (head == NULL) {
return;
}
struct _node *temp = head;
head = head->next;
free(temp);
}
but it gives me seg fault or memory error Abort trapL 6.
It's all good to use just one struct, a node for your purpose.
struct node {
char *string;
struct node *next;
};
Then your loop for removing elements between two indices will not delete the right elements if you don't adjust the index according to the changing length of the list. And you must also return the new head of the list.
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
The help function delete_at_index looks as follows.
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
Complete program below.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct node {
char *string;
struct node *next;
};
void freeList(struct node *head) {
struct node *tmp;
while (head != NULL) {
tmp = head;
head = head->next;
free(tmp->string);
free(tmp);
}
}
struct node *delete_at_index(struct node *head, unsigned i) {
struct node *next;
if (head == NULL)
return head;
next = head->next;
return i == 0
? (free(head), next) /* If i == 0, the first element needs to die. Do it. */
: (head->next = delete_at_index(next, i -
1), head); /* If it isn't the first element, we recursively check the rest. */
}
struct node *deleteList(struct node *head, unsigned from, unsigned to) {
unsigned i;
unsigned count = 0;
for (i = from; i <= to; i++) {
head = delete_at_index(head, i - count);
count++;
}
return head;
}
void pushvar1(struct node **head_ref, char *new_data) {
struct node *new_node = malloc(sizeof(struct node));
new_node->string = strdup(new_data);
new_node->next = (*head_ref);
(*head_ref) = new_node;
}
void printListvar1(struct node *node) {
while (node != NULL) {
printf(" %s ", node->string);
node = node->next;
}
printf("\n");
}
int main(int argc, char **argv) {
struct node *head = NULL;
for (int i = 0; i < 5; i++) {
char str[2];
sprintf(str, "node%d", i);
pushvar1(&head, str);
}
puts("Created Linked List: ");
printListvar1(head);
head = deleteList(head, 0, 2);
puts("Linked list after deleted nodes from index 0 to index 2: ");
printListvar1(head);
freeList(head);
return 0;
}
Test
Created Linked List:
node4 node3 node2 node1 node0
Linked list after deleted nodes from index 0 to index 2:
node1 node0
every programming problem can be solved by adding an extra level of indirection: use a pointer to pointer ...
unsigned deletefromto(struct node **head, unsigned from, unsigned to)
{
unsigned pos,ret;
struct node *this;
for (pos=ret=0; this = *head;pos++) {
if (pos < from) { head = &(*head)->next; continue; }
if (pos > to) break;
*head = this->next;
free(this);
ret++;
}
return ret; /* nuber of deleted nodes */
}

Resources