reading from a file to make an array using C [closed] - c

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
How do I make an array by reading from a .txt file??
I'm making a bidding(auction) program. I need to read integers from the .txt and use those in an array. I am confused as to how I would go about that in my program.
The txt is as follows:
100 15
200 20
300 25
400 30
500 35

It is definitely recommended to show one's own effort while asking the question. However, to give you a jump start, please find a couple of solutions as below.
One possible illustrative solution using a static array is as in Solution 1 below. The assumption in the solution below is that the number of elements is known and is less than 32. If wish to keep it truly dynamic, you will have to implement a solution using a linked list as in Solution 2 below.
Solution 1: Fixed Array based approach
int main()
{
FILE *finp;
int someArr[32];
int i, ctr = 0;
finp = fopen("haha.txt", "r");
if(NULL == finp)
{
printf("Unable to open file\n");
exit(-1);
}
while((!feof(finp)) && (ctr < 32))
{
fscanf(finp, "%d ", &someArr[ctr++]);
}
for(i = 0; i < (ctr -1); i++)
{
printf("%d==>", someArr[i]);
}
printf("%d\n", someArr[i]);
fclose(finp); //Close the file pointer
return 0;
}
The expected output of this program is
100==>15==>200==>20==>300==>25==>400==>30==>500==>35
Solution 2: Linked List based solution
Further to my earlier comment, please find an alternative dynamic solution which doesn't require a prior knowledge on the number of elements as below.
typedef struct node {
int value;
struct node *next;
}node;
void createList(FILE *fInp, node **headBase)
{
node *currNode;
node *head = *headBase;
node *tail;
while(!feof(fInp))
{
currNode = malloc(sizeof(struct node));
fscanf(fInp, "%d ", &currNode->value);
currNode->next = NULL;
if(NULL == head)
{
head = currNode;
tail = currNode;
}
else
{
tail->next = currNode;
tail = currNode;
}
}
//Store back the updated head pointer
*headBase = head;
}
void printList(node **headBase)
{
node *tmpNode = *headBase;
while(tmpNode->next != NULL)
{
printf("%d-->", tmpNode->value);
tmpNode = tmpNode->next;
}
printf("%d\n", tmpNode->value);
}
void deleteList(node **headBase)
{
node *head = *headBase;
node *tmp;
while(NULL != head)
{
tmp = head; // Get a temp pointer
head = head->next; // Move head pointer
tmp->next = NULL; // break the link
printf("<< Deleted Node: %d\n", tmp->value);
free(tmp);
}
// Store the head pointer back which should be NULL
*headBase = head;
}
int main()
{
FILE *finp;
node *head = NULL;
finp = fopen("haha.txt", "r");
if(NULL == finp)
{
printf("Unable to open file\n");
exit(-1);
}
createList(finp, &head);
printList(&head);
deleteList(&head);
fclose(finp);
return 0;
}
The expected output of this program is
100-->15-->200-->20-->300-->25-->400-->30-->500-->35
<< Deleted Node: 100
<< Deleted Node: 15
<< Deleted Node: 200
<< Deleted Node: 20
<< Deleted Node: 300
<< Deleted Node: 25
<< Deleted Node: 400
<< Deleted Node: 30
<< Deleted Node: 500
<< Deleted Node: 35

Supposing you don't know how many integers can be found in the input file, you could define a max value.
You must too include stdio.h and stdlib.h
#define MAX 255
int main() {
FILE *file = fopen("input.txt", "r");
int integers[MAX];
int i = 0;
if (file != NULL) {
while (!feof(file) && i < MAX) {
if (fscanf(file, "%d", &integers[i++]) != -1) {
printf("%d ", integers[i-1]);
}
}
fclose(file);
} else {
printf("Unable to open file");
return EXIT_FAILURE;
}
return 0;
}

Related

how to take input from a text scanf and put it in linkedlist in C

