I have a code that sorts a list, I can get it to sort when the list is hardcoded. I am now attempting to implement getting the list from an input file and running it the same way through the code then printing it to an output file. I am trying to get a scanned list from an input file to go through what I have (that is working) for sorting and for the result to be printed to an output file.
You have assigned *tmp to head. But I can see that head had always been NULL. So the loop is never entered, and nothing is being inserted to the list.
So what we'd need to do it first initialize head to a node instance
typdef struct node
{
char* data;
struct node *prev;
struct node *next;
}node;
head = malloc(sizeof(node));
then we assign it data.
head->attribute = value;
finally we set this pointer location value to our tmp pointer as well.
tmp = head;
no we can proceed with our loop
strings in C are represented as an array of chars, whose stored location points to the first element of the char array. the array must also end with a NULL chat '\0'. note that strlen(str) will return length of string without the NULL char so you must add 1 while mallocing to take this into sconsideration. i would advise not messing with strings unless absolutely necessary. by that I mean trying to manually manipulate them. this will introduce another set of problems not related to what we're working on in general. we should just use strncar(), strncpy() methods until c style strings become completely intuitive.
I hope I understood right your question. I tried to fix the program like it will read a file and make a list of the data in the file.
I fixed some issues;
For the transverse function, i added a for loop and printed the data using %c.
while (temp != NULL) {
for(i=0; temp->data[i]!='\0'; i++) {
printf("%c\n", temp->data[i]);
}
temp = temp->next;
}
I changed the insertAtEnd function like this;
void insertAtEnd(FILE* f, char* data)
And naturally, in main function, calling this function changed like;
insertAtEnd(ifp, result[i]);
By the way for the following statement, my complier wanted me to express the temp as char, it said it was the first use of this. It also seems like you entered a space after &.
insertAtEnd(ofp, &temp);
I added the following statements to the main function;
argc -= optind;
argv += optind;
I also changed this ifp= fopen(ifilename, "r"); statement with this ifp= fopen("ifilename.txt", "r");statement. I opened a text file named ifilename.txt and wrote some data there.
EDIT:
Ok so if you want to print the strings to an output file and you want to print the words in the lines individually, you will change the code doing the following things:
I changed the struct's data with an array, gave it an expected maximum line length with a sharp defined MAX_LEN;
struct node
{
char* data[MAX_LEN];
struct node *prev;
struct node *next;
};
I changed the insertAtEnd function again because I scanned the file in main function, made an array of the strings, sent it to this function and added it to the end of the list. I used this piece of code in main fuction:
char* result[count];
char* temp = (char*)malloc(sizeof(char));
while (fgets(temp, sizeof(temp), ifp))
{
result[count] = (char*)malloc(sizeof(char)*20);
strcpy(result[count], temp);
insertAtEnd(result, count);
count++;
}
count is the number of strings in the file. I also sent this number to insertAtEnd function;
void insertAtEnd(char* data[], int size)
{
//Create a new node
struct node *newnode = (struct node*)malloc(sizeof(struct node));
newnode->data[size] = data[size];
if (newnode->data[size] != NULL) {
...
I wanted to use the output file you opened in the main function, so I sent this file and sent the count -number of strings- to the printing function transverse like this;
void traverse(FILE *of, int size)
{
int i;
// List is empty
if (head == NULL) {
printf("\nList is empty\n");
return;
};
// Else print the Data
struct node* temp;
temp = head;
while (temp != NULL) {
for(i=0; i<size; i++) {
fputs(temp->data[i], of);
temp = temp->next;
}
fprintf(of, "\n");
}
}
Also in main function, calling this function will be changing like;
traverse(ofp, count);
Related
I am having problem storing all the values into the Generic LinkedList, my linkedlist works totally works on a normal user Keyboard input but when I try to store values(strings) from a file, there is something weird happening, it only store the last value of the file.
I have checked my addToList() function but theres nothing wrong with it.
P.s But I am feeling its either I am printing wrong or my reading from the file into the linkedlist is wrong.
Thank you.
#include<stdio.h>
#include <stdlib.h>
#include<string.h>
#include "LinkedListItems.h"
#define MAX 10000
int main()
{
printf("Testing MissileFIle.txt");
void* secondStr;
//Had to malloc the thing
secondStr = (void*)malloc(1*sizeof(char));
FILE* missileFile;
missileFile = fopen("missiles.txt", "r");
if(missileFile == NULL)
{
printf("The file is empty");
}
number_list_t* missileList = calloc(1, sizeof(number_list_t));
void* input;
//Have to allocate the input
input = malloc(1*sizeof(void*));
//this is to read the data into the second Str
while(fgets(secondStr,MAX,missileFile) != NULL)
{
//Let just print out first just to test my memory
printf("%s\n",secondStr);
//Right now its only reading one string so far which is really weird AFFFFF
addTolist(missileList,secondStr);
}
//Gotta declare another list just to print out the list
number_node_t* current = missileList->head;
while(current != NULL)
{
//There is something wrong with this line
printf("%s\n",current-> number);
current = current-> next;
}
fclose(missileFile);
}
OUTPUT:
Testing MissileFile.txt
splash
single
V-line
h-line
Single
Single
Single
Single
Single
Single
typedef struct NumberNode
{
//It can store any data type
void* number;
struct NumberNode* next;
}number_node_t;
//List of Nodes
typedef struct NumberList
{
number_node_t* head;
int count; //This is not nesssary but it can be useful for counting how many variables
}number_list_t;
void addTolist(number_list_t* list, void* newNumber)
{
//tem[ = newNode]
number_node_t* newNode = calloc(1,sizeof(number_node_t));
newNode->number = newNumber;
newNode->next = list->head;
list->head = newNode;
}
INPUT DATA:
single
splash
single
V-Line
h-line
Single
The way you have implemented this, it cannot work.
The main problem, among many, is related to the void* pointers which cannot be dereferenced.
The size of elements should be given, either on creating the list in which case all elements are of the same type, or separately for each individual element. You can check out this question for an example of something that could work.
As far as the buffer thing is concerned, addToList should allocate new memory for each newNumber. What you are currently doing results in all data of the list pointing to a specific space in memory (the one allocated to secondStr). Each time you change the content of that memory space, all elements in the list are affected. This is why you print the same value for all elements and more specifically the last value in your file.
The way you allocate memory is also not really ok, same goes for the way you open your file, there is memory leaking etc. I am not going into details.
At least this issue:
Copy the string
OP's goal includes the need to copy the string from the read buffer to the list, not just copy the buffer pointer.
// void addTolist(number_list_t* list, void* newNumber) {
void addStringTolist(number_list_t* list, const char *s) {
// number_node_t* newNode = calloc(1,sizeof(number_node_t));
number_node_t* newNode = calloc(1, sizeof *newNode); // todo: add error check
size_t sz = strlen(s) + 1;
newNode->number = malloc(sz); // todo: add error check
strpy(newNode->number, s);
newNode->next = list->head;
list->head = newNode;
}
Note: When freeing the list, newNode->number also needs to be free'd.
regarding:
while(fgets(secondStr,MAX,missileFile) != NULL)
MAX is defined as 10000 but secondStr is defined as pointer to one byte. so when this is executed, a buffer overflow occurs.
This is undefined behavior and probably the root of the problem with reading from a file
I have a function called addMod that, when called, adds a node to a certain index of an array of Module struct LinkedLists called modules contained within a System struct. A Module struct has a string field, two int fields, and a pointer to the next Module, the first three fields being initialized according to arguments provided in addMod. addMod roughly looks like this:
int addMod(System *system, const char *text, int num1, int num2, int index) {
Module *temp = malloc(sizeof(Module));
Module *current;
temp->next = NULL;
if ([any of the constructors are invalid]) return 0;
temp->text = malloc(strlen(text)+1);
strcpy(temp->text, text);
temp->num1 = num1; temp->num2 = num2;
if (!system->modules[index]) {
system->modules[index] = temp; //If there are no modules in the LinkedList at the given index, makes the head = temp.
}
else {
if (system->compare(temp, system->modules[index]) <= 0) { //compare is a func pointer field of system that compares two Modules to see in what order they should be. Here, we check if temp should become the head of modules[index].
temp->next = system->modules[index]; //Assigns the current head as the module following temp.
system->modules[index] = temp; //Makes temp the current head.
}
else {
current = system->modules[index];
while (current->next && system->compare(temp, current->next) > 0) { //While current isn't the last node in the LinkedList and temp comes after the node after current
current = current->next;
}
temp->next = current->next; //Adds temp in between current and current->next.
current->next = temp;
}
}
return 1;
}
All of the above works as expected, except when printing the contents of system, the console indicates there's a memory leak that I'm assuming is because I fail to properly free temp based on what valgrind tells me. My problem is not knowing where to free it- it seems anywhere I put it causes a segfault after printing the contents. From my understanding, I have to make sure that no other variables are depending upon the value being held by temp, but I can't seem to find a way to do that considering every possible ending of my if statement leads to assigning temp to a node within modules. Putting free(temp) between the logic and return 1 also yields a segfault, I'm assuming because I often malloc temp again when calling addMod multiple times in succession.
In summary, to add a new node to a LinkedList that may or may not be populated, in which this new node may be inserted in any arbitrary position in the LinkedList, I have to allocate memory to a temporary node so that I can insert it later. Where do I free this allocated memory once I have successfully inserted the node?
Assuming your management of a System instance is sound (a big assumption, since I cannot see that code), you have giant hole in the memory allocation of temp with a subsequent hard return 0 in the condition where the "constructor" check fails. More to the point:
Module *temp = malloc(sizeof(Module)); // memory allocated here...
Module *current;
temp->next = NULL;
if ([any of the constructors are invalid])
return 0; // and leaked here.
It may be as simple as swapping the check around. Obviously other code that is supposed to free the dynamic allocations should be considered and evaluated as well.
A Simpler Approach
The node addition code is complicated and it need not be. In the end all you should really care about is finding the place where your new node resides.
If the slot in the table is empty, its the first node in that list.
IF the slot in the table is NOT empty, find the sorted location and insert it there.
Both of those can be accomplished with a single while-loop by using a pointer-to-pointer, where said entity hold the address of the pointer that will hold the new node in either of the cases above, and as a bonus, surgical insertion is literally two assignments.
It's done like this. Note that most of this code is just making the Module object safely. The actual insertion is only a single while-loop and some pointer assignments. It assumes the table in System initially contains NULL entries:
int addMod(System *system, const char *text, int num1, int num2, int index)
{
// allocate new node here
Module *temp = malloc(sizeof *temp);
if (temp == NULL)
{
perror("Failed to allocate new Module");
return 0;
}
size_t len = strlen(text);
temp->text = malloc(len + 1);
if (temp->text == NULL)
{
perror("Failed to allocate module name");
free(temp);
return 0;
}
// finish copying member data
memcpy(temp->text, text, len);
temp->text[len] = 0;
temp->num1 = num1;
temp->num2 = num2;
// now find where it belongs, and set next appropriately
Module **pp = system->modules + index;
while (*pp && system->compare(temp, *pp) <= 0)
pp = &(*pp)->next;
temp->next = *pp;
*pp = temp;
return 1;
}
Understand this is from deriving what I think your System type looks like, as it was never presented:
typedef struct System
{
Module *modules[MAX_MODULES];
int (*compare)(const Module* lhs, const Module *rhs);
} System;
I'm fairly confident it is similar to this. Of course, you'll have to adapt if it isn't. I suggest you review this and step through it in a debugger. There is no substitute for watching it live.
Best of luck.
I'm trying to creating linear linked list recursively with c language,
but keep sticking from here and the code is not working with the error "Linker Tools Error LNK2019". Sadly i can't understand what's the matter. Here is my code.
Thanks for your big help in advance.
#include <stdio.h>
#include <stdlib.h>
struct node
{
char num; //Data of the node
struct node *nextptr; //Address of the next node
};
typedef struct node element;
typedef element *link;
link head;
void displayList(); // function to display the list
int main()
{
char s[] = "abc";
link stol(s);
{
link head;
if (s[0] == '\0')return(NULL);
else {
head = (link)malloc(sizeof(element));
head->num = s[0];
head->nextptr = stol(s + 1);
return(head);
}
}
printf("\n\n Linked List : To create and display Singly Linked List :\n");
printf("-------------------------------------------------------------\n");
displayList();
return 0;
}
void displayList()
{
link tmp;
if (head == NULL)
{
printf(" List is empty.");
}
else
{
tmp = head;
while (tmp != NULL)
{
printf(" Data = %d\n", tmp->num); // prints the data of current node
tmp = tmp->nextptr; // advances the position of current node
}
}
}
You redefine a link object called head in your main() function. It hides the global head variable.
Removing the definition inside main would fix your problem, but you should consider passing a link* as a parameter to your displayList function in any case.
I've just noticed this statement return(head); in main(). You program exits prematurely as a result as well.
Everytime I look at your app, I find more issues. If I were you, I'd start by creating a function that adds a node to the list. It's much easier to add new nodes to the front of the list, so you should try that first. Try adding to the tail once you get this running. Adding to the tail is very similar, but you have to 'walkthe list first to get to the last element, exactly as you already do indisplayList()` Another way is keeping the address of the last node* you've added to the list. Like I said, it adds a bit of complexity, so get it working with addToHead first.
void addToHead(link* l, node* n)
{
n->nextptr = l->nextptr;
l->nextptr = n;
}
in your main, you can allocate one new node at a time, as you already do with malloc(). Initialize its contents num with an integer, and let addToHead deal with the pointer stuff. Your use of pointers is terrible, but lists are quite easy, and addToList pretty much shows what can and what should be put in pointers - namely other pointers.
You can remove almost everything in main() before the first printf. You'll have to
start loop:
write a prompt so the user knows what to do using printf()
read input from user using scanf("%d", &n), or equivalent.
break from the loop if user enters a negative value.
malloc() a new node
set its data num = n
call addToHead to add the node.
Loop until user enters an empty string, or -1.
That should take about 8 to 10 lines of code. if in doubt, you will easily find documentation on scanf, with google or on http://en.cppreference.com/w/c.
I declared a linked list implemented in C as follows:
struct node_List {
int i;
char * name;
struct node_List* next;
};
typedef struct node_List nodeList;
Then I declared the list head globally as:
nodeList list; // head of the list - does not contain relevant data
Finally, I have a function id(char * s) with a string s as th only argument.
nodeType id(char *s)
{
nodeType *p; // another List type
if ((p = malloc(sizeof(nodeType))) == NULL) {
// error: out of memory;
}
nodeList * node = &list;
// printf(" ");
while (node->next != NULL){
node = node->next;
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
}
// error: not found;
}
The problem is, when i run this program and call foo("somestring") the program executes the error: not found part and aborts execution, despite the string somestring being in the list.
I tried executing the very same program by inserting some printf() for debugging purposes, and it works perfectly, except it prints additional characters along with the output.
This happens each time I add some print lines, e.g. if I uncomment the two printf()s which I wrote in the example above (one of them or both, i get the same successful result). It doesn't work though if the printf is called with no arguments or with an empty string "".
I can't figure out what's happening, I double-checked the list creation and population functions and I am totally sure they work correctly. I tried changing the while break condition, but that didn't work, too. I have observed a similar behaviour on both Linux (with gcc) and Windows (using CodeBlocks editor's integrated compiler)
How could a printf directive affect a program so much?
EDIT: This code is part of a syntax analyzer written in Yacc. The whole code can be found below. It's a long read, and it is not completed, but the code above was tested and used to work as explained.
lexer: http://pastebin.com/1TEzzHie
parser: http://pastebin.com/vwCtMhX4
When looking in the provided source code, the algorithm to explore the linked list has two ways to miss node in the while-loop comparison.
Way 1 - starting only from the second node of the list.
Placing node = node->next; before the comparison will force the first comparison to be &(list)->next instead of &(list).
To start from the first node, simply place node = node->next; after
the comparison.
Way 2 - never ending to the last node of the list.
Using (node->next != NULL) in the while condition will force to exit from the loop before comparing the last node => node->next = NULL;.
To end by the last node, simply change the while condition to (node != NULL).
Solution:
while (node != NULL){ // end from the last node
if (strcmp(node->name, s) == 0){
// printf(" ");
// assign node to an attribute in p
return p;
}
node = node->next; // explore link after comparison
}
The actual error is a wrong type declaration of a variable returned by the function:
nodeType* createPoint(char* l){
nodeList* p;
if((p=malloc(sizeof(nodeList))) == NULL){
yyerror("out of memory");
} else {
// do stuff with p
}
return p;
}
The function return value was a nodeType* and p was instantiated as nodeList*.
The declaration of those two types was pretty simple, that's why the program could work.
the working code can be found here.
The strange behaviour with printf() was probably caused by the heap space needed for printf's arguments: since this function accepts an arbitrary number of parameters, it saves them in a list. This list is instantiated in the heap, there overwriting the old data left there from the wrong implementation of createPoint.
I'm doing my coursework regarding airport simulation and I'm having some troubles trying to store information in the character array part.
I am supposed to type in a string of character and it will store in the planeName part of the node but it can't seem to work. My int main() is pretty much empty now because I didn't want to continue coding with incorrect functions.
Below are my codes:
struct node {
char planeName[5];
int planeNumber;
struct node* next;
};
struct node* front = NULL;
struct node* rear = NULL;
void Enqueue(char name[5], int x);
int main() {
}
void Enqueue(char name[5], int x){
struct node* temp = (struct node*)malloc(sizeof(struct node));
temp -> planeName = name;
temp -> planeNumber = x;
temp -> next = NULL;
if (front == NULL && rear == NULL)
front = rear = temp;
rear -> next = temp; //set address of rear to address of temp
rear = temp; //set rear to point to temp
return;
}
This is the error message in the line containing: temp -> planeName = name
This is the part where error message pops up and I have no clue why is this happening.
Can someone please help and ask more questions me if my question is not clear enough?
temp -> planeName = name;
You can't assign to an array. Array cannot be used as lvalue. Use strcpy instead-
strcpy(temp -> planeName,name);
Note- But make sure your char arrays are nul terminated before passing them to strcpy.
Your strings are arrays of characters, so you have to copy the individual elements. Fortunately, there are functions (like strcpy) written to do just that.
The error comes from the fact that you are performing a shallow copy by copying the name of your array planeName.
If you want to copy your array you need to copy each and every element of it, this is done easier if the last element of your array contains a special character indicating its end, for example the character \0.
An array containing as its last character, the \0 is called: null terminated. There are a lot of functions that perform operations on null terminated arrays. The one that you need is:
char * strcpy ( char * destination, const char * source );
which will copy all of the element of the null terminated array passed as source to destination. In your case it will look like this:
strcpy(temp -> planeName,name);
Here is a brief info about strcpy().