As part of a college assignment, I'm trying to do a simple C app, using Win32 for GUI programming and writing my own dynamic linked list for storing data. Since i could use it for other things later, I'm trying to write a generic list, with "built in" functions for reading and writing data to a file. Now here's my problem
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct tagA{
int t_int;
float t_float;
char t_char;
char t_vchar[30];
} A;
typedef struct tagB{
void *data;
struct tagB *prox;
} B;
int main(){
A dA = {1, 1.5, 'a', "teste123"};
B dB = {&dA, NULL};
dB.data = &dA;
B dB2 = {0};
FILE *fp;
fp = fopen("Data.txt", "w");
size_t dSize = sizeof(dA);
printf("Struct size: %d", dSize);
if(fp == NULL){
printf("nope");
}else{
fwrite(&dB.data, dSize, 1, fp);
}
fclose(fp);
fp = fopen("Data.txt", "r");
dB2.data = malloc(dSize);
fread(&dB2.data, dSize, 1, fp);
printf("\n\n%s", ((A*)dB2.data)->t_vchar);
}
This is the code I'm trying to work out.
The writing works just fine, and I just have to make it to a separate function that receives the pointer to the data struct and its size.
But the reading is off... Once read and printed to the console, the t_int shows a really large number, the t_float has nothing, and so the char and string...
Also, I know its not the best written, most efficient and safe code, but it's just a prototype, something that came into my mind...
Your problem is you are writing the address of &dB.data with fwrite instead of dB.data itself (it is already a pointer). For example:
fwrite(dB.data, dSize, 1, fp);
will resolve your problem (with the like corresponding change to fread).
void *data;
It's not useful to declare data as void*. Declare it as A *data; instead.
fwrite(&dB.data, dSize, 1, fp);
...
fread(&dB2.data, dSize, 1, fp);
dB2.data is a pointer, just use dB2.data. See example below. For better readability you can declare ptr_data instead of data
typedef struct tagA {
int t_int;
float t_float;
char t_char;
char t_vchar[30];
} A;
typedef struct tagB {
A *data;
struct tagB *prox;
} B;
int main() {
A dA = { 1, 1.5, 'a', "teste123" };
B dB = { 0 };
dB.data = &dA;
B dB2 = { 0 };
FILE *fp;
fp = fopen("Data.txt", "w");
size_t dSize = sizeof(dA);
printf("Struct size: %d", dSize);
if(fp == NULL) {
printf("nope");
}
else {
fwrite(dB.data, dSize, 1, fp);
}
fclose(fp);
fp = fopen("Data.txt", "r");
dB2.data = malloc(dSize);
fread(dB2.data, dSize, 1, fp);
printf("\n\n%s\n", dB2.data->t_vchar);
return 0;
}
Your error is at fwrite(), fread(). The first param of them is the pointer which points at the real data you want to write/read.
Since you want to read/write a struct A, the pointer must actually point at struct A, not struct A*.
Just replace
fwrite(&dB.data, dSize, 1, fp);
fread(&dB2.data, dSize, 1, fp);
with
fwrite(dB.data, dSize, 1, fp);
fread(dB2.data, dSize, 1, fp);
Related
Hi I have the following structure:
struct points{
int round[11];
int sum;
};
struct student{
char studid[7];
char *s_name;
char *f_name;
struct points p_points;
};
I am creating an array of structures, each representing an individual student. When I exit my program I will save that array to a file using the following function:
int save_file(struct student *array, int size, const char *filename){
struct student *object=malloc(size*sizeof(struct student));
for(int i=0;i<size;i++){
object[i].f_name=malloc(strlen(array[0].etunimi)+1);
object[i].s_name=malloc(strlen(array[0].sukunimi+1));
strcpy(object[i].f_name,array[0].etunimi);
strcpy(object[i].s_name,array[0].sukunimi);
strcpy(object[i].studid,array[0].opnro);
object[i].points=array[0].points;
}
FILE * file= fopen(filename, "wb");
if (file != NULL) {
fwrite(object, size*sizeof(struct student), 1, file);
fclose(file);
}
for(int x=0;x<size;x++){
free(object[x].etunimi);
free(object[x].sukunimi);
}
free(object);
return 1;
}
When I want to modify the record and load the file I am facing a problem. I don't know how to allocate memory for object[i].f_name and object[i].s_name and I don't know the size of the array in the file. My function looks like this now:
int read_file(const char *filename){
struct student *object2=malloc(sizeof(struct student));
FILE * file= fopen("output", "rb");
if (file != NULL) {
fread(object2, sizeof(struct student), 1, file);
fclose(file);
}
print_situation(object2,1);
return 1;
}
How can I check the size of the array in the file and get the lengths of f_name and s_name from the file in order to allocate the memory properly?
First things first - my header (.h) file looks like this:
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
typedef struct riff_list {
char id[4];
uint32_t cksize;
char subid[4];
uint8_t *buf;
} list_t;
void write_u32_le(uint32_t n, FILE *f)
{
uint8_t i, buf[4];
for (i = 0; i < 4; i++)
{
buf[i] = n & 0xFF;
n >>= 8;
}
fwrite(buf, 1, 4, f);
}
void init_list_chunk(list_t list, char *cktype)
{
memcpy(list.id, "LIST", 4);
list.cksize = 0;
memcpy(list.subid, cktype, 4);
}
void write_list_chunk(list_t list, FILE *f)
{
fwrite(list.id, 1, 4, f);
write_u32_le(4 + list.cksize, f);
fwrite(list.subid, 1, 4, f);
fwrite(list.buf, 1, list.cksize, f);
}
Now, the problem is with a basic test program trying to write something to a file. This comes out as expected:
int main()
{
FILE *f;
list_t list;
memcpy(list.id, "LIST", 4);
list.cksize = 0;
memcpy(list.subid, "TEST", 4);
f = fopen("C:\\listtest.bin", "wb");
fwrite(list.id, 1, 4, f);
write_u32_le(4+list.cksize, f);
fwrite(list.subid, 1, 4, f);
list.buf = malloc(4);
fwrite(list.buf, 1, 4, f);
free(list.buf);
fclose(f);
}
While this just produces a 4096-byte file with junk, with no recognizable parts of what is expected (not even "LIST"):
int main()
{
FILE *f;
list_t list;
init_list_chunk(list, "TEST");
list.buf = malloc(4);
list.cksize += 4;
f = fopen("C:\\listtest.bin", "wb");
write_list_chunk(list, f);
free(list.buf);
fclose(f);
}
Why is this? Why does the latter approach not work as expected?
The expected output should be something like:
LIST
ssss
TEST
xxxx
Where "ssss" is the size and "xxxx" is any random data (4 bytes).
I have seen approaches that instead passes structs as pointers to them (&my_struct_var) and accesses the members in a function by deferencing them as my_struct_var->member, but can I pass the struct as it is?
Calling a function with out = func(in); means that if the function modifies the contents of in those modifications will only be visible within the function. When the function returns the calling function will still have the same contents in the variable in. Doing a call by value could be described as the called function gets its own copy of the variable.
You have two options to solve your problem:
1) As you already suggested yourself, your function init_list_chunk could take a pointer to your structure. By then modifying the structure the pointer points to those modifications will be usable also for the calling function.
2) Instead of returning void your init_list_chunk could return the modified structure. Something like: list = init_list_chunk(list, "TEST"); or even list = init_list_chunk("TEST"); as there is no useful input information within list at the time of the function call.
I have to write a function that will read an array of structures of type Product with data from a binary file.This file contains the number of products - nr and a number of articles of type Product. What's wrong? Thank you in advance!
#define SIZE 30
typedef struc{
int id;
char[SIZE] name;
float price;
}Product;
void create(Product *p, FILE *fptr)
{
p = malloc(sizeof(Product));
fread(p, 1, sizeof(Product), fptr);
}
int main(int argc, char* argv[])
{
FILE *fptr = fopen(argv[1],"rb");
Product *p;
create(p, fptr);
return 0;
}
You have to modify it to something like this:
#include <stdio.h>
#include <stdlib.h>
#define SIZE 30
typedef struct{
int id;
char name[SIZE];
float price;
}Product;
int readproducts(Product *p, FILE *fptr, int nr)
{
if(nr != fread(p, sizeof(Product), nr, fptr))
return -1;
return 0;
}
int main(int argc, char* argv[])
{
FILE *fptr = fopen(argv[1],"rb");
int nr = 0;
if(NULL == fptr) return -1;
// First read number of products from file
// Assuming this number is written as 4 byte integer - at the start of file
if(fread(&nr, 4, 1, fptr) != 1)
return -1;
// Now, read the products
Product *p = malloc(nr * sizeof(Product));
if(-1 == readproducts(p, fptr, nr))
return -1;
fclose(fptr);
return 0;
}
The way you had used malloc in your function was wrong, see here why.
PS. That said, binary writing/reading might not be portable across different computers.
Im having some trouble with writing more than one struct to the file and then close the program. The next time I open the file and print whats in there, it displays strange text.
If I only choose to print 1 struct plus the obligatory first on that says how many structs are in the file (the first in the file) it displays correct.But as soon as there is more than two http://imgur.com/ANTCSAZ.
I have been looking for a couple hours for the solution but cant find it, would appreciate all the help I can get! :)
#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
//#include "allafunktioner.h"
struct vinnare{
int ar;
char namn[20];
};
struct vinnare *inlasningTillFil(struct vinnare *vinnare, int antalvinnareinlasning);
int meny();
int vinnarear(int ar, char namnlista, int vinnare);
void artistnamn(int ar, char namnlista, int vinnare);
void skrivutalla(int ar, int namnlista, int vinnare);
main(){
int a=1, val, antalvinnareinlasning,test=0;
struct vinnare *vinnare;
FILE *file;
file = fopen("F:\\Uppgifter", "rb");
if (file == NULL){
vinnare = NULL;
printf("Ange antal vinnare:");
scanf("%d", &antalvinnareinlasning);
vinnare = (struct vinnare *)malloc(antalvinnareinlasning*sizeof(struct vinnare));
vinnare = inlasningTillFil(vinnare, antalvinnareinlasning);
}
else{
fread(&antalvinnareinlasning, sizeof(int), 1, file);
printf("%d", antalvinnareinlasning);
vinnare =(struct vinnare *)malloc(antalvinnareinlasning*sizeof(struct vinnare));
for (a = 1; a < (antalvinnareinlasning + 1); a++){
fread(&vinnare[a].ar, sizeof(int), 1, file);
fread(&vinnare[a].namn, sizeof(char)*20, 1, file);
printf("%d", vinnare[a].ar);
printf("%s", vinnare[a].namn);
}
}
fflush(stdin);
getchar();
}
struct vinnare *inlasningTillFil(struct vinnare *vinnare, int antalvinnareinlasning){
int a, temp;
FILE *file;
file = fopen("F:\\Uppgifter", "wb");
vinnare[0].ar = antalvinnareinlasning;
fwrite(&vinnare[0], sizeof(struct vinnare),1, file);
for (a = 1; a < (antalvinnareinlasning + 1); a++){
printf("Ange vilket år du vill mata in: ");
scanf("%d", &temp);
vinnare[a].ar = temp;
fflush(stdin);
printf("Ange vinnaren för det året:");
fgets(vinnare[a].namn, 20, stdin);
fflush(stdin);
fwrite(&vinnare[a], sizeof(struct vinnare), 1, file);
}
}
For the first block of struct data, you wrote:
fwrite(&vinnare[0], sizeof(struct vinnare),1, file);
i.e. sizeof(struct vinnare) bytes of data
but you are reading only int
fread(&antalvinnareinlasning, sizeof(int), 1, file);
i.e. 4 bytes of data
therefore the file pointer is advanced only by 4 bytes and points to 20 bytes of garbage data, which is then followed by next blocks of data that you wrote using for in function inlasningTillFil.
Here:
vinnare = inlasningTillFil(vinnare, antalvinnareinlasning);
You are assigning the value of a function that doesn't returns anything
I seriously doubt this for loop. You are starting from 1, means second item and ending with number_of_allocations + 1, clearly out of your allocations.
for (a = 1; a < (antalvinnareinlasning + 1); a++){
I wrote a program in C to open bitmap image and save the dimension the image. i am having some problem to write the fread() function. please tell me what should be the correct format for the function in the code that i have written.
here i have used pointer array because i have to open multiple bitmap images.
#include<conio.h>
#include<stdio.h>
#include<stdlib.h>
void fskip(FILE *fp, int num_bytes)
{
int i;
for (i=0; i<num_bytes; i++)
fgetc(fp);
}
typedef struct tagBITMAP /* The structure for a bitmap. */
{
int width;
int height;
//unsigned char *data;
} BITMAP;
int main()
{
int temp1=0;
BITMAP *bmp[50];
FILE *fp = fopen("splash.bmp","rb");
if (fp!=NULL && (fgetc(fp)=='B' && fgetc(fp)=='M')){
bmp[temp1] = (BITMAP *) malloc (sizeof(BITMAP));
fskip(fp,16);
fread(&bmp[temp1].width, sizeof(int), 1, fp);
fskip(fp,2);
fread(&bmp[temp1].height,sizeof(int), 1, fp);
fclose(fp);
}
else exit(0);
getch();
}
fread(&bmp[temp1].width, sizeof(int), 1, fp);
should be:
fread(&(bmp[temp1]->width), sizeof(int), 1, fp);
because bmp[temp1] is address of struct use -> operator instead of . Same error is in second fread().
. DOT that works with value variable called element selection by reference.
-> is used called element selection through pointer.