i'm trying to take input from a text file and put the value in a linked list variables,
my file(text.txt) in in the following format:
the first value is my burst time, the second arrival and the last value is the priority, i want to make operations on all of these value from the same line like burst time + prioriy and so on, and when the operation for the first line ends up, the program should pass to the next line until the time the prom will fin the EOF.
now the big issue is when i'm trying to read each character and store each in a variable of a linked list for manipulation. find down my code:
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int x;
struct Node* next;
}Node;
void insert_end(Node** root, int value)
{
Node* new_node = malloc(sizeof(Node));
if(new_node == NULL)
{
exit(1);
}
new_node->next = NULL;
new_node->x = value;
if(*root == NULL)
{
*root = new_node;
return;
}
Node* curr = *root;
while(curr->next != NULL)
{
curr = curr->next;
}
curr->next = new_node;
}
//the part i'm reading the file
void deserialize(Node** root)
{
FILE* file = fopen("text.txt","r");
if(file == NULL)
{
exit(2);
}
int val;
int val2;
while(fscanf(file, "%d", &val)>0)
{
insert_end(root, val);
}
fclose(file);
}
int main(int argc, char* argv[])
{
Node* root = NULL;
if(root == NULL)
{
exit(2);
}
root->x = 15;
root->next = NULL;
deserialize(&root);
for(Node* curr = root; curr != NULL; curr = curr->next)
{
printf("%d\n",curr->x);
}
deallocate(&root);
return 0;
}
i really need your help, thank you
A complete example including serialize() deserialize() and linked list functions are here after the "Now What?" paragraph
May be you could write this in 2 steps. First try to consume the data on file, then put the code to insert this into a linked list..
About the struct
typedef struct Node
{
int x;
struct Node* next;
} Node;
maybe not the best way to describe a linked list. This is just a node and not a list. You will be better served with a bit of encapsulation. A list has metadata and pointers to nodes. Nodes points to or contain data. A list is NOT a node. A node is NOT a list. Program a linked list with just a node is problematic at best. Many loose pointers and your case even more problematic Node** pointers.
Compare with something like
typedef struct
{
unsigned burst;
unsigned arrival;
unsigned priority;
} Info;
typedef struct st_node
{
Info* info;
struct st_node* next;
struct st_node* prev;
} Node;
typedef struct
{
Node* head;
Node* tail;
unsigned size;
} List;
List* create();
List* destroy(List* list);
int insert(Info* one_item, List* list);
And see that a list is a list of nodes. Nodes points to info and info is the unit of data. Any data.
insert() inserts an item into a list, create() and destroy() manages lists and the encapsulation makes everything far more easier than just using pointers and pointers to pointers.
Consuming the file
Using this file as input.txt
2:101:34
20:10:3
5:1:4
and this data unit
typedef struct
{
unsigned burst;
unsigned arrival;
unsigned priority;
} Info;
See that the input is a CSV --- from Comma Separated Values --- file, a format from '70s. The separator is a ':'.
scanf() and family was written for this: Scan Formatted Files, hence the name. It is a scanner. So it is easier to just use it in this way.
See this example
List* deserialize(const char* file)
{
FILE* in = fopen(file, "r");
if (in == NULL) return NULL;
Info info = {0};
List* new_l = create(); // new list here
while (3 == fscanf(
in, "%d:%d:%d", &info.arrival,
&info.burst, &info.priority))
{
fprintf(
stderr, "%d:%d:%d\n", info.arrival, info.burst,
info.priority);
insert(&info, new_l); // insert data into list
};
fclose(in);
return new_l; // returns a list with the data on file
}
and the output
2:101:34
20:10:3
5:1:4
when called as
List* new_list = deserialize("input.txt");
as expected. And a List is returned with the data on file...
The complete code
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
unsigned burst;
unsigned arrival;
unsigned priority;
} Info;
typedef struct st_node
{
Info* info;
struct st_node* next;
struct st_node* prev;
} Node;
typedef struct
{
Node* head;
Node* tail;
unsigned size;
} List;
int insert(Info* one_item, List* list);
List* create();
List* destroy(List*);
List* deserialize(const char* file)
{
FILE* in = fopen(file, "r");
if (in == NULL) return NULL;
Info info = {};
List* new_l = create(); // new list here
while (3 == fscanf(
in, "%d:%d:%d", &info.arrival,
&info.burst, &info.priority))
{
fprintf(
stderr, "%d:%d:%d\n", info.arrival, info.burst,
info.priority);
insert(&info, new_l); // insert data into list
};
fclose(in);
return new_l; // returns a list with the data on file
}
int main(void)
{
List* new_list = deserialize("input.txt");
new_list = destroy(new_list);
return 0;
}
int insert(Info* one_item, List* list) { return 0; }
List* create()
{
List* L = (List*)malloc(sizeof(List));
if (L == NULL) return NULL;
L->size = 0;
L->head = NULL;
L->tail = NULL;
return L;
}
List* destroy(List* list) { return NULL; }
Now what?
Now we have
List* deserialize(const char* file)
that can consume the data from a file like this
input.txt:
3:2:1
6:4:2
12:8:3
24:16:4
by using
List* new_list = deserialize("input.txt");
But deserialize() just prints the data on stderr
We want a linked list of the dataset.
I will write an example below, but step by step in order to cover other cases for other readers.
A linked list
I will add a sequence number to the nodes just to help in testing.
The linked list has nothing to do with our problem, or else we will need one implementation of linked list for every program in life. In fact would be great if the code for the list was in another source code file, in order to be used anywhere else.
this is the example for List
typedef struct st_node
{
int num;
Info* info;
struct st_node* next;
struct st_node* prev;
} Node;
typedef struct
{
size_t size;
Node* head;
Node* tail;
} List;
A list of nodes, nodes pointing to info.
info is from now on
// info is the thing in the list
typedef struct
{
unsigned burst;
unsigned arrival;
unsigned priority;
unsigned seq; // sequence number for testing
} Info;
// this is a helper to format a single node listing
int show_i(Info*, const char*);
The code for show_i() is simple
int show_i(Info* info, const char* msg)
{
if (info == NULL) return -1;
if (msg != NULL) printf("%s", msg);
printf(
"#%4d: B:%4d A:%4d P:%4d\n", info->seq, info->burst,
info->arrival, info->priority);
return 0;
}
And the reason for this to exist is to provided some encapsulation on the way the nodes are printed.
And the functions we will use here are the obvious ones:
List* create_l();
List* destroy_l(List*);
int empty(List*);
int insert_n(Info*, List*);
int remove_n(List*);
int show_l(List*, const char*);
int size(List*);
This is a very simple example so we will assume a standard queue, FIFO (First In First Out) one, with items added at the end and removed from the front.
empty() returns 1 if the list is empty
size() returns the expected size
show_l() shows the list contents with an optional title message
the other functions work as expected.
A simple C implementation of the linked list
Functions have no more than 10 to 15 lines
List* destroy_l(List* L)
{
if (L == NULL) return NULL;
Node* p = L->head;
for (size_t i = 0; i < L->size; i += 1)
{ // remove one by one
Node* nx = p->next;
free(p->info); // free data
free(p); // free node
p = nx;
}; // for
free(L); // free list
return NULL; // to invalidate pointer
}
int empty(List* L)
{
if (L == NULL) return 0;
return (L->size == 0);
}
List* create_l()
{
List* nv = (List*)malloc(sizeof(List));
if (nv == NULL) return NULL;
nv->size = 0; // vazia
nv->head = NULL;
nv->tail = NULL;
return nv;
}
int insert_n(Info* info, List* L)
{ // inserts at the end of list
static unsigned seq = 1000;
if (L == NULL) return -1;
// new node here
Node* nv = (Node*)malloc(sizeof(Node));
// new data here: always copy
nv->info = (Info*)malloc(sizeof(Info));
*(nv->info) = *info;
nv->info->seq = seq++; // USN
nv->prev = L->tail;
nv->next = NULL;
// ajusta os ponteiros da lista
L->size += 1; // conta o novo
if (L->size == 1)
L->head = nv;
else { L->tail->next = nv; }
L->tail = nv;
return (int)L->size;
}
int remove_n(List* L)
{ // remove from start
if (L == NULL) return -1;
if (L->size == 0) return -2;
Node* p = L->head->next;
free(L->head->info); // data
free(L->head); // node
L->head = p;
L->size -= 1;
if (L->size == 0) L->tail = NULL;
return (int)L->size;
}
int show_l(List* L, const char* tit)
{
if (L == NULL) return -1;
if (tit != NULL) printf("%s", tit);
if (L->size == 0)
printf(" no elements\n");
else
printf(" %zd elements:\n", L->size);
if (L->head != NULL)
printf(" [First seq: %d", L->head->info->seq);
if (L->tail != NULL)
printf(" Last seq: %d]\n", L->tail->info->seq);
Node* p = L->head;
for (size_t i = 0; i < L->size; i += 1)
{
show_i(p->info, "\t");
p = p->next;
}
printf("\n");
return 0;
}
int size(List* L)
{
if (L == NULL) return 0;
return (int)L->size;
}
A test program for the list code
#include <stdio.h>
#include "v2-l.h"
int main(void)
{
Info info = {1, 1, 1, 1};
List* my_list = create_l();
show_l(my_list, "empty list...\n");
my_list = destroy_l(my_list);
my_list = create_l();
// test size
const int test_size = 3;
printf("[Testing with %d elements]\n\n\n", test_size);
for (int i = 0; i < test_size; i += 1)
{
info.priority = i; // just for testing
insert_n(&info, my_list);
};
char message[] = "NNNNNN elements inserted\n";
sprintf(message, "%d elements inserted\n", test_size);
show_l(my_list, message);
int res = 0;
while (res >= 0)
{
printf("\tabout to remove 1st element:\n");
res = remove_n(my_list);
printf(
"\
\tremove_l() returned %d\n\
\tsize() returned %d\n\
\tempty() returned %d\n",
res, size(my_list), empty(my_list));
show_l(my_list, "\n ==> List now:\n");
if (res < 0) break;
}; // while()
show_l(my_list, "On exit\n");
my_list = destroy_l(my_list);
return 0;
}
The idea: creates a list with test_size elements and then remove one by one until error, calling the functions. Then the list is destroyed.
output from test
empty list...
no elements
[Testing with 3 elements]
3 elements inserted
3 elements:
[First seq: 1000 Last seq: 1002]
#1000: B: 1 A: 1 P: 0
#1001: B: 1 A: 1 P: 1
#1002: B: 1 A: 1 P: 2
about to remove 1st element:
remove_l() returned 2
size() returned 2
empty() returned 0
==> List now:
2 elements:
[First seq: 1001 Last seq: 1002]
#1001: B: 1 A: 1 P: 1
#1002: B: 1 A: 1 P: 2
about to remove 1st element:
remove_l() returned 1
size() returned 1
empty() returned 0
==> List now:
1 elements:
[First seq: 1002 Last seq: 1002]
#1002: B: 1 A: 1 P: 2
about to remove 1st element:
remove_l() returned 0
size() returned 0
empty() returned 1
==> List now:
no elements
about to remove 1st element:
remove_l() returned -2
size() returned 0
empty() returned 1
==> List now:
no elements
On exit
no elements
Using the list on the original program
// here goes the program target
List* deserialize(const char* file);
int serialize(List* list, const char* file);
double pri_avg(List*);
The next obvious step is to use the 1st program and consume the file, but this time writing the data into a linked list, and then calling serialize() to create a new file with the data in the list.
Sure, both files must have the same data and the program will test itself.
As you asked, #jonathan pascal, the function pri_avg() computes an useless priority average, just to show how to compute something using the data from all nodes in the list.
Note that this is the same logic as in showing the list contents in show_l(). This is called a filter and in languages like C we can just pass a function address to a function that loops over the code, and use the same code to do anything with the dataset. In C++ is, for example, a for_each() function that does just this. All these functions here has the same logic.
Example implementation of the 3 functions
List* deserialize(const char* file)
{
FILE* in = fopen(file, "r");
if (in == NULL) return NULL;
Info info = {0};
List* new_l = create_l(); // new list here
while (3 == fscanf(
in, "%d:%d:%d", &info.burst,
&info.arrival, &info.priority))
{
// fprintf(
// stderr, "%d:%d:%d\n", info.arrival,
// info.burst, info.priority);
insert_n(&info, new_l); // insert data into list
};
fclose(in);
return new_l; // returns a list with the data on file
};
int serialize(List* L, const char* file)
{
if (L == NULL) return -1;
if (file == NULL)
{
printf("Missing file name\n");
return -2;
}
if (L->size == 0)
{
printf("Dataset is empty\n");
return -3;
}
FILE* out = fopen(file, "w");
if (out == NULL) return -3;
fprintf(
stderr,
"serialize(): writing %d elements into \"%s\"\n",
size(L), file);
Node* p = L->head;
for (size_t i = 0; i < L->size; i += 1)
{
fprintf(
out, "%d:%d:%d\n", p->info->burst,
p->info->arrival, p->info->priority);
p = p->next;
}
fprintf(out, "\n");
fclose(out);
fprintf(stderr, "\"%s\" closed\n", file);
return 0;
}
// get the priority average from the list
double pri_avg(List* L)
{
if (L == NULL) return -1;
if (L->size == 0) return 0.; // easy
double avg = 0.;
Node* p = L->head;
for (size_t i = 0; i < L->size; i += 1)
{ // here we have node data, one
// at a time
avg = avg + p->info->priority;
p = p->next;
};
return (double)avg / size(L);
}
Testing the 3 functions
#include <stdio.h>
#include "v2-l.h"
int main(void)
{
const char* in_file = "input.txt";
printf(
"deserialize(): building list from \"%s\"\n",
in_file);
List* my_list = deserialize(in_file);
show_l(my_list, " ==> As read from file...\n");
printf("average priority is %6.2f\n", pri_avg(my_list));
const char* out_file = "another.txt";
int res = serialize(my_list, out_file);
printf(
"serialize(): dumping list into \"%s\" "
"returned %d\n",
out_file, res);
my_list = destroy_l(my_list);
return 0;
}
And we have full circle over the problem: a CSV file is read from disk, a linked list is built, some values are computed, the list is written to disk in another file.
test output
deserialize(): building list from "input.txt"
==> As read from file...
4 elements:
[First seq: 1000 Last seq: 1003]
#1000: B: 3 A: 2 P: 1
#1001: B: 6 A: 4 P: 2
#1002: B: 12 A: 8 P: 3
#1003: B: 24 A: 16 P: 4
average priority is 2.50
serialize(): writing 4 elements into "another.txt"
"another.txt" closed
serialize(): dumping list into "another.txt" returned 0
The format string %d does not match the input :101 ,since : cannot be part of an integer. So scanf("%d") consumes nothing and the : is left in the input stream. You could use: while(fscanf(file, "%4d:", &val) == 1). If you are reading the last value on a line, the : will not match, but in this case you don't care. You might want to use fscanf(file, "%4d:%4d:%4d", ...) == 3 if you want to check the format of the input (ie, always exactly 3 inputs per line, so you can reject lines like 1:2:3:4:5:6:7). YMMV

