How to create a linked list from a binary input file? With first few bytes being an int and the next few a char and so onWhy is “while (!feof(file))” always wrong?How do I create a Java string from the contents of a file?How to create a linked list of nodes that are contained in the max-Depth of a Binary Tree using JavaSegmentation fault when inserting values from file into linked listhow to read in file that contains char, int and white space into linked listHow do I create an array of multiple linked lists in c?C Linked List - Linking next Linked List NodeUnexpected behaviour of fread() reading from binary fileGetting all chars in text file by fscanf() returns invalid count of charLinked list issue from reading a file cHow to convert a binary file to a text file, containing ints and chars
Picking a theme as a discovery writer
As a GM, is it bad form to ask for a moment to think when improvising?
Find the area of the smallest rectangle to contain squares of sizes up to n
While drilling into kitchen wall, hit a wire - any advice?
All of my Firefox add-ons been disabled suddenly, how can I re-enable them?
Changing stroke width vertically but not horizontally in Inkscape
Can I combine SELECT TOP() with the IN operator?
A 2-connected graph contains a path passing through all the odd degree vertices
Can an Iranian citizen enter the USA on a Dutch passport?
How do I, as a DM, handle a party that decides to set up an ambush in a dungeon?
Transistor gain, what if there is not enough current?
Two denim hijabs
Why are condenser mics so much more expensive than dynamics?
Where did Lovecraft write about Carcosa?
What does the phrase "go for the pin" mean here?
hl with custom color and linebreak and math
What does のそ mean on this picture?
Debian 9 server no sshd in auth.log
When did England stop being a Papal fief?
What do you call a painting painted on a wall?
How to speed up large double sums in a table?
Primes in a Diamond
What is the thing used to help pouring liquids called?
Is throwing dice a stochastic or a deterministic process?
How to create a linked list from a binary input file? With first few bytes being an int and the next few a char and so on
Why is “while (!feof(file))” always wrong?How do I create a Java string from the contents of a file?How to create a linked list of nodes that are contained in the max-Depth of a Binary Tree using JavaSegmentation fault when inserting values from file into linked listhow to read in file that contains char, int and white space into linked listHow do I create an array of multiple linked lists in c?C Linked List - Linking next Linked List NodeUnexpected behaviour of fread() reading from binary fileGetting all chars in text file by fscanf() returns invalid count of charLinked list issue from reading a file cHow to convert a binary file to a text file, containing ints and chars
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty height:90px;width:728px;box-sizing:border-box;
I want to create a linked list from an input binary file. The first sizeof(int) bytes is an int and the next sizeof(char) bytes is a char and it keeps going like that.
What I want to do is create a linked list from this file where each node in the linked list contains a character and a tree node that contains this int value.
I am stuck when it comes to creating a linked list out of this file. If it was just a regular file with ints and no binary and no chars, I would have used fscanf to read the file and stored its contents into an array, and then I would have traversed through the array and made the nodes. However, I am confused when these chars are present in the file. Could anyone please help me and tell me if there is a way to create a linked list?
Edits ->
ListNode *head = malloc(sizeof(ListNode)*sizeoffile);
//how do i find the size of the file.
//if it was a file with just integers, I would have done something like this
// int value;
// int count = 0;
//while(fscanf(fptr, "%d", &value)==1)
//
// count++;
//
//But now that there is chars, I am really confused how I would determine
//the size of the file.
while(!feof(fptr))
fread(head, sizeof(int)+sizeof(char), 1, fptr);
I know this is not right. ^
c file linked-list
add a comment |
I want to create a linked list from an input binary file. The first sizeof(int) bytes is an int and the next sizeof(char) bytes is a char and it keeps going like that.
What I want to do is create a linked list from this file where each node in the linked list contains a character and a tree node that contains this int value.
I am stuck when it comes to creating a linked list out of this file. If it was just a regular file with ints and no binary and no chars, I would have used fscanf to read the file and stored its contents into an array, and then I would have traversed through the array and made the nodes. However, I am confused when these chars are present in the file. Could anyone please help me and tell me if there is a way to create a linked list?
Edits ->
ListNode *head = malloc(sizeof(ListNode)*sizeoffile);
//how do i find the size of the file.
//if it was a file with just integers, I would have done something like this
// int value;
// int count = 0;
//while(fscanf(fptr, "%d", &value)==1)
//
// count++;
//
//But now that there is chars, I am really confused how I would determine
//the size of the file.
while(!feof(fptr))
fread(head, sizeof(int)+sizeof(char), 1, fptr);
I know this is not right. ^
c file linked-list
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56
add a comment |
I want to create a linked list from an input binary file. The first sizeof(int) bytes is an int and the next sizeof(char) bytes is a char and it keeps going like that.
What I want to do is create a linked list from this file where each node in the linked list contains a character and a tree node that contains this int value.
I am stuck when it comes to creating a linked list out of this file. If it was just a regular file with ints and no binary and no chars, I would have used fscanf to read the file and stored its contents into an array, and then I would have traversed through the array and made the nodes. However, I am confused when these chars are present in the file. Could anyone please help me and tell me if there is a way to create a linked list?
Edits ->
ListNode *head = malloc(sizeof(ListNode)*sizeoffile);
//how do i find the size of the file.
//if it was a file with just integers, I would have done something like this
// int value;
// int count = 0;
//while(fscanf(fptr, "%d", &value)==1)
//
// count++;
//
//But now that there is chars, I am really confused how I would determine
//the size of the file.
while(!feof(fptr))
fread(head, sizeof(int)+sizeof(char), 1, fptr);
I know this is not right. ^
c file linked-list
I want to create a linked list from an input binary file. The first sizeof(int) bytes is an int and the next sizeof(char) bytes is a char and it keeps going like that.
What I want to do is create a linked list from this file where each node in the linked list contains a character and a tree node that contains this int value.
I am stuck when it comes to creating a linked list out of this file. If it was just a regular file with ints and no binary and no chars, I would have used fscanf to read the file and stored its contents into an array, and then I would have traversed through the array and made the nodes. However, I am confused when these chars are present in the file. Could anyone please help me and tell me if there is a way to create a linked list?
Edits ->
ListNode *head = malloc(sizeof(ListNode)*sizeoffile);
//how do i find the size of the file.
//if it was a file with just integers, I would have done something like this
// int value;
// int count = 0;
//while(fscanf(fptr, "%d", &value)==1)
//
// count++;
//
//But now that there is chars, I am really confused how I would determine
//the size of the file.
while(!feof(fptr))
fread(head, sizeof(int)+sizeof(char), 1, fptr);
I know this is not right. ^
c file linked-list
c file linked-list
edited Mar 24 at 0:54
noobie
asked Mar 23 at 4:33
noobienoobie
12
12
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56
add a comment |
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56
add a comment |
3 Answers
3
active
oldest
votes
Step 1: Assume all data from an external source (e.g. from a file) is potentially malicious and/or corrupted and/or came from a different computer (with different sizeof(int)
and different endianness).
Step 2: Define your file format properly (taking step 1 into account). E.g. maybe it's supposed to be a value in the range 123 to 123456 that's stored as 4 consecutive bytes in little endian order (it should never be an int
); and maybe it's a byte containing an ASCII character (it should never be a "random whatever character set the compiler felt like using char
").
Step 3: Write some code to load data from the file into an array of bytes. If the file is expected to be small you can use realloc()
to increase the size of the buffer if the buffer wasn't big enough (but make sure there's a "max. file size" so that a malicious attacker can't trick you into consuming all available RAM and crashing due to "out of memory"). If the file is expected to be larger; look into functions like mmap()
. Alternatively, you can have a "read next part of file; parse next part of file" loop that recycles a fixed sized buffer.
Step 4: Write code to parse the "array of bytes" data and check that it actually complies with the file format specs in every way possible. For example, unsigned long value = buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24)
and if( (value < 123) || (value > 123456) ) { // Data is malformed
.
Step 5: Once you've parsed the data (and written code to handle every conceivable error condition in an appropriate manner, and know for a fact that it must be valid data), you can store the data in a structure and add that structure to a linked list. E.g.
// Parse and check it
if(bufferSize < position + 5)
return "File ends in the middle of a record";
unsigned long value = buffer[position] + (buffer[position+1] << 8) + (buffer[position+2] << 16) + (buffer[position+3] << 24);
if( (value < 123) || (value > 123456) )
return "Data was malformed (integer out of range)";
if( (buffer[position+4] < 0x20) || (buffer[position+4] >= 0x7F) )
return "Data was malformed (character not printable ASCII)";
// Create a structure
myStructureType * myStruct = malloc(sizeof(myStructureType));
if(myStruct == NULL)
return "Failed to allocate memory for structure";
myStruct->value = value;
myStruct->character = buffer[position+4];
position += 5;
// Add structure to singly linked list
myStruct->next = NULL;
if(listFirst == NULL)
listFirst = myStruct;
else
listLast->next = myStruct;
listLast = myStruct;
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and differentsizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.
– Ben Zotto
Mar 24 at 2:34
add a comment |
Ok, so I suggest that you forget about linked lists. Just stick to the first problem: reading data from a binary file.
The text of the problem is unclear about the size of the objects, so let's assume that it says: "There is a binary file which contains widgets composed by a 32 bit integer (little endian) and an 8 bit number representing an ASCII character. Dump all the widgets to stdout
one per line representing the integer in base 10 followed by a space and then the character".
Let's assume that your int
is 32 bit little endian and your char is a signed byte, i.e. let's assume you are on one of the 99.9% of the machines in the world.
Now you have to read the widgets, that is an int and a char. There are usually two functions you have to chose from when reading: fscanf
and fread
. The first one reads from data formatted for humans to read, while the second one reads bytes as they are from a file. Which one do you need now? the second one, so we need to use that.
In your code you write
while (!feof(fptr))
This is always wrong. The only correct way for reading a file is:
while (1)
// Read
// Check
// Use
Then you can find a way to read and check in the while condition, but believe me: write it this way the first time.
So lets populate the above template. To check if fread
succeeded you need to check if it returned the number of elements you asked for.
while (1)
Of course you can pack this in the while condition, but I don't see a reason for that.
Now I'd test this with your input and with a good debugger and check if all the data in the file gets printed out. If everything is ok, you can move on to the rest of the problem, that is putting these widgets in a linked list.
Here I assumed that you didn't learn struct
s yet. If this is not the case, you can work with them:
struct widget
int i;
char c;
;
[...]
while (1)
struct widget w;
// Read
int ok1 = fread(&w.i, 4, 1, fptr);
int ok2 = fread(&w.c, 1, 1, fptr);
// Check
if (ok1 != 1
Don't be deluded by the fact that the widget has the same structure of your data on file. You cannot trust that
fread(&w, 5, 1, fptr); // No! Don't do this
will read your data correctly. When making a struct, the compiler can put all the space it want between fields, so I wouldn't be surprised if sizeof(widget)
returned 8.
Disclaimer: I wrote the code directly on the browser and didn't check it!
add a comment |
I think you are getting a little too caught up in something that isn't really a fundamental problem. if you need to create a linked list from a file, you could use fscanf()
or fread()
or whatever you like to read a file into a buffer and manipulate that buffer as you wish. The same logic for parsing an array of ints (read in from a file) can be applied to parsing a buffer of strings from a binary file (you say binary file with sizeof(int)
, sizeof(char)
consecutively so I'm going to assume you mean it can be read into a buffer)
You say
"If it was just a regular file with ints and no binary and no chars, I
would have usedfscanf
to read the file and stored its contents into
an array, and then I would have traversed through the array and made
the nodes"
you can traverse a string, or list of strings (however you decide to parse your buffer) using the same logic to make nodes. That's the beauty of a data structure, or struct if you will, in C
.
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55310632%2fhow-to-create-a-linked-list-from-a-binary-input-file-with-first-few-bytes-being%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Step 1: Assume all data from an external source (e.g. from a file) is potentially malicious and/or corrupted and/or came from a different computer (with different sizeof(int)
and different endianness).
Step 2: Define your file format properly (taking step 1 into account). E.g. maybe it's supposed to be a value in the range 123 to 123456 that's stored as 4 consecutive bytes in little endian order (it should never be an int
); and maybe it's a byte containing an ASCII character (it should never be a "random whatever character set the compiler felt like using char
").
Step 3: Write some code to load data from the file into an array of bytes. If the file is expected to be small you can use realloc()
to increase the size of the buffer if the buffer wasn't big enough (but make sure there's a "max. file size" so that a malicious attacker can't trick you into consuming all available RAM and crashing due to "out of memory"). If the file is expected to be larger; look into functions like mmap()
. Alternatively, you can have a "read next part of file; parse next part of file" loop that recycles a fixed sized buffer.
Step 4: Write code to parse the "array of bytes" data and check that it actually complies with the file format specs in every way possible. For example, unsigned long value = buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24)
and if( (value < 123) || (value > 123456) ) { // Data is malformed
.
Step 5: Once you've parsed the data (and written code to handle every conceivable error condition in an appropriate manner, and know for a fact that it must be valid data), you can store the data in a structure and add that structure to a linked list. E.g.
// Parse and check it
if(bufferSize < position + 5)
return "File ends in the middle of a record";
unsigned long value = buffer[position] + (buffer[position+1] << 8) + (buffer[position+2] << 16) + (buffer[position+3] << 24);
if( (value < 123) || (value > 123456) )
return "Data was malformed (integer out of range)";
if( (buffer[position+4] < 0x20) || (buffer[position+4] >= 0x7F) )
return "Data was malformed (character not printable ASCII)";
// Create a structure
myStructureType * myStruct = malloc(sizeof(myStructureType));
if(myStruct == NULL)
return "Failed to allocate memory for structure";
myStruct->value = value;
myStruct->character = buffer[position+4];
position += 5;
// Add structure to singly linked list
myStruct->next = NULL;
if(listFirst == NULL)
listFirst = myStruct;
else
listLast->next = myStruct;
listLast = myStruct;
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and differentsizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.
– Ben Zotto
Mar 24 at 2:34
add a comment |
Step 1: Assume all data from an external source (e.g. from a file) is potentially malicious and/or corrupted and/or came from a different computer (with different sizeof(int)
and different endianness).
Step 2: Define your file format properly (taking step 1 into account). E.g. maybe it's supposed to be a value in the range 123 to 123456 that's stored as 4 consecutive bytes in little endian order (it should never be an int
); and maybe it's a byte containing an ASCII character (it should never be a "random whatever character set the compiler felt like using char
").
Step 3: Write some code to load data from the file into an array of bytes. If the file is expected to be small you can use realloc()
to increase the size of the buffer if the buffer wasn't big enough (but make sure there's a "max. file size" so that a malicious attacker can't trick you into consuming all available RAM and crashing due to "out of memory"). If the file is expected to be larger; look into functions like mmap()
. Alternatively, you can have a "read next part of file; parse next part of file" loop that recycles a fixed sized buffer.
Step 4: Write code to parse the "array of bytes" data and check that it actually complies with the file format specs in every way possible. For example, unsigned long value = buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24)
and if( (value < 123) || (value > 123456) ) { // Data is malformed
.
Step 5: Once you've parsed the data (and written code to handle every conceivable error condition in an appropriate manner, and know for a fact that it must be valid data), you can store the data in a structure and add that structure to a linked list. E.g.
// Parse and check it
if(bufferSize < position + 5)
return "File ends in the middle of a record";
unsigned long value = buffer[position] + (buffer[position+1] << 8) + (buffer[position+2] << 16) + (buffer[position+3] << 24);
if( (value < 123) || (value > 123456) )
return "Data was malformed (integer out of range)";
if( (buffer[position+4] < 0x20) || (buffer[position+4] >= 0x7F) )
return "Data was malformed (character not printable ASCII)";
// Create a structure
myStructureType * myStruct = malloc(sizeof(myStructureType));
if(myStruct == NULL)
return "Failed to allocate memory for structure";
myStruct->value = value;
myStruct->character = buffer[position+4];
position += 5;
// Add structure to singly linked list
myStruct->next = NULL;
if(listFirst == NULL)
listFirst = myStruct;
else
listLast->next = myStruct;
listLast = myStruct;
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and differentsizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.
– Ben Zotto
Mar 24 at 2:34
add a comment |
Step 1: Assume all data from an external source (e.g. from a file) is potentially malicious and/or corrupted and/or came from a different computer (with different sizeof(int)
and different endianness).
Step 2: Define your file format properly (taking step 1 into account). E.g. maybe it's supposed to be a value in the range 123 to 123456 that's stored as 4 consecutive bytes in little endian order (it should never be an int
); and maybe it's a byte containing an ASCII character (it should never be a "random whatever character set the compiler felt like using char
").
Step 3: Write some code to load data from the file into an array of bytes. If the file is expected to be small you can use realloc()
to increase the size of the buffer if the buffer wasn't big enough (but make sure there's a "max. file size" so that a malicious attacker can't trick you into consuming all available RAM and crashing due to "out of memory"). If the file is expected to be larger; look into functions like mmap()
. Alternatively, you can have a "read next part of file; parse next part of file" loop that recycles a fixed sized buffer.
Step 4: Write code to parse the "array of bytes" data and check that it actually complies with the file format specs in every way possible. For example, unsigned long value = buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24)
and if( (value < 123) || (value > 123456) ) { // Data is malformed
.
Step 5: Once you've parsed the data (and written code to handle every conceivable error condition in an appropriate manner, and know for a fact that it must be valid data), you can store the data in a structure and add that structure to a linked list. E.g.
// Parse and check it
if(bufferSize < position + 5)
return "File ends in the middle of a record";
unsigned long value = buffer[position] + (buffer[position+1] << 8) + (buffer[position+2] << 16) + (buffer[position+3] << 24);
if( (value < 123) || (value > 123456) )
return "Data was malformed (integer out of range)";
if( (buffer[position+4] < 0x20) || (buffer[position+4] >= 0x7F) )
return "Data was malformed (character not printable ASCII)";
// Create a structure
myStructureType * myStruct = malloc(sizeof(myStructureType));
if(myStruct == NULL)
return "Failed to allocate memory for structure";
myStruct->value = value;
myStruct->character = buffer[position+4];
position += 5;
// Add structure to singly linked list
myStruct->next = NULL;
if(listFirst == NULL)
listFirst = myStruct;
else
listLast->next = myStruct;
listLast = myStruct;
Step 1: Assume all data from an external source (e.g. from a file) is potentially malicious and/or corrupted and/or came from a different computer (with different sizeof(int)
and different endianness).
Step 2: Define your file format properly (taking step 1 into account). E.g. maybe it's supposed to be a value in the range 123 to 123456 that's stored as 4 consecutive bytes in little endian order (it should never be an int
); and maybe it's a byte containing an ASCII character (it should never be a "random whatever character set the compiler felt like using char
").
Step 3: Write some code to load data from the file into an array of bytes. If the file is expected to be small you can use realloc()
to increase the size of the buffer if the buffer wasn't big enough (but make sure there's a "max. file size" so that a malicious attacker can't trick you into consuming all available RAM and crashing due to "out of memory"). If the file is expected to be larger; look into functions like mmap()
. Alternatively, you can have a "read next part of file; parse next part of file" loop that recycles a fixed sized buffer.
Step 4: Write code to parse the "array of bytes" data and check that it actually complies with the file format specs in every way possible. For example, unsigned long value = buffer[0] + (buffer[1] << 8) + (buffer[2] << 16) + (buffer[3] << 24)
and if( (value < 123) || (value > 123456) ) { // Data is malformed
.
Step 5: Once you've parsed the data (and written code to handle every conceivable error condition in an appropriate manner, and know for a fact that it must be valid data), you can store the data in a structure and add that structure to a linked list. E.g.
// Parse and check it
if(bufferSize < position + 5)
return "File ends in the middle of a record";
unsigned long value = buffer[position] + (buffer[position+1] << 8) + (buffer[position+2] << 16) + (buffer[position+3] << 24);
if( (value < 123) || (value > 123456) )
return "Data was malformed (integer out of range)";
if( (buffer[position+4] < 0x20) || (buffer[position+4] >= 0x7F) )
return "Data was malformed (character not printable ASCII)";
// Create a structure
myStructureType * myStruct = malloc(sizeof(myStructureType));
if(myStruct == NULL)
return "Failed to allocate memory for structure";
myStruct->value = value;
myStruct->character = buffer[position+4];
position += 5;
// Add structure to singly linked list
myStruct->next = NULL;
if(listFirst == NULL)
listFirst = myStruct;
else
listLast->next = myStruct;
listLast = myStruct;
edited Mar 24 at 2:29
answered Mar 24 at 2:16
BrendanBrendan
14k1532
14k1532
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and differentsizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.
– Ben Zotto
Mar 24 at 2:34
add a comment |
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and differentsizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.
– Ben Zotto
Mar 24 at 2:34
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and different
sizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.– Ben Zotto
Mar 24 at 2:34
This is a good comprehensive answer. @noobie, if some of this seems over your head currently (ie, things like endianness and different
sizeof(int)
) then you may wish to ask followup questions about this. The short story here is that you can't really reliably shove the contents of your C structure into a file and then suck them back up. There may be cases where you could do so, but you shouldn't learn it from that direction; follow @Brendan's advice here for defining a binary format for your file and then processing it securely into your memory structures. This pattern will serve you well.– Ben Zotto
Mar 24 at 2:34
add a comment |
Ok, so I suggest that you forget about linked lists. Just stick to the first problem: reading data from a binary file.
The text of the problem is unclear about the size of the objects, so let's assume that it says: "There is a binary file which contains widgets composed by a 32 bit integer (little endian) and an 8 bit number representing an ASCII character. Dump all the widgets to stdout
one per line representing the integer in base 10 followed by a space and then the character".
Let's assume that your int
is 32 bit little endian and your char is a signed byte, i.e. let's assume you are on one of the 99.9% of the machines in the world.
Now you have to read the widgets, that is an int and a char. There are usually two functions you have to chose from when reading: fscanf
and fread
. The first one reads from data formatted for humans to read, while the second one reads bytes as they are from a file. Which one do you need now? the second one, so we need to use that.
In your code you write
while (!feof(fptr))
This is always wrong. The only correct way for reading a file is:
while (1)
// Read
// Check
// Use
Then you can find a way to read and check in the while condition, but believe me: write it this way the first time.
So lets populate the above template. To check if fread
succeeded you need to check if it returned the number of elements you asked for.
while (1)
Of course you can pack this in the while condition, but I don't see a reason for that.
Now I'd test this with your input and with a good debugger and check if all the data in the file gets printed out. If everything is ok, you can move on to the rest of the problem, that is putting these widgets in a linked list.
Here I assumed that you didn't learn struct
s yet. If this is not the case, you can work with them:
struct widget
int i;
char c;
;
[...]
while (1)
struct widget w;
// Read
int ok1 = fread(&w.i, 4, 1, fptr);
int ok2 = fread(&w.c, 1, 1, fptr);
// Check
if (ok1 != 1
Don't be deluded by the fact that the widget has the same structure of your data on file. You cannot trust that
fread(&w, 5, 1, fptr); // No! Don't do this
will read your data correctly. When making a struct, the compiler can put all the space it want between fields, so I wouldn't be surprised if sizeof(widget)
returned 8.
Disclaimer: I wrote the code directly on the browser and didn't check it!
add a comment |
Ok, so I suggest that you forget about linked lists. Just stick to the first problem: reading data from a binary file.
The text of the problem is unclear about the size of the objects, so let's assume that it says: "There is a binary file which contains widgets composed by a 32 bit integer (little endian) and an 8 bit number representing an ASCII character. Dump all the widgets to stdout
one per line representing the integer in base 10 followed by a space and then the character".
Let's assume that your int
is 32 bit little endian and your char is a signed byte, i.e. let's assume you are on one of the 99.9% of the machines in the world.
Now you have to read the widgets, that is an int and a char. There are usually two functions you have to chose from when reading: fscanf
and fread
. The first one reads from data formatted for humans to read, while the second one reads bytes as they are from a file. Which one do you need now? the second one, so we need to use that.
In your code you write
while (!feof(fptr))
This is always wrong. The only correct way for reading a file is:
while (1)
// Read
// Check
// Use
Then you can find a way to read and check in the while condition, but believe me: write it this way the first time.
So lets populate the above template. To check if fread
succeeded you need to check if it returned the number of elements you asked for.
while (1)
Of course you can pack this in the while condition, but I don't see a reason for that.
Now I'd test this with your input and with a good debugger and check if all the data in the file gets printed out. If everything is ok, you can move on to the rest of the problem, that is putting these widgets in a linked list.
Here I assumed that you didn't learn struct
s yet. If this is not the case, you can work with them:
struct widget
int i;
char c;
;
[...]
while (1)
struct widget w;
// Read
int ok1 = fread(&w.i, 4, 1, fptr);
int ok2 = fread(&w.c, 1, 1, fptr);
// Check
if (ok1 != 1
Don't be deluded by the fact that the widget has the same structure of your data on file. You cannot trust that
fread(&w, 5, 1, fptr); // No! Don't do this
will read your data correctly. When making a struct, the compiler can put all the space it want between fields, so I wouldn't be surprised if sizeof(widget)
returned 8.
Disclaimer: I wrote the code directly on the browser and didn't check it!
add a comment |
Ok, so I suggest that you forget about linked lists. Just stick to the first problem: reading data from a binary file.
The text of the problem is unclear about the size of the objects, so let's assume that it says: "There is a binary file which contains widgets composed by a 32 bit integer (little endian) and an 8 bit number representing an ASCII character. Dump all the widgets to stdout
one per line representing the integer in base 10 followed by a space and then the character".
Let's assume that your int
is 32 bit little endian and your char is a signed byte, i.e. let's assume you are on one of the 99.9% of the machines in the world.
Now you have to read the widgets, that is an int and a char. There are usually two functions you have to chose from when reading: fscanf
and fread
. The first one reads from data formatted for humans to read, while the second one reads bytes as they are from a file. Which one do you need now? the second one, so we need to use that.
In your code you write
while (!feof(fptr))
This is always wrong. The only correct way for reading a file is:
while (1)
// Read
// Check
// Use
Then you can find a way to read and check in the while condition, but believe me: write it this way the first time.
So lets populate the above template. To check if fread
succeeded you need to check if it returned the number of elements you asked for.
while (1)
Of course you can pack this in the while condition, but I don't see a reason for that.
Now I'd test this with your input and with a good debugger and check if all the data in the file gets printed out. If everything is ok, you can move on to the rest of the problem, that is putting these widgets in a linked list.
Here I assumed that you didn't learn struct
s yet. If this is not the case, you can work with them:
struct widget
int i;
char c;
;
[...]
while (1)
struct widget w;
// Read
int ok1 = fread(&w.i, 4, 1, fptr);
int ok2 = fread(&w.c, 1, 1, fptr);
// Check
if (ok1 != 1
Don't be deluded by the fact that the widget has the same structure of your data on file. You cannot trust that
fread(&w, 5, 1, fptr); // No! Don't do this
will read your data correctly. When making a struct, the compiler can put all the space it want between fields, so I wouldn't be surprised if sizeof(widget)
returned 8.
Disclaimer: I wrote the code directly on the browser and didn't check it!
Ok, so I suggest that you forget about linked lists. Just stick to the first problem: reading data from a binary file.
The text of the problem is unclear about the size of the objects, so let's assume that it says: "There is a binary file which contains widgets composed by a 32 bit integer (little endian) and an 8 bit number representing an ASCII character. Dump all the widgets to stdout
one per line representing the integer in base 10 followed by a space and then the character".
Let's assume that your int
is 32 bit little endian and your char is a signed byte, i.e. let's assume you are on one of the 99.9% of the machines in the world.
Now you have to read the widgets, that is an int and a char. There are usually two functions you have to chose from when reading: fscanf
and fread
. The first one reads from data formatted for humans to read, while the second one reads bytes as they are from a file. Which one do you need now? the second one, so we need to use that.
In your code you write
while (!feof(fptr))
This is always wrong. The only correct way for reading a file is:
while (1)
// Read
// Check
// Use
Then you can find a way to read and check in the while condition, but believe me: write it this way the first time.
So lets populate the above template. To check if fread
succeeded you need to check if it returned the number of elements you asked for.
while (1)
Of course you can pack this in the while condition, but I don't see a reason for that.
Now I'd test this with your input and with a good debugger and check if all the data in the file gets printed out. If everything is ok, you can move on to the rest of the problem, that is putting these widgets in a linked list.
Here I assumed that you didn't learn struct
s yet. If this is not the case, you can work with them:
struct widget
int i;
char c;
;
[...]
while (1)
struct widget w;
// Read
int ok1 = fread(&w.i, 4, 1, fptr);
int ok2 = fread(&w.c, 1, 1, fptr);
// Check
if (ok1 != 1
Don't be deluded by the fact that the widget has the same structure of your data on file. You cannot trust that
fread(&w, 5, 1, fptr); // No! Don't do this
will read your data correctly. When making a struct, the compiler can put all the space it want between fields, so I wouldn't be surprised if sizeof(widget)
returned 8.
Disclaimer: I wrote the code directly on the browser and didn't check it!
answered Mar 24 at 19:10
Costantino GranaCostantino Grana
1,0381722
1,0381722
add a comment |
add a comment |
I think you are getting a little too caught up in something that isn't really a fundamental problem. if you need to create a linked list from a file, you could use fscanf()
or fread()
or whatever you like to read a file into a buffer and manipulate that buffer as you wish. The same logic for parsing an array of ints (read in from a file) can be applied to parsing a buffer of strings from a binary file (you say binary file with sizeof(int)
, sizeof(char)
consecutively so I'm going to assume you mean it can be read into a buffer)
You say
"If it was just a regular file with ints and no binary and no chars, I
would have usedfscanf
to read the file and stored its contents into
an array, and then I would have traversed through the array and made
the nodes"
you can traverse a string, or list of strings (however you decide to parse your buffer) using the same logic to make nodes. That's the beauty of a data structure, or struct if you will, in C
.
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
add a comment |
I think you are getting a little too caught up in something that isn't really a fundamental problem. if you need to create a linked list from a file, you could use fscanf()
or fread()
or whatever you like to read a file into a buffer and manipulate that buffer as you wish. The same logic for parsing an array of ints (read in from a file) can be applied to parsing a buffer of strings from a binary file (you say binary file with sizeof(int)
, sizeof(char)
consecutively so I'm going to assume you mean it can be read into a buffer)
You say
"If it was just a regular file with ints and no binary and no chars, I
would have usedfscanf
to read the file and stored its contents into
an array, and then I would have traversed through the array and made
the nodes"
you can traverse a string, or list of strings (however you decide to parse your buffer) using the same logic to make nodes. That's the beauty of a data structure, or struct if you will, in C
.
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
add a comment |
I think you are getting a little too caught up in something that isn't really a fundamental problem. if you need to create a linked list from a file, you could use fscanf()
or fread()
or whatever you like to read a file into a buffer and manipulate that buffer as you wish. The same logic for parsing an array of ints (read in from a file) can be applied to parsing a buffer of strings from a binary file (you say binary file with sizeof(int)
, sizeof(char)
consecutively so I'm going to assume you mean it can be read into a buffer)
You say
"If it was just a regular file with ints and no binary and no chars, I
would have usedfscanf
to read the file and stored its contents into
an array, and then I would have traversed through the array and made
the nodes"
you can traverse a string, or list of strings (however you decide to parse your buffer) using the same logic to make nodes. That's the beauty of a data structure, or struct if you will, in C
.
I think you are getting a little too caught up in something that isn't really a fundamental problem. if you need to create a linked list from a file, you could use fscanf()
or fread()
or whatever you like to read a file into a buffer and manipulate that buffer as you wish. The same logic for parsing an array of ints (read in from a file) can be applied to parsing a buffer of strings from a binary file (you say binary file with sizeof(int)
, sizeof(char)
consecutively so I'm going to assume you mean it can be read into a buffer)
You say
"If it was just a regular file with ints and no binary and no chars, I
would have usedfscanf
to read the file and stored its contents into
an array, and then I would have traversed through the array and made
the nodes"
you can traverse a string, or list of strings (however you decide to parse your buffer) using the same logic to make nodes. That's the beauty of a data structure, or struct if you will, in C
.
edited Mar 31 at 7:59
Rarblack
3,19541229
3,19541229
answered Mar 23 at 6:16
Dan LDan L
64
64
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
add a comment |
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
Thank you for your response, I really appreciate it. So would it be something like while(!feof(fptr)) fread(some_linked_list_pointer, sizeof(int)+sizeof(char), 1, fptr);
– noobie
Mar 24 at 0:33
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55310632%2fhow-to-create-a-linked-list-from-a-binary-input-file-with-first-few-bytes-being%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Technically the answer to your question is "yes" (there is a way to create linked lists). Why do you need to create an array first? If you can traverse an array, you can traverse an input file. Where exactly are you stuck?
– melpomene
Mar 23 at 5:24
If you want an answer, you need to really clarify this question and show some effort. Let's see, you could start editing your question and show us your code for reading one integer and one char from a binary file. Before that show us the hex dump of such a file.
– Costantino Grana
Mar 23 at 7:05
@melpomene I want to traverse the input file and put it into a linked list. I am confused because I dont know how to use fscanf when it is a linked list. Would I use %d or %c in the parameters? I dont know how to put both things into one node. I am confused because the file is a binary file. I am sorry if I am not explaining my problem well.
– noobie
Mar 24 at 0:41
@CostantinoGrana I edited the post to add code. The reason I didn't add code was because I didn't know how to form the code in the first place and I was confused as to how I would go about forming it. I have added some code to make my problem more clear. If you could help, that would be great, I apologize if my question wasn't clear, I am a beginner and I really don't know how to go about solving this problem.
– noobie
Mar 24 at 0:56