Task is to read a map from a file and then display it. The binary file begins with 2 floats and continues with objects of this format:
struct Node {
float height;
int terrainType;
float visitsCount;
struct Node *next;
}Node;
And the function doing the reading:
void showMapTerrain(struct Node Node)
{
FILE *fp;
if ((fp = fopen("map.bin", "rb")) == NULL) {
puts("Unable to open file.");
exit(7);
}
float mapLenght, alt;
if (fread(&mapLenght, sizeof(float), 1, fp) != 1) {
puts("Unable to read from file.");
exit(18);
}
if (fread(&alt, sizeof(float), 1, fp) != 1) {
puts("Unable to read from file.");
exit(20);
}
/*Idea with this is to get the 2 floats out of the way so I can start reading the objects with a single fread.*/
char *mapTerrain = (char *)calloc(mapLenght, sizeof(char));
while (1) {
if (fread(&Node, sizeof(struct Node), 1, fp) != 1) {
//But this bit right here fails, it reads 0 objects.
printf("fread: %d\n", fread(&Node, sizeof(struct Node), 1, fp));
puts("Unable to read from file.");
exit(30);
}
*mapTerrain = Node.terrainType;
}
puts("Terrain type map: ");
while (*mapTerrain) {
printf("[%c]", *mapTerrain);
}
free(mapTerrain);
}
The 2 floats are only in the beginning, so they're outside the loop, that reads objects. I'm pretty sure the syntax for the fread is correct, it's unclear to me what the problem is.
Also, it's not required to make a linked list in this function, we're creating an array of numbers (ranging 1-4, hence char*) and then displaying it.
Edit: the function doing the writing:
void addToFile(struct Node Node)
{
FILE *fp;
float mapLenght, alt;
if ((fp = fopen("map.bin", "rb")) == NULL) {
if ((fp = fopen("map.bin", "wb")) == NULL) {
//2 fopens to check if the file exists. If it doesn't, the user has to input the //2 floats in the beginning. Otherwise we skip straight to adding objects in the //file
puts("Unable to open the file.");
exit(7);
}
puts("How long is the map?");
scanf("%f", &mapLenght);
if (fwrite(&mapLenght, sizeof(float), 1, fp) != 1) {
puts("Unable to write to file.");
exit(6);
}
puts("What's the map's altitude?");
scanf("%f", &alt);
if (fwrite(&alt, sizeof(float), 1, fp) != 1) {
puts("Unable to write to file.");
}
fclose(fp);
}
else {
fclose(fp);
}
if ((fp = fopen("map.bin", "ab")) == NULL){
puts("Unable to open file for further writing.");
exit(7);
}
int c = 0;
while (1) {
puts("Inputting data for individual square meters of the map:");
printf("How high is square meter %d?", ++c);
puts("('-1' to stop.)");
scanf("%f", &Node.height);
if (Node.height == -1) {
system("cls");
puts("You've decided to stop adding data.");
break;
}
printf("What's the terrain type of square meter %d?\n", c);
puts("Values allowed: ");
puts("0 - flora");
puts("1 - waste");
puts("2 - water");
puts("3 - road");
puts("4 - building");
Node.terrainType = 7;
while (1) {
scanf("%d", &Node.terrainType);
if (Node.terrainType < 0 || Node.terrainType>4) {
puts("Invalid data.");
}
else {
break;
}
}
printf("What's the daily visit count for square meter %d?", c);
scanf("%f", &Node.visitsCount);
if (fwrite(&Node, sizeof(Node), 1, fp) != 1) {
//Unlike the other function, everything here works properly, even this fwrite
puts("Error writing data to file.");
exit(6);
}
}
}
My apologies, but I made a very dumb mistake. fread was reading objects just fine, it returned 0 when it got to EOF. I assumed it returned 0 on the first iteration. Fix is bellow:
int *mapTerrain = (int *)calloc(mapLenght, sizeof(int));
int i = 0;
while (1) {
if (fread(&Node, sizeof(struct Node), 1, fp) != 1) {
break;
}
mapTerrain[i] = Node.terrainType;
i++;
}
puts("Map by terrain type: ");
int n;
for (n = 0; n < i; n++) {
printf("[%d]", mapTerrain[n]);
}
puts("");
free(mapTerrain);
Related
I have a static array of structs and through a void new_cinema() function i want to get an info about a film and so on and write this info to the file and then using another function i want to read this info through the file. I've tried to do this:
FILE* file;
fpos_t current_position = 0;
struct cinema
{
char name[256];
char session[256];
double price;
int audience;
};
struct cinema october[25];
int counter = 0;
int cntr[N] = { 0 };
void new_cinema()
{
if (counter < N)
{
if (counter == 0)
{
fopen_s(&file, "file.bin", "wb");
if (file == NULL)
{
printf("An error occured1\n");
fclose(file);
return;
}
}
if (counter != 0)
{
fopen_s(&file, "file.bin", "ab");
if (file == NULL)
{
printf("An error occured2\n");
fclose(file);
return;
}
}
fsetpos(file, ¤t_position);
printf("\nWrite the name of the movie:\n");
gets_s(october[counter].name, 255);
printf("\nEnter the session time:\n");
scanf_s("%s", october[counter].session, 255);
printf("\nEnter ticket price:\n");
scanf_s("%lf", &october[counter].price);
printf("\nEnter the number of viewers:\n");
scanf_s("%d", &october[counter].audience);
fwrite(&october[counter], sizeof(struct cinema), 1, file);
fgetpos(file, ¤t_position);
counter++;
}
else
printf("\nThe limit has gone!\n");
fclose(file);
}
In this part of the code i create a struct cinema and then an array october of the struct cinema type. In the new_cinema() function if counter is zero, which means the user didn't actually create anything before i fopen_s(&file, "file.bin", "wb"); and set the the position to zero fsetpos(file, ¤t_position);, after that i get some info and write it to the file fwrite(&october[counter], sizeof(struct cinema), 1, file); and then i get the current position and increment the counter.
I think that i'm doing all this wrong, firsty i'm not sure abot the
fwrite(&october[counter], sizeof(struct cinema), 1, file);, i don't know about the & because it is the array. Do i need & in here? Secondly, the fgetpos() and fsetpos() when i get the current position and when the user enters new_cinema() again and fsetpos sets the position of indicator of stream i guess that after completeing receiving information about the movie and writing this info to the file, the last character of the previous structure can be rewritten to reflect the new information. Is it ?
And after doing all this, I try to read this information from the file, i wrote this code, but it is incorrect:
void read_struct()
{
fopen_s(&file, "file.bin", "rb");
if (file == NULL)
{
printf("couldn't read the file\n");
return;
}
struct cinema *testing;
testing = (struct cinema*)malloc(sizeof(struct cinema) * 25);
int i = 0;
while(!feof(file))
{
fread(&testing[i], sizeof(struct cinema), 1, file);
++i;
}
for (i = 0; i < 25; i++)
{
printf("%s\n", testing[i].name);
printf("%s\n", testing[i].session);
printf("%lf", testing[i].price);
printf("%d\n", testing[i].audience);
}
}
Assistance is really appreciated!
I have written content to a file using a file pointer. I would now like to print this data in the form of an array. I am new to programming in C, and it looks like printing file pointers is different.
Here is an example of my code,
int main(){
double a=0;
double b=0;
double c=0;
double d=0;
int bufferLength = 330752;
char buffer[bufferLength];
FILE *fp = fopen("original.dat", "r");
if (!fp){
printf("Cant open the original file\n");
return -1;
}
FILE *fp1 = fopen("24bitnoise.dat", "r");
if (!fp1){
printf("Cant open the noise file\n");
return -1;
}
FILE *outfp= fopen("out.dat", "w");
if(outfp == NULL)
{
printf("Unable to create file\n");
}
while(fgets(buffer, bufferLength, fp)) {
if (2==sscanf(buffer, "%lf %lf", &a,&b)){ // Just printing col 2 //
// printf("b: %f\n", b);
fprintf(outfp, "%0.25f\n", b);
}
}
FILE *noisefp= fopen("outnoise.dat", "w");
if(noisefp == NULL)
{
printf("Unable to create file\n");
}
while(fgets(buffer, bufferLength, fp1)) {
if (2==sscanf(buffer, "%lf %lf", &c,&d)){ // Just printing col 2 //
fprintf(noisefp, "%0.25f\n", d);
}
}
printf("%f", outfp);
printf("File transferred\n");
fclose(outfp);
fclose(fp);
fclose(fp1);
fclose(noisefp);
return 0;
}
I would now like to print the values from *outfp in the form of an array.
OP is attempting, incorrectly, to print the contents of a file with
printf("%f", outfp);
"%f" expects a matching double, not a FILE *.
To print the text contents of a file, line-by-line:
FILE *inf = fopen("out.dat", "r");
if (inf) {
while(fgets(buffer, bufferLength, inf)) {
printf("%s", buffer);
}
fclose(inf);
}
how can I put these values into an array?
The "trick" is how to determine the size of the array.
One simple approach:
size_t count = 0;
while(fgets(buffer, bufferLength, fp)) {
if (2==sscanf(buffer, "%lf %lf", &a,&b)) {
count++;
}
}
double fp_array = malloc(sizeof *fp_array * count);
if (fp_array == NULL) Handle_Out_of_memory(); // Some tbd code
// Read again
rewind(fp);
size_t i = 0;
while(fgets(buffer, bufferLength, fp)) {
if (2==sscanf(buffer, "%lf %lf", &a,&b)) {
fp_array[i++] = b;
}
}
// Use fp_array
free(fp_array); // clean up when done.
A more elegant approach would re-size the allocation as needed and perform only one read pass.
I have a .dat file with two columns, time & channel of audio data. I am trying to just read the column channel, write it in a different .dat file and save it.
In the code, I have stored the file in a buffer and I'm able to read the values in the column. Now I'm trying to put the second column in another file named out.dat, but it looks like it's not writing anything into the file. Here's what I've done.
int main(){
double a=0;
double b=0;
int bufferLength = 330750;
char buffer[bufferLength];
FILE *fp = fopen("original.dat", "r");
if (!fp){
printf("Cant open file\n");
return -1;
}
FILE *outfp= fopen("out.dat", "w");
if(outfp == NULL)
{
printf("Unable to create file\n");
}
while(fgets(buffer, bufferLength, fp)) {
if (2==sscanf(buffer, "%lf %lf", &a,&b)){ // Just printing col 2 //
printf("b: %f\n", b);
}
}
for(bufferLength=0; bufferLength<330750; bufferLength++){
fputs(&bufferLength, outfp);
}
printf("File transferred\n");
fclose(outfp);
fclose(fp);
return 0;
}
First, you can copy the data into the new file and count the numbers with:
int counter = 0;
while (fgets(buffer, bufferLength, fp)) {
if (2 == sscanf(buffer, "%lf %lf", &a, &b)) {
counter += 1;
fprintf(outfp, "%f\n", b);
}
}
Then create an array and read the file again:
double *data = malloc(sizeof(*data) * counter);
if (!data) { /* handle error */ }
rewind(fp); // If rewind is not available use fseek(fp, 0, SEEK_SET)
int index = 0;
while (fgets(buffer, bufferLength, fp)) {
if (2 == sscanf(buffer, "%lf %lf", &a, &b)) {
data[index++] = b; // Just saving b??
}
}
Alternatively, you can combine these 2 loops and use realloc to allocate memory for the array as you go:
double *data = NULL; // Important: needs to be initialized to NULL
int counter = 0;
while (fgets(buffer, bufferLength, fp)) {
if (2 == sscanf(buffer, "%lf %lf", &a, &b)) {
double *temp = realloc(data, sizeof(*data) * (counter + 1));
if (!temp) { /* handle error.... */ }
data = temp;
data[counter++] = b;
fprintf(outfp, "%f\n", b);
}
}
I'm studying textfile topic in C and I have got a question: what can I use instead of __fpurge(stdin); but make this function work like __fpurge(stdin); and I am not allowed to include <stdlib.h> in this program. I have read this c - need an alternative for fflush but as long as I'm not allowed to #include <stdlib.h> so I can't use strtol.
void generateBill() {
FILE *fp, *fp1;
struct Bill t;
int id, found = 0, ch1, brel = 0;
char billname[40];
fp = fopen(fbill, "rb");
printf("ID\tName\tPrice\n\n");
while (1) {
fread(&t, sizeof(t), 1, fp);
if (feof(fp)) {
break;
}
printf("%d\t", t.pid);
printf("%s\t", t.pname);
printf("%d\t\t\t\n", t.pprice);
total = total + t.pprice;
}
printf("\n\n=================== Total Bill Amount %d\n\n", total);
fclose(fp);
if (total != 0) {
//__fpurge(stdin);
printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
scanf("%d", &ch1);
if (ch1 == 1) {
brel = billFileNo();
sprintf(billname, "%s%d", " ", brel);
strcat(billname, "dat");
fp = fopen(fbill, "rb");
fp1 = fopen(billname, "wb");
while (1) {
fread(&t, sizeof(t), 1, fp);
if (feof(fp)) {
break;
}
fwrite(&t, sizeof(t), 1, fp1);
}
fclose(fp);
fclose(fp1);
fp = fopen(fbill, "wb");
fclose(fp);
}
total = 0;
}
}
for a replacement for __fpurge(stdin) suggest:
int ch;
while( (ch = getchar() ) != EOF && ch != '\n' ){;}
which only requires #include <stdio.h>
__fpurge is a non-standard function only available on some systems (glibc 2.1.95, IBM zOS...) that discards input read into the stream buffer not yet consumed by getc().
As explained in the linux manual page, Usually it is a mistake to want to discard input buffers.
You read user input with scanf(), which stops scanning input when the requested conversion is completed, for example %d stops reading the characters typed by the user when it reads a character that cannot continue the number and leaves this character in the input stream. Since stdin is usually line buffered when attached to a terminal, you should just read and discard any remaining bytes in the line input by the user after you process the input.
Here is a simple function for this purpose:
int flush_input(FILE *fp) {
int c;
while ((c = getc(fp)) != EOF && c != '\n')
continue;
return c;
}
You would call this function after processing user input and you should test the return value of scanf() to ensure the user input had the expected syntax.
Here is a modified version of you function:
#include <errno.h>
#include <string.h>
// return a non zero error code in case of failure
int generateBill(void) {
FILE *fp, *fp1;
struct Bill t;
int id, found = 0, ch1, brel = 0;
char billname[40];
fp = fopen(fbill, "rb");
if (fp == NULL) {
fprintf(sdterr, "cannot open %s: %s\n", fbill, strerror(errno));
return 1;
}
printf("ID\tName\tPrice\n\n");
while (fread(&t, sizeof(t), 1, fp) == 1) {
printf("%d\t", t.pid);
printf("%s\t", t.pname);
printf("%d\t\t\t\n", t.pprice);
total = total + t.pprice;
}
printf("\n\n=================== Total Bill Amount %d\n\n", total);
if (total != 0) {
int res;
printf("\n\n\n Do you want to generate Final Bill[1 yes/any number to no]:");
while ((res = scanf("%d", &ch1)) == 0) {
fprintf("Invalid input. Try again\n");
flush_input(stdin);
}
flush_input(stdin);
if (res == EOF) {
fprintf("premature end of file on input\n");
fclose(fp);
return 2;
}
if (ch1 == 1) {
brel = billFileNo();
snprintf(billname, sizeof billname, "bill-%d-dat", brel);
rewind(fp);
fp1 = fopen(billname, "wb");
if (fp1 == NULL) {
fprintf(sdterr, "cannot open %s: %s\n", billname, strerror(errno));
fclose(fp);
return 1;
}
while (fread(&t, sizeof(t), 1, fp) == 1) {
fwrite(&t, sizeof(t), 1, fp1);
}
fclose(fp1);
}
}
fclose(fp);
return 0;
}
I have a structure that looks like this :
typedef struct Student { //dynamically allocated structure
char *first_name;
char *last_name;
float grade;
}Student;
What I want to do is to read data from a binary file and dynamically allocate memory for the first_name and last_name fields. I successfully completed this task when reading from a normal .txt file. Here is the code:
void Read_From_File(const char *file_name, Student *p_destination, const int number_of_students)
{
FILE *p_file = fopen(file_name, "r");
if (!p_file)
{
perror("Error opening the file. \n");
exit(EXIT_FAILURE);
}
int index = 0;
while (index < number_of_students)
{
unsigned char buffer[256];
fscanf (p_file, "%s", buffer);
p_destination[index].last_name = (char*)malloc(strlen(buffer) + 1);
strcpy(p_destination[index].last_name, buffer);
fscanf(p_file, "%s", buffer);
p_destination[index].first_name = (char*)malloc(strlen(buffer) + 1);
strcpy(p_destination[index].first_name, buffer);
fscanf(p_file, "%f", &p_destination[index].grade);
index++;
}
fclose(p_file);
}
It was simple because fscanf can read data individually and has type specifiers, like the following : %s last name / %s first name / %f grade. I don't know how to use fread to read single pieces of data like I did with fscanf.
Here is what I've tried so far, but it doesn't work:
int number_of_students = 0;
unsigned char buffer[256];
char file_name[10];
FILE *p_file = NULL;
Student *p_students = NULL;
printf("Enter file name. \n");
scanf("%s", file_name);
p_file = fopen(file_name, "rb");
fread(&number_of_students, sizeof(number_of_students), 1, p_file);
p_students = (Student *)malloc(number_of_students * sizeof(Student));
if (!p_students)
{
perror("Could not allocate memory. \n");
exit(EXIT_FAILURE);
}
for (int index = 0; index < number_of_students; ++index)
{
fread(buffer, sizeof(char), 1, p_file);
p_students[index].last_name = (char *)malloc(strlen(buffer) + 1);
if (!p_students[index].last_name)
{
printf("Could not allocate memory. \n");
exit(EXIT_FAILURE);
}
strcpy(p_students[index].last_name, buffer);
fread(buffer, sizeof(char), 1, p_file);
p_students[index].first_name = (char *)malloc(strlen(buffer) + 1);
if (!p_students[index].first_name)
{
printf("Could not allocate memory. \n");
exit(EXIT_FAILURE);
}
strcpy(p_students[index].first_name, buffer);
fread(&p_students[index].grade, sizeof(float), 1, p_file);
}
Print_Students(p_students, number_of_students);
Also, the Print_Students function looks like this:
void Print_Students(Student *p_students, int number_of_students)
{
printf("================================================================================================\n");
for (unsigned int index = 0; index < number_of_students; ++index)
{
printf("\t\t===================== Student %d =====================\n\n", index);
printf("Last name: %s\n", p_students[index].last_name);
printf("First name: %s\n", p_students[index].first_name);
printf("Grade: %.2f\n", p_students[index].grade);
}
printf("\n");
}
The input.txt file looks like this:
19
Terresa Minaya 9.50
Otto Pleiman 7
Illa Holzman 5.25
Alona Greeson 3.40
Natalya Vickrey 10
Catrina Cho 9.34
Loida Dinapoli 9.43
Neely Mcelligott 8.30
Salome Urban 8.75
Rosetta Dagenhart 9.10
Diane Cooksey 10
Novella Longmire 3
Gilberte Manganaro 4
Joye Humbert 5
Justa Larock 6
Delana Bufkin 7
Genaro Kenison 8.98
Refugio Arena 4.56
Iona Nida 7.65
I loaded the data from this file in my vector of Students, and then I wrote the input.bin file using based on the data from my vector. I've used the following code to write to binary:
void Write_To_Binary(const char *file_name, Student *p_source, const int number_of_students)
{
size_t successfully_written = 0;
FILE *p_file = fopen(file_name, "wb");
if (!p_file)
{
perror("Error opening the file. \n");
exit(EXIT_FAILURE);
}
successfully_written = fwrite(&number_of_students, sizeof(number_of_students), 1, p_file);
if (successfully_written != 1)
{
perror("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
successfully_written = fwrite(p_source, sizeof(Student), number_of_students, p_file);
if (successfully_written != number_of_students)
{
perror("Error writing all the student data. \n");
exit(EXIT_FAILURE);
}
fclose(p_file);
}
UPDATE: I've followed iBug's solution and it worked. I changed the data fields as it follows: sizeof(last_name) last_name sizeof(first_name) first_name grade.
I'll post here the functions I've used to write to the bin file, and read from it.
Here is the function Write_To_Binary
void Write_To_Binary(const char *file_name, Student *p_source, const unsigned int number_of_students)
{
FILE *p_file = fopen(file_name, "wb");
if (!p_file)
{
perror("Error opening the file. \n");
exit(EXIT_FAILURE);
}
size_t successfully_written = 0;
successfully_written = fwrite(&number_of_students, sizeof(number_of_students), 1, p_file);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
unsigned int width = 0, width1 = 0;
for (unsigned int index = 0; index < number_of_students; ++index)
{
width = strlen(p_source[index].last_name) + 1;
successfully_written = fwrite(&width, sizeof(width), 1, p_file);
printf("Name: %s Width: %d \n", p_source[index].last_name, width);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
successfully_written = fwrite(p_source[index].last_name, width, 1, p_file);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
width = strlen(p_source[index].first_name) + 1;
successfully_written = fwrite(&width, sizeof(width), 1, p_file);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
successfully_written = fwrite(p_source[index].first_name, width, 1, p_file);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
successfully_written = fwrite(&p_source[index].grade, sizeof(float), 1, p_file);
if (successfully_written != 1)
{
printf("Error writing to the file. \n");
exit(EXIT_FAILURE);
}
}
fclose(p_file);
}
And here is the function Read_From_Binary
void Read_From_Binary(const char *file_name, Student *p_destination)
{
FILE *p_file = fopen(file_name, "rb");
if (!p_file)
{
perror("Error opening file. \n");
exit(EXIT_FAILURE);
}
unsigned int number_of_students = 0;
size_t successfully_read;
successfully_read = fread(&number_of_students, sizeof(number_of_students), 1, p_file);
if (successfully_read != 1)
{
printf("Error reading the number of students. \n");
exit(EXIT_FAILURE);
}
unsigned int width = 0;
for (unsigned int index = 0; index < number_of_students; ++index)
{
successfully_read = fread(&width, sizeof(width), 1, p_file);
if (successfully_read != 1)
{
printf("Error reading from the file. \n");
exit(EXIT_FAILURE);
}
p_destination[index].last_name = (char*)malloc(width);
if (!p_destination[index].last_name)
{
printf("Could not allocate memory. \n");
exit(EXIT_FAILURE);
}
successfully_read = fread(p_destination[index].last_name, width, 1, p_file);
if (successfully_read != 1)
{
printf("Error reading from the file. \n");
exit(EXIT_FAILURE);
}
successfully_read = fread(&width, sizeof(width), 1, p_file);
if (successfully_read != 1)
{
printf("Error reading from the file. \n");
exit(EXIT_FAILURE);
}
p_destination[index].first_name = (char*)malloc(width);
if (!p_destination[index].first_name)
{
printf("Could not allocate memory. \n");
exit(EXIT_FAILURE);
}
successfully_read = fread(p_destination[index].first_name, width, 1, p_file);
if (successfully_read != 1)
{
printf("Error reading from the file. \n");
exit(EXIT_FAILURE);
}
successfully_read = fread(&p_destination[index].grade, sizeof(float), 1, p_file);
if (successfully_read != 1)
{
printf("Error reading from the file. \n");
exit(EXIT_FAILURE);
}
}
fclose(p_file);
}
I did a similar job in a recent project.
I implemented a binary file format on my own, and it's structure is
MAGIC
number of records
record 1
(int) length of this record
data
record 2
(int) length of this record
data
So you can pit an extra 4 bytes (or an integer) indicating the length of what to read, and read according to that number.
Advantages of this implementation are:
You don't need another buffer to read first, which may add an extra limitation on lengths of records.
When the content format changes, you don't have to worry about reading lengths.
No single character needs to be used as "terminator" because the length is pre-determined.
You need to know the format of the file. I assume the following:
the file starts with a four-byte integer that holds the number of students in the file.
The data about each student is in the order First name, Last name, grade.
The strings first and last name are terminated with a null byte.
the float is a 4 byte float.
Following the 4 byte float follows the next student (there is no record demarcation).
Now you can read the data. The only thing is how to determine the length of the strings as you have to allocate memory for them. There are two ways:
use a buffer of reasonable size (say buf[256]) and read character by character until you see the null character (you may want to skip characters that would let the buffer overflow, so another part of the file format specification is that strings cannot be longer than 255). After reading and terminating the buffer with \0 call strlen and then allocate the string with malloc, or
remember the current position, read character by character, counting them until you see the \0, allocate the memory, seek backwards and read the string.