Memory access violations when trying to read from structs inside of other structs

I am having trouble figuring out how to do this correctly. I have a linked list of nodes then those nodes have pointers put into an array contained in that node. These nodes make up a sort of one-way graph between the nodes. I must then traverse the nodes randomly until the node "Home" is reached.
The main issue I'm having is assigning the graph nodes into the list nodes. I want the function to take in the head of the list, the names of the nodes and the weight (cost to travel between nodes). I'm not sure how to do this correctly and I don't know what I did but I think there's an infinite loop somehow. Any help is greatly appreciated.
The input file is structured as such:
Applebees
GroundRound
BlueMoose
DrunkenNoodle
Home
STOP
Applebees BlueMoose 10
Applebees DrunkenNoodle 13
GroundRound Applebees 2
GroundRound DrunkenNoodle 7
GroundRound Home 52
STOP STOP 0
GroundRound
Ignore the print statements in graphInsert() those are me trying to debug the loops.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
struct graphNode {
char name[100]; // Establishment name
int arcCnt; // Number of outgoing arc from this node
int weights[10]; // Weights of each outgoing arc from this node
struct graphNode* arcs[10]; // Holds other graph nodes that are connected to this node (this node is source)
};
struct listNode {
char name[100]; // Establishment name
struct listNode* next;
struct graphNode* graph; // Pointer into graph
};
void listInsert(struct listNode **head, char name[100]) {
// setup new nodes
struct graphNode* newGraph = (struct graphNode*)malloc(sizeof(struct graphNode));
for (int i = 0; i < 100; i++) {
newGraph->name[i] = name[i];
}
for (int i = 0; i < 10; i++) {
newGraph->arcs[i] = NULL;
}
newGraph->arcCnt = 0;
struct listNode* newNode = (struct listNode*)malloc(sizeof(struct listNode));
for (int i = 0; i < 100; i++) {
newNode->name[i] = name[i];
}
newNode->next = NULL;
newNode->graph = newGraph;
// check if head is NULL
if (*head == NULL) {
*head = newNode;
return;
}
// if the list is populated then add the node to the end
struct listNode* current = *head;
while (current->next != NULL) {
current = current->next;
}
current->next = newNode;
}
void graphInsert(struct listNode** head, char src[100], char dst[100], int weight) {
struct listNode* srcNode = *head;
printf("CALL:");
while (srcNode->next != NULL) { // loop through list to find src
printf("%s %s", srcNode->name, src);
if (strcmp(srcNode->name, src) == 0) { // when it finds the name, find the dst update the graph node data
printf("FOUND");
struct listNode* dstNode = *head;
while (dstNode->next != NULL) { // this loop is to find the pointer to the dst node
printf(" %s %s", dstNode->name, dst);
if (strcmp(dstNode->name, src) == 0) { // when it finds name finally update all the info
printf("FOUND");
// assign the new arc to the right spot based on arcCnt (how many arcs there are), then return to exit the loops
srcNode->graph->arcs[srcNode->graph->arcCnt] = dstNode->graph;
srcNode->graph->weights[srcNode->graph->arcCnt] = weight;
srcNode->graph->arcCnt++;
return;
}
dstNode = dstNode->next;
}
}
srcNode = srcNode->next;
}
}
int main(){
srand(2021);
// setup variables
struct listNode* head = NULL;
struct graphNode* sourceNode = NULL;
FILE* data = fopen("./hw10.data", "r");
int i = 0;
int section = 1; // flag to read the file correctly
// this loop reads the file
while (1) {
char name[100];
char name2[100];
int weight = 0;
if (section == 1) { // reads the first section
fscanf(data, "%100s", name);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else { // if its not the end of the section then add the name to the linked list
listInsert(&head, name);
}
} else if (section == 2) { // reads the first section and builds the graph
fscanf(data, "%100s %100s %d", name, name2, &weight);
if (strcmp(name, "STOP") == 0) { // if end of section then increment section counter
section++;
} else {
//graphInsert(&head, name, name2, weight);
}
} else if (section == 3) { // this section only reads one line and gets the
char tmp[100];
fscanf(data, "%100s", tmp);
struct listNode* current = head;
while (current->next != NULL) { // loop through to find the right node for the name
if (strcmp(current->name, tmp) == 0) { // if names are equal update the node
sourceNode = current->graph;
break;
}
current = current->next;
}
}
if (feof(data)) break;
i++;
}
// debug print data
printf("\n");
struct listNode* current = head;
while (current != NULL) {
printf("%s\n", current->name);
current = current->next;
}
printf("\n");
// starting node
printf("%s ", sourceNode->name);
// now walk through the graph from sourceNode until we reach the node "Home"
int totalWeight = 0;
i = 0;
while (i < 100) {
char* tmp = sourceNode->name;
if (strcmp(tmp, "Home") == 0) { // if were home then exit program
// ending node and cost
printf("%s %d", sourceNode->name, totalWeight);
return 0;
} else { // if were not home then keep looping
int index = (rand() % sourceNode->arcCnt); // Generates random number between 0 and sourceNode->arcCnt
sourceNode = sourceNode->arcs[index];
//printf("Going to: %s, Index: %d", sourceNode->name, totalWeight);
}
i++;
}
return 0;
}

