I made linked list with struct.
The 1st string goes well, however the 2nd one isn’t "am", but random character appears.
And 3rd and later one, the pointer is broken and this flows exception, "Segmentation fault".
Here is the code.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
typedef struct strliststruct{
char* string;
unsigned long long length;
struct strliststruct* prior;
struct strliststruct* later;
int exist_prior;
int exist_later;
}strlist;
strlist init_strlist(){
strlist ans;
ans.exist_later=0;
ans.exist_prior=0;
ans.length=0;
return ans;
}
strlist init_strlist_with_string(char* str,char splitter){
strlist ans=init_strlist(),next;
unsigned long long i;
for(i=0;1;i++){
if(str[i]==splitter){
next=init_strlist_with_string(&str[i+1],splitter);
ans.later=&next;
ans.exist_later=1;
next.exist_prior=1;
next.prior=&ans;
}else if(str[i]!=''){continue;}
ans.string=malloc(sizeof(char)*(i+1));
ans.string[i]='';
for(unsigned long long j=0;j<i;j++){
ans.string[j]=str[j];
}
break;
}
return ans;
}
int main(){
strlist sl=init_strlist_with_string("I am a human",' ');
while(1){
printf("%sn",sl.string);
if(sl.exist_later){sl=*sl.later;}else break;
}
return 0;
}
I work on Visual Studio code, and compile it with gcc.
I tried to find why does it cause with breakpoint, and found the 4th pointer is deleted on 4th "ans.string=malloc".
And 2nd and later data was destroied on "sl=sl.later".
I have no idea of solution.
2
Answers
I had to avoid to return local variables as pointer, which destroy after the function ended. So, instead of this, using malloc to reserve memories would be the solution. Here is the improved code.
Well, your program fails due to the use of memory addresses that are out of scope, as you may have learned from the comments.
IMHO here is the center issue: as you can see in any text book on data structures, a linked list is a set — pssibly empty — of nodes. The linked list is not of data. The node is not the data. The list is not a node. The node is not the list. Although is possible to mix this, and very very common, you will end up with code that is not reusable and is very hard to test and maintain.
I will show a common way to write this kind of things, a way that can make life easier and your code reusable. And a more convenient abstraction.
encapsulation is essential and you need a better abstraction.
TL;DR;
This can be a long post since I am adding comments, code and arguments. For the code you can jump to 3.2: a second example
1: the original data
Here is all you have in the original code:
So this single
struct
is the model and isAnd there is no metadata, not even the minimum: to take account of the head and the size of the list.
2: a normal abstraction
A linked list is just that: a list of nodes with links. There is no linked list of strings, of movies, of tickets, of musics. A node is an abstraction that points to or contains one record of data. A list is generic. Is reusable as a map, a set, a stack, an array or a dictionary are.
2.1: the list
List
This is a possible list. It can be empty, but is has control of its size internally. Has pointers to tail and head so is is trivial to insert or extract nodes from either end. As in a queue or stack, for example. A linked list can abstract these things.
2.2: a node
Node
This is a possible node: the links and a pointer to a data record.
2.3: some operations on
List
Using encapsulation of the list and data — and operations on data — we see no mention of the data in the definition so far. This way the code will work for lists of anything, so it can be reused with no change.
so_insert_back(Info* info, List* list)
gets a record and inserts into the list. At the back of the listso_insert_front(Info* info, List* list)
does he same but at the front of the listso_print_list(List*, const char* msg)
displays the list at the screen, and accepts an optional message.2.4: the data record
This
Info
is the unit of data in the nodes for this particularList
implementation. But each node has only a pointer to suchstruct
.The operations defined below permits the list to manage nodes without knowing what they are, sort of a mediator design pattern.
2.5: some operations on data
In the example code it will become clear why these exist and how to use it. It is the same concept: encapsulation.
Info* so_copy_info(Info*)
is called a copy constructor and get anInfo
and returns a copy of it.Info* so_delete_info(Info*)
is called a destructor and gets the adrress of a record and delete it.Info* so_factory_info()
is called a constructor and here is a factory function: each time it is called is returns a newInfo
record, with known data:"Element nnnnnn"
is the string, numbered from 1 up. This way it is trivial to test for 10 or 10,000 records in the list.so_print_info(Info*, const char* msg)
will display the list on screen, with metadata and all records3: a 1st example:
main1.c
3.1: output
Notes:
so_factory_info()
returns elements numbered the program is easy to follow: back insertion preserves the order, front insertion inverts them.so_print_list
accepts a message so we can identify the tests at the call3.2: a second example, using the idea in the original code:
main2.c
Again the code is simple:
so_line_insert( const char* string, const char delim, List* list)
does the expected: gets a string and a delimiter and parse the string into words and inserts them into the list.so_multi_insert(List* list, const char delim, const unsigned N, ...)
uses the function above and inserts all lines into the list3.4: parsing the line
Instead of using library functions like
strchr
orsscanf
a minimalist state machine with 2 states are used to parse the line, extract the words and insert into the list. Is is the only function in the example with more than 20 lines of code but has less than 40. It is a single loop with a switch, a classic FSM.3.4: output of the 2nd example
Here some tests are run with the delimiters in many positions and then the example string is inserted also (see the code above).
4: The data, node and list example implementation
4.1: header file
stuff.h
4.2: a possible implementation
stuff.c
Conclusion
This is a long post, I was coding along. It is just a mock up to show some possible uses.
But is almost a generic list, easily expandable.
To use just copy header and implementation and add code for main.
HIH