#include<stdio.h>
#include<stdlib.h>
struct nodetag{
int ndata;
struct nodetag *pNext;
};
typedef struct nodetag nodetag;
int main(){
nodetag *p1=NULL,*bago,*last,*ptemp;
int i,x,y;
printf ("\nEnter number of nodes: ");
scanf ("%d", &i);
y=i;
while (i)
{
if (p1 == NULL)
{
p1 = malloc(sizeof(nodetag));
last = p1;
p1->pNext = NULL;
scanf("%d",&p1->ndata);
}
else
{
bago = malloc(sizeof(nodetag));
last->pNext = bago;
bago->pNext = NULL;
scanf("%d",&bago->ndata);
}
i--;
}
ptemp = p1;
for(x=0;x<y;x++){
printf("%d",ptemp->ndata);
ptemp=ptemp->pNext;
}
getch();
return 0;
}
can i copy the whole nodes to ptemp to avoid the pfirst getting moved?
when i ran the code it seems that it only prints the first and last data of the nodes.
how can i access the second node when the number of nodes is more than 2?
im focusing on printing the data in the nodes
ptemp = p1;
for(x=0;x<y;x++){
printf("%d",ptemp->ndata);
ptemp=ptemp->pNext;
this seems that it crashes the whole program
bago->pNext = NULL;
After this add this line:
last = bago;
Now errors in your code:
You are not updating the last pointer hence every time you assign a value it is overwritten on the second value assigned.
You have never freed the mallocd memory, before exiting main() free all the memory by iterating over the list as you do while printing.
getch() is not a standard library function, hence not portable, you should use getchar() instead.
EDIT: (On OP's comment)
Well, try to understand it yourself, its very simple. Step over/Execute the code manually by hand.
else
{
bago = malloc(sizeof(nodetag));
last->pNext = bago;
bago->pNext = NULL;
scanf("%d",&bago->ndata);
last = last->pNext; /*you need add this statements*/
}
sorry ,my English is not good.
I can not explain it in English.
Related
I am beginner in programming. thanks for helping me.
I am trying to make a linked list in strings.
inputs are strings, and it ends if input is "exit".
But when i compile it, it prints out the last inputs only, and i can't solve it!
From function addrear, it distinguishes whether data is stored in linked list for the first time of not. and store data and links to another Node appropriately.
From function printlist, it starts from the start of linked list and prints out the data in each nodes.
I've tried it with integer type , and when this code was executed with int , not string, it worked correctly, so i think error came out from character array.
ex) input1 "dump",
input2 "end",
input3 "dir",
input4 "exit",
than output would be
dump,
end,
dir,
exit
but it comes out
exit
exit
exit
exit
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char instruction[1000];
struct Node {
struct Node* next;
char* data;
};
struct Node* pStart = NULL;
struct Node* pEnd = NULL;
void addrear(char* val)
{
struct Node* Current;
Current = (struct Node*)malloc(sizeof(struct Node));
Current->data = val;
Current->next = NULL;
//printf("%s\n", Current->data);
if (pStart == NULL)
{
pStart = Current;
pEnd = Current;
}
else
{
pEnd->next = Current;
pEnd = Current;
}
}
void printlist(struct Node* Current)
{
Current = pStart;
while (Current != NULL)
{
printf("%s\n", Current->data);
Current = Current->next;
}
}
int main()
{
int i;
while (1)
{
printf("sicsim> ");
fgets(instruction, sizeof(instruction), stdin);
instruction[strlen(instruction) - 1] = '\0';
addrear(instruction);
if (strcmp(instruction, "exit") == 0)
{
break;
}
}
printlist(pStart);
}
As MZB answered, your problem is you are confusing reference and value.
You said:
"I've tried it with integer type , and when this code was executed with int , not string, it worked correctly, so i think error came out from character array."
There's a huge difference between assigning the value of int and assigning a string. you are going to get the value of this int anyway- you don't care where he "lives". It is also true when we talk about char, but if you talk about strings - you want to point to this string - so you want to point at some place which can hold your data and would not be modified.
If you want to save this string you need to know that the string storage place would not be accessed.
Therefore you should copy char by char so you wouldn't care if "instruction" will be assign as something else.
Your mistake is that you are storing a pointer to the instruction buffer in the Node structure. Each time you read a string, you overwrite that buffer with the string you read in.
You need to allocate memory for each string.
If you're learning C++, check out the documentation on "new" (how you should allocate the space for Node etc.) malloc is a lower-level C method of doing things.
Hello and thanks to all who bothered to read! I am currently working on a program that uses a singly linked list to print out a pattern based on the first letter of the color element and first element in the details int address array shown below.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct Node{
char* color;
int** details;
struct Node* next;
}Node;
Node* light_info(char *filename){
Node* head = malloc(sizeof(Node));
Node* second = malloc(sizeof(Node));
Node* third = malloc(sizeof(Node));
Node* fourth = malloc(sizeof(Node));
Node* fifth = malloc(sizeof(Node));
Node* sixth = malloc(sizeof(Node));
head->next = second;
second->next = third;
third->next = fourth;
fourth->next = fifth;
fifth->next = sixth;
sixth->next = NULL;
FILE* fp = fopen(filename, "r");
char* token;
int num1, num2;
int* ptr1 = &num1;
int* ptr2 = &num2;
char line[250];
Node* current = head;
if(head==NULL||second==NULL||third==NULL||fourth==NULL||fifth==NULL||sixth==NULL){
printf("Error. Program has amnesia, not allocating memory...");
}
else{
while((fgets(line,250,fp)!=NULL)&&(current!=NULL)){
token = strtok(line, ",\n");
current->color = malloc(20);
current->color = token;
current->details = malloc(sizeof(ptr1)*2);
token = strtok(NULL, ",\n");
num1 = atoi(token);
current->details[0]=ptr1;
token = strtok(NULL, ",\n");
num2 = atoi(token);
current->details[1]=ptr2;
current = current->next;
}
}
return head;
}
/*Takes a Node pointer as a parameter, and iterates through the linked list,
printing out a number of dashes for each light's brightness score.*/
void off(Node* h){
printf("\n***Turning lights off:\n");
while(h!=NULL){
int i;
int* ptr = h->details[0];
int b = *ptr;
for(i=0;i<b;i++){
printf("-");
}
printf(" ");
h=h->next;
}
printf("\n");
}
/*Takes a Node pointer as a parameter, and iterates through the linked list,
printing out the first letter of each color the amount of times each light is bright.*/
void on(Node* h){
printf("\n***Turning lights on:\n");
while(h!=NULL){
int i;
int* ptr = h->details[0];
int b = *ptr;
for(i=0;i<b;i++){
printf("%c",h->color[0]);
}
printf(" ");
h=h->next;
}
printf("\n");
}
/*Frees data using Node's head and prints exit message.*/
void Exit(Node* h){
printf("Exiting...\n");
Node* temp;
while(h!=NULL){
free(h->color);
free(h->details);
temp = h;
h = h->next;
free(temp);
}
}
int main(int argc, char **argv){
if(argc < 2||argc >= 3){
printf("Error. Enter one filename and one filename only.");
}
else{
char* filename = argv[1];
Node* head = light_info(filename);
int vibe_check = 1;
int Switch = 0;
char resp[10];
while(vibe_check){
if(head == NULL){
printf("Head memory not allocated...");
vibe_check = 0;
}
else{
scanf("%s", resp);
if(strcmp(resp,"off")==0){
if(Switch==0){
printf("\n--Lights are already off.\n");
}
else{
Switch = 0;
off(head);
}
}
else if(strcmp(resp,"on")==0){
if(Switch==1){
printf("\n--Lights are already on.\n");
}
else{
Switch = 1;
on(head);
}
}
else if(strcmp(resp,"exit")==0){
Exit(head);
}
else{
printf("Invalid command, type in off, on, or exit.");
}
}
}
}
}
The data for this program comes from a file formatted like so,
blue,2,0
green,1,0
red,1,0
red,2,1
yellow,2,1
blue,1,1
The expected out put for the program should be bb g r rr yy b any time someone types on with dashes replacing letters when someone types off after the lights are on. However, when run the program prints nothing out and after several rounds of debugging and valgrind, I've noticed two things:
The Node structs are not assigned line-by-line, leading to Nodes having duplicates of the last line
of data gotten rather than individual pieces of data based on the line read.
According to valgrind, their is an uninitialized value in the on function that I can't find.
Sorry if this is quite lengthy, but any help would be deeply appreciated! I am open to editing my post and any constructive critique if necessary!
The way you process your input in light_info has several errors.
First, current->color is assigned some allocated memory, then that memory is lost by the assignment on the next line (current->color = token;). This assignment will not copy the string pointed to by token, but will change the value of color to point to the same place - which is in the local variable line and will be dangling once your function returns. You'll want to use strcpy (or the safer version, strncpy) to copy the string into your allocated space.
You do something similar with current->details[0]=ptr1;. ptr1 points at the local num1 variable, so this pointer will also become dangling when the function returns. I'm not sure why details is an array of pointers. An array of int (where you can store the values directly) would seem a better choice. (The same applies to details[1] and ptr2).
Unrelated to this problem, the error checks for one of the mallocs to have failed are in the wrong place. You've already dereferenced all those pointers before you check them for NULL. That check should be up right after you've done the last malloc, before you start assigning all those next pointers.
There is also a lack of error checking elsewhere.
This question already has answers here:
Why is the gets function so dangerous that it should not be used?
(13 answers)
Crash or "segmentation fault" when data is copied/scanned/read to an uninitialized pointer
(5 answers)
Closed 4 years ago.
When I try to run this code, all I get is a warning that gets() is too dangerous too use. And then when I run it, I get blank. I am suppose to display this:
Ollie 2.9 freshmen
John 3.2 senior
Julie 2.2 freshmen
Joe 1.8 freshmen
Mary 3.8 senior
Sue 3.4 junior
Jane 2.7 senior
Bob 2.8 senior
Fred 3.2 freshmen
Bill 3.3 junior
Here is my code:
Student *top = NULL; // to point top node of list
Student * temp, *temp1, *temp2; // for traversing list
// Creates the entire linked list from the file.
// Should call readNext and push
// Returns head of the linked list
Student *buildStudentList()
{
Student *p; // will hold the data to be pushed in list
p = readNext();
push(&top, p);
return top; //TODO: Change return
}
//Read a single line from standard input and return a student structure located on the heap
Student *readNext()
{
Student *s = (Student*)malloc(sizeof(Student)); // allocating dynamic memory in heap
printf("Please Enter Student Name, gpa, year :");
gets(s->name);
scanf("%f", &s->gpa);
gets(s->year);
s->next = NULL; // initially make next as NULL
return s; //TODO: Change return
}
//Return a student structure stored on the heap
Student *makeStudent(char *name, float gpa, char *year)
{
Student *s = (Student*)malloc(sizeof(Student));// allocating memory in heap
s->name = name;
s->gpa = gpa;
s->year = year;
s->next = NULL;
return s; //TODO: Change return
}
//insert a new student node at the head of the linked list
void push(Student **list, Student *student)
{
top = *list;
student->next = top; // assign current top node of list to be second node of the list
top = student; // make current node as top node of the list
printf("push successful.\n");
}
//Insert a student node in the desired position on the linked list
void insert(Student *list, Student *s, int position)
{
int i;
top = list;
temp = top;// temp is for traversing the list
for (i = 1; i < position - 1; i++) // loop to reach desired position in the list
{
temp = temp->next;
}
if (temp == NULL)
{
printf("Position does not exist.\n");
}
else
{
s->next = temp->next;
temp->next = s;
}
}
//Displays contents of a single student structure
void display(Student *s) {
printf("NAME:%s\t| GPA:%f\t| YEAR:%s\n", s->name, s->gpa, s->year);
}
//Displays contents of the entire linked list
void displayAll(Student *list)
{
temp = list;
while (temp != NULL)
{
display(temp);
temp = temp->next;
}
}
//Delete all data allocated on the heap before terminating program
void cleanUp(Student *list)
{
temp1 = list; // will point to the top node of list
temp2 = temp1->next; // will point to the second node of the list
while (temp1 != NULL)
{
free(temp1);
temp1 = temp2;
temp2 = temp2->next;
}
printf("Cleanup Successful.\n");
}
//Main function tests your functions.
int main()
{
Student *list, *s;
printf("Program Started ");
//Construct Linked List from Standard Input
list = buildStudentList();
//Insert a new student in desired position
s = makeStudent("Max", 3.0, "senior");
insert(list, s, 1);
//Display entire linked list
displayAll(list);
//Free all heap memory
cleanUp(list);
printf("Program Successful Exit ");
return 0;
//exit(EXIT_SUCCESS);
}
And here is the output I am getting:
Program Started
Segmentation fault
Should I try to use the fgets() instead of gets()? The output I am trying to do is part of a different file, does that have a affect to it?
Ignoring warnings is never the right thing to do. The aim is not just to remove the warnings using some hack but to address the root cause that produces warning. In this particular case, the compiler explicitly has warned you that using gets is too dangerous. Why would you not heed such a clear warning?
gets has been removed from the standard from C11 onwards.
The gets() function does not perform bounds checking, therefore this function is extremely vulnerable to buffer-overflow attacks. It cannot be used safely (unless the program runs in an environment which restricts what can appear on stdin). For this reason, the function has been deprecated in the third corrigendum to the C99 standard and removed altogether in the C11 standard. fgets() and gets_s() are the recommended replacements.
Never use gets().
Also look at your memory allocation/deallocation for the members of the struct.
Also read this question on whether the result of malloc should be cast.
Hello I went through your code, assuming that your structure description is as follows:
typedef struct Student_s{
char name[32];
float gpa;
char year[5];
struct Student_s* next;
}Student;
The problem with gets() is already pointed out in previous answer by P.W
. You could use scanf("%s",s->name) instead of gets(),
And in makeStudent() you should be using strcpy() for copying string. [ Reason ]
Also in cleanUp() consider the case when the last node is being freed, temp1 will be pointing to the last node and temp2 to NULL. In this situation if you do a temp2 = temp2->next it will result in segmentation fault. You could avoid that by enclosing the statement in an if.
if(temp2 != NULL){
temp2 = temp2->next;
}
As part of an assignment, I am having a program read in the names and id of people from a file, and saving them in separate linked lists. I have a nested while loop to traverse the list until it reaches the end, and then assign the values at the end. Unfortunately the program keeps crashing while reading and it seems to revolve around the second while loop.
Here is the struct established before the main()
struct node
{
char name[50];
int id;
struct node *next;
}*start;
Here is the function itself:
void read()
{
int tempNum = 0, id, jack = 0;
char name[50];
struct node *temp, *right;
temp = start;
FILE *ifp = fopen("AssignmentOneInput.txt", "r");
while(fscanf(ifp," %s", &name) != EOF)
{
fscanf(ifp, " %[^,]s, %[^/n]d", &name, &id);
temp = (struct node *)malloc(sizeof(struct node));
strcpy(temp->name,name);
temp->id = id;
right = (struct node *)start;
printf("test number one\n");
while(right->next != NULL)
{
printf("test number two\n");
right = right->next;
}
printf("test number three\n");
right->next = temp;
right = temp;
right->next = NULL;
}
}
As for its implementation in the main function, it is the very first function called, so it looks a little like:
main()
{
read();
I guess thatstart is a global variable? Then it will be zero-initialized by the compiler and C runtime system. That means it will, as a pointer, be initialized to NULL. So when you use it uninitialized in your code it will be NULL and you have undefined behavior when you dereference the pointer. And undefined behavior is arguably the most common cause of crashes.
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.
I'm loading a file into memory and I am doing so with the following statement:
if ((ch = fread(&temp[i],1,1,loadDict)) == EOF)
break;
But I receive a segmentation fault. Upon inspection using gdb I verified that the fault is happening at this line (the if statement, before the break). Why does it not see that it will fault (the whole point of using EOF)?
I thought it might be that I'm using the EOF in an if statement rather than within a while() statement. Is it possible to use EOF in an if statement?
Update: More Code
bool load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char* new = malloc(sizeof(char)); // for storing the "new-line" character
*new = 0x0A;
// defines a node, which containes one word and points to the next word
typedef struct node
{
char* word;
struct node* next;
}
node;
node* head = malloc(sizeof(node));
node* temp = malloc(sizeof(node));
head->next=temp;
// copies a word from the dictionary file into a node
int* numStore = malloc(sizeof(int)); //count for number of words in dictionary
int num = 0;
int ch = 0; // to hold for EOF
int flag = 0; // for breaking out of while loop
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
int i = -1;
do
{
i++;
if (!feof(loadDict) || !ferror(loadDict))
{
flag = 1;
break;
}
fread(&temp[i],1,1,loadDict);
if (memcmp (new, &temp[i], 1) == 0)
num += 1;
}
while(memcmp (new, &temp[i], 1) != 0);
temp=newNode;
if (flag == 1)
break;
}
numStore = #
return true;
}
typedef struct node
{
char* word;
struct node* next;
}
The structure that you defined can crash, at least the implementations I have seen has. The char* inside the node has no fixed value. So when you do :
node* head = malloc(sizeof(node));
The malloc() will allocate a memory of (taking 1 byte for char pointer, and an int size pointer for node, defaulting to 4 bytes on a 32-bit machine) 5 bytes. What happens when you read more than 5 bytes?
Also, you are needlessly complicating this:
int* numStore = malloc(sizeof(int));
If you want to store the number of words in the dictonary, straight away use an int numstore, less headache :)
while(true)
{
node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);
...
}
Now, this here is an interesting concept. If you want to read till the end of file, you have got two options:
1) use feof()
2) at the end of the loop, try this:
while(true)
{
....
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
Also, this line: temp->word=malloc(46);
Why are you manually allocating 46 bytes?
Armin is correct, &temp[i], while i does get allocated to 0, the do{...}while(); is completely unnecessary.
Also from man fread : http://www.manpagez.com/man/3/fread/
You are reading what looks to me like 1 character.
In my opinion, try something like this:
set a max value for a word length (like 50, way more for practical purposes)
read into it with fscanf
get its length with fscanf
allocate the memory
Also, you do not need to allocate memory to *head; It can be kept as an iterator symbol
I almost forgot, how are you going to use the returned list, if you are returning bool, and the *head is lost, thus creating a memory leak, since you can't deallocate the rest? And unless you are using c99, c doesn't support bool
/*Global declaration*/
typedef struct node
{
char* word;
struct node* next;
}node;
node *head, *tmp;
/* for the bool if you really want it*/
typedef enum { false, true } bool;
node* load(const char* dictionary)
{
FILE* loadDict = fopen(dictionary, "r");
char word[50];
int num = 0;
int len;
node *old;
while(true)
{
/*node* newNode = malloc(sizeof(node));
temp->next=newNode;
temp->word=malloc(46);*/
fscanf(loadDict,"%s ",word);
len = strlen(word);
tmp = malloc(len + sizeof(node));
strcpy(tmp->word,word);
tmp->next = NULL;
if(head==NULL)
{
head = tmp;
old = head;
}
else
old->next = tmp;
old = tmp;
num++;
if(fgetc(loadDict)==EOF) break; else fseek(loadDict,-1,SEEK_CUR);
}
printf("number of counted words::\t%d\n",num);
fclose(loadDict);
return head;
}
Also, please remember that i have only accounted for the act that words are separated by one space per, so please load the file t=like that, or change the algo :) Also, be sure to free the memory after using the program !
void freeDict()
{
node *i;
while(head!=NULL)
{
i = head;
head = head->next;
free(i);
}
}
Hope this helps :)
This compiles...I've now run it too. The error handling on failure to allocate is reprehensible; it should at minimum give an error message and should probably free all the allocated nodes and return 0 (NULL) from the function (and close the file).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct Node
{
char *word;
struct Node *next;
} Node;
Node *dict_load(const char *dictionary)
{
FILE *loadDict = fopen(dictionary, "r");
if (loadDict == 0)
return 0;
Node *head = 0;
char line[4096];
while (fgets(line, sizeof(line), loadDict) != 0)
{
size_t len = strlen(line); // Includes the newline
Node *node = malloc(sizeof(*node));
if (node == 0)
exit(1); // Reprehensible
node->word = malloc(len);
if (node->word == 0)
exit(1); // Reprehensible
memmove(node->word, line, len - 1); // Don't copy the newline
node->word[len-1] = '\0'; // Null terminate the string - tweaked!
node->next = head;
head = node;
}
fclose(loadDict);
return head;
}
If you've got to return a bool from the function, then you probably need:
static bool dict_load(const char *dictionary, Node **head)
If the argument list is fixed at just the file name, then you're forced to use a global variable, which is nasty on the part of the people setting the exercise. It's 'doable' but 'ugly as sin'.
The code above does work (note the tweaked line); adding functions dict_free() and dict_print() to release a dictionary and print a dictionary plus proper error handling in dict_load() and a simple main() allows me to test it on its own source code, and it works (printing the source backwards). It gets a clean bill of health from valgrind too.
You're use of temp[i] raises suspicion that you might be accessing outside memory.
To quote from K&R:
If pa points to a particular element of an array, then by definition pa+1 points
to the next element, pa+i points i elements after pa, and pa-i points i elements
before.
These remarks are true regardless of the type or size of the variables in
the array a. The meaning of ``adding 1 to a pointer,'' and by extension,
all pointer arithmetic, is that pa+1 points to the next object, and pa+i
points to the i-th object beyond pa.