How can I reverse the order of a linked list?

I am trying to print out the results of the linked list in the reverse order that they were entered in. The program takes 3 inputs, Song name, song length (in seconds) and copyright. The program should take the list of songs and print the in the reverse order that they were entered in.
I am not too familiar with linked list. This is my first time using it as sort of a database.
#include <stdio.h>
#include <stdlib.h>
#pragma warning(disable:4996)
//defining struct
typedef struct node
{
char songName[20];
int songLength;
int copyright;
struct node * next;
}node;
//defining prototypes
node *create(int n);
void display(node *head);
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(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);
//fgets(temp->songName, 20, stdin);
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(node *head)
{
node *p = NULL;
if (head == NULL)
{
printf("List is empty\n");
}
else
{
p = head;
while (p != NULL)
{
printf("Song: %s, ", p->songName);
printf("%d minutes, ", p->songLength);
if (p->copyright == 1)
{
printf("Copyrighted\n");
}
else if (p->copyright == 0)
{
printf("No copyright\n");
}
p = p->next;
}
}
}
So if Input the following:
Song 1 - All Star (song name), 237 (seconds), 0 (no copyrights)
song 2 - Crab Rave, 193, 0
song 3 - 7 rings, 185, 1(copyrights)
The output should be:
7 rings, 185, 1
Crab Rave, 193, 0
All Star, 237, 0
If you have a single (forward) linked list, the probably easiest way to print it in reverse order is using recursion:
void display_recursive(node *n) {
if (!n) {
return;
}
display_recursive(n->next);
printf("Song: %s, ", n->songName);
...
}
Recursion means that a function is calling itself (until some end-condition, the anchor, is reached).
By that way, program flow will build up a "stack" of display_recursive- function calls, with the first node, then the second node, ..., until it reaches the last node; by then, recursion stops, and the print part of display_recursive is handled, starting with the last node backwards.
Hope this explanation helps; Try it out in the debugger to see what happens.

Linked list — deletion of nodes which contain prime numbers [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 5 years ago.
Improve this question
I have written a code in the C language which will create a linked list. The linked list structre has two fields, namely data and next; data contains integer data, next is a structure pointer.
The program asks the user to input data into the list. Once the data has been entered, the program will go through the list and check which data in the node contains a prime number. If it finds one such node, it will delete it and link the next node to the previous node, but I am getting a segmentation fault error and I am unable to solve.
I am putting below the code. Can you please be kind enough to help me solve it as I do not know how to find the problem?
#include <stdio.h>
#include <stdlib.h>
struct node {
int data;
struct node *next;
};
typedef struct node *nptr;
nptr H, h, n;
void deletetheprime(struct node**);
void display();
int prime(int);
int main() {
nptr temp1, temp;
int i, N, p;
printf("\n if list is completed enter 999\n");
for (;;) {
printf("\n enter the data \n");
scanf("%d", &i);
if (i == 999)
break;
else
if (H == NULL) {
H = h = (nptr)malloc(sizeof(struct node));
H->data = i;
H->next = NULL;
} else {
n = (nptr)malloc(sizeof(struct node));
n->data = i;
n->next = NULL;
h->next = n;
h = n;
}
}
printf("\n data before deletion\n");
display();
temp = H;
while (temp != NULL) {
N = temp->next->data;
p = prime(N);
if (p == 1) {
deletetheprime(&temp);
} else {
temp = temp->next;
}
}
printf("\n the data after deletion is\n");
display();
return 0;
}
void deletetheprime(struct node **temp2) {
nptr temp, temp1;
temp = *temp2;
temp1 = temp->next;
temp->next = temp->next->next;
free(temp1);
temp = temp->next;
}
int prime(int i) {
int j, p = 0;
for (j = 2; j <= i / 2; i++) {
if (i % j == 0) {
break;
}
}
if (j > i / 2) {
p = 1;
}
return p;
}
void display() {
nptr temp;
temp = H;
while (temp != NULL) {
printf("\n %d", temp->data);
temp = temp->next;
}
}
The problem is here:
while (temp != NULL) {
N = temp->next->data;
When you reach the last element of the list, temp is not NULL, but temp->next is so temp->next->data has undefined behavior.
There are other problems:
your prime() function is inefficient and will return 1 for 0 and 1.
you deletetheprime() function deletes the node and updates the pointer in the callers scope, but the caller does not update the link in the previous node nor the H pointer if the deleted node is the first.
you use global variables for no good reason, you should pass H to display() and make all variables local in main().
you never free the allocated objects, it is good style to free everything you allocate.
you should not hide pointers behind typedefs, make node a typedef for struct node but keep pointers visible, it is a good habit to avoid confusing both the reader and the programmer.
To delete the node, you should use the pointer to link trick:
for (struct node **p = &H; *p;) {
if (prime((*p)->data) {
nptr np = *p;
*p = np->next;
free(np);
} else {
p = &(*p)->next;
}
}
p initially points to the head pointer H and subsequently points to the next member of the previous node. It can be used to update the head pointer or the link in the previous node when a node to be deleted is found.
Here is a corrected and simplified version:
#include <stdio.h>
#include <stdlib.h>
typedef struct node {
int data;
struct node *next;
} node;
int isprime(int n) {
if (n < 2)
return 0;
if (n % 2 == 0)
return n == 2;
for (int i = 3; i * i <= n; i += 2) {
if (n % i == 0) {
return 0;
}
}
return 1;
}
void display(const node *temp) {
while (temp != NULL) {
printf(" %d", temp->data);
temp = temp->next;
}
printf("\n");
}
int main(void) {
node *H = NULL;
node **lastp = &H;
node *n;
int i;
printf("Enter values, when list is completed enter 999\n");
for (;;) {
printf("\n enter the data: ");
if (scanf("%d", &i) != 1 || i == 999)
break;
n = malloc(sizeof(*n));
if (n == NULL)
break;
n->data = i;
n->next = NULL;
*lastp = n;
lastp = &n->next;
}
printf("\n data before deletion: ");
display(H);
for (node **p = &H; *p;) {
if (isprime((*p)->data)) {
n = *p;
*p = n->next;
free(n);
} else {
p = &(*p)->next;
}
}
printf("\n the data after deletion is: ");
display(H);
/* free the list */
while (H != NULL) {
n = H;
H = n->next;
free(n);
}
return 0;
}
I shall attribute your please solve it! stance to your poor command of the English language. Please learn to improve both your communications and your programming skills by carefully studying answers on this site.
The problem occurs here, in main
while(temp!=NULL)
{
N=temp->next->data;
...
You are checking if temp is not NULL, which is correct, but accessing data of next node, which can be NULL, and has to be NULL near the end of the list, which leads to undefined behavior.
Simply modify it to
while(temp!=NULL)
{
N=temp->data;
...
Where you are sure that temp isn't NULL and you won't get segmentation error here. And it'll work.
Or if you need to access data of temp->next->next node, you've got to check if next->next isn't NULL as well.
while(temp!=NULL)
{
if (temp->next->next != NULL)
{
N=temp->next->data;
}
else // temp->next->next is NULL so you can't access the data
...

Linked List insertion in Beginning

I am trying basic creation of linked list using C. I have written the following code which is working up until first node but fails eventually on second one. I think the issue is where I am trying to display the node values in list separated by arrow(->). I think my logic is right but please correct me. Thanks in advance
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
NODE *node1, *node2, *start, *save;
int main()
{
node1 = (NODE *)malloc(sizeof(NODE));
int i = 0;
start = NULL;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
scanf("%d", &inf);
node1->number = inf;
node1->next = NULL;
if(start == NULL)
{
start = node1;
save = node1;
}
else
{
// save=start;
// start=node1;
// node1->next=save;
node1->next = start;
start = node1;
}
while(node1 != NULL)
{
printf("%d ->",node1->number);
node1 = node1->next;
}
}
return 0;
}
The issues are
How you're allocating your nodes for insertion (i.e. save for one, you're not).
How they're placed in the list once you fix the above.
Don't cast malloc in C programs (read here for why).
Fail to check the success of your scanf invoke.
Fail to check the success of your malloc invoke
Before you get discouraged, things you did correctly:
Did not mask a node pointer in a typedef
Properly included a MCVE for review
Prospected the things you may be doing wrong.
A very simple example of iterating three values into a linked list would look something like this:
#include <stdio.h>
#include <stdlib.h>
struct node
{
int number;
struct node *next;
};
typedef struct node NODE;
int main()
{
NODE *head = NULL, *p;
int i = 0;
for(i = 0; i < 3; i++)
{
int inf;
printf("Enter node value:");
if (scanf("%d", &inf) == 1)
{
p = malloc(sizeof *p);
if (p != NULL)
{
p->number = inf;
p->next = head;
head = p;
}
else
{
perror("Failed to allocate new node");
return EXIT_FAILURE;
}
}
else
{
// failed to read data. break
break;
}
// report current linked list
printf("%d", p->number);
for (p=p->next; p; p = p->next)
printf(" -> %d", p->number);
fputc('\n', stdout);
}
// cleanup the linked list
while (head)
{
p = head;
head = head->next;
free(p);
}
head = NULL;
return 0;
}
Input
The values 1 2 3 are input upon being prompted:
Output
Enter node value:1
1
Enter node value:2
2 -> 1
Enter node value:3
3 -> 2 -> 1
Best of luck.
You should use malloc() inside for loop.
Since it is outside, same memory is being used.
As said by Vamsi, you should use malloc to put the nodes on the heap. You also generally shouldn't cast the output of malloc, it isn't needed. And then you could play around with making a doubly-linked list, where you also have a prev pointer inside your struct.

Resources