Structure as a parameter of extern function C - c

I have to read a text file using this structure. Also, I have to use external functions. I made the code for file reading and it works in main function.
Text file:
banana 3 orange 8 music 9- first character is a blank space*
#include <stdio.h>
#include <stdlib.h>
struct file
{
char name[30];
char size;
};
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",&f[n].name,&f[n].size);
n++;
}
}
But when I try to make this reading using another c file and extern function it's no working.. :(
This is what is written in filereading.c:
void fileReading(struct file *f[30], FILE *files)
{
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",&f[n].name,&f[n].size);
n++;
}
}
And fileReading.h:
void fileReading(struct fisier *, FILE *);
And in main.c:
#include <stdio.h>
#include <stdlib.h>
struct file
{
char name[30];
char size;
};
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
fileReading(f[30],files);
}
When I compile it, it says:
request for member 'name' in something not a structure or union
request for member 'size' in something not a structure or union|
||=== Build finished: 2 errors, 2 warnings (0 minutes, 0 seconds) ===||
Can you help me, please? Thank you!

From what I see it looks like you do not have a good understanding of pointers.
These changes should solve your problem:
void fileReading(struct file *f, FILE *files)
{
int n=0;
while (1)
{
fgetc(files);
if(feof(files)) break;
fscanf(files,"%s %c",f[n].name,&f[n].size);
//printf("%s %c",f[n].name,f[n].size);
n++;
}
}
int main()
{
int n=0;
struct file f[30];
FILE *files;
files=fopen("files.txt","r");
fileReading(f,files);
}
What you did wrong:
void fileReading(struct file *f[30], FILE *files) //here you were saying file is a **
fscanf(files,"%s %c",&f[n].name,&f[n].size); // here you need to send the a char* but you were sending a char ** as a second parameter
fileReading(f[30],files); // here you were sending the 31th element of the structure array f which by the way doesn't exist (indexing is from 0 , f[29] is the last) even though that was not what you wanted to do in the first place

The file fileReading.c doesn't know the definition of struct file. You need to move it from main.c to fileReading.h and #include "fileReading.h" in both main.c and fileReading.c.
Also, the definition and call of fileReading is incorrect. Instead of:
void fileReading(struct file *f[30], FILE *files)
You want:
void fileReading(struct file *f, FILE *files)
And you call it like this:
fileReading(f,files);
This is incorrect:
fileReading(f[30],files);
Because you're passing a single struct file instead of the array, and the single instance you're passing is one element off the end of the array (since the size is 30, valid indexes are 0-29), which can cause indefined behavior.

Related

Structures Program not working as intended (Bug)

I have been working on reading data from a file, which contains student name and age in the format:
John
12
Jane
13
Julia
18
Here's the program I wrote:
#include <stdio.h>
#include <stdlib.h>
struct record{
char name[50];
int age;
};
int main(){
FILE *fp;
fp=fopen("sample2.txt","r");
struct record a[50];
int counter=1;
int i=0;
while (!EOF){
if (counter%2!=0){
fgets(a[i].name,50,fp);
counter++;
}
if (counter%2==0){
a[i].age=getw(fp);
counter++;
i++;
}
}
return 0;
}
However, on printing a[0].name, I am not getting expected output. Can someone help?
As already pointed out in the comments, EOF is a value defined in stdio.h and does not say anything about your file descriptor. I also would recommend you to use fscanf (As long you are sure that the names in the file are all of the correct length). fscanf takes a string similar to printf, specifying the elements you are expecting and returns the number of possible matches. Also it helps you with converting your data to the correct datatypes. So the code could look like this:
#include <stdio.h>
#include <stdlib.h>
struct record
{
char name[50];
int age;
};
int main ()
{
FILE *fp;
fp = fopen ("sample2.txt", "r");
struct record a[50];
int i = 0;
while (fscanf(fp, "%s\n%d\n", (char *) a[i].name, &a[i].age) > 0) {
i++;
}
printf("%s %d\n", a[1].name, a[1].age);
return 0;
}

Writing/Reading a struct from a .txt file

I'm trying to write an array of structs to a file, then read that file into an empty array of structs and print out the variables within each struct element of the array.
my code is below, currently I just have it to try to print the first element, but nothing is printed out to the screen.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct{
char name[1024];
int price;
} game;
void main(){
FILE *filename;
filename = fopen("file.txt","w");
game library[3]; //creation of our game library
//initializing the array to be written, 3 structs inside this array should be written to the file in sizeof(game).
strcpy(library[0].name,"Minecraft");
strcpy(library[1].name,"Opium");
strcpy(library[2].name,"Devil");
library[0].price = 10;
library[1].price = 20;
library[2].price = 30;
fwrite(library,sizeof(game),3,filename);
fseek(filename,0,SEEK_SET);
game second[3];
printf("test");
fread(second,sizeof(game),3,filename);
printf("element 0 is %s $%d",second[0].name,second[0].price);
fclose(filename);
}

Copying audio file, issue with pointers

I was wondering if someone could help me with a problem that I'm having. I'm fairly sure that it's a pointer issue (read: I'm VERY much a C beginner), but I've been struggling with it for a fair while and have been unable to fix the issue (despite reading reference pages).
My code is meant to copy a .WAV file using two functions (the function prototypes are fixed). First it reads the file, then it writes a new file using the data samples from the old file. The header is defined in "R_WAV.h" as a typedef struct. The code is run from this:
#include <stdlib.h>
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <malloc.h>
#include "R_WAV.h"
//Function Declarations
int read_WAV(header_type *header, char **data, char *filename);
int write_WAV(header_type *header, char *data, char *filename);
int main()
{
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
char **data;
read_WAV(header, data, *filename);
}
//Run write_WAV
{
header_type *header;
char *filename[] = {//Various files};
char *data;
write_WAV(header, data, *filename);
}
//Run read_WAV again on new files to ensure header info is valid
{
header_type *header;
char *filename[] = {//output files from write};
char *data;
read_WAV(header, data, *filename);
}
return(0);
}
The read_WAV function I've written (abbreviated slightly) is:
int read_WAV(header_type *header, char **data, char *filename)
{
unsigned char buffer4[4];
unsigned char buffer2[2];
FILE *fp = fopen(filename, "rb"); //Open file
//Code here that checks if file successfully opened
//If file valid, find length of file
fseek(fp, 0L, SEEK_END); //Place position at EoF
int size = ftell(fp); //Read the current value
rewind(fp); //Reset position
//Code here that checks if file size < min. header size, if true exits
header = (void*)malloc(size);
//Reading RIFF string
fread(header->ChunkID, sizeof(header->ChunkID), 1, fp);
printf("\nChunkID: %s \n", (header->ChunkID));
And so on, until it comes time to read the data:
//Read DATA samples
char *buffer_data = (char*)malloc(header->Subchunk2Size);
fread(buffer_data,1,(header->Subchunk2Size),fp);
//Error checking code here for if buffer==NULL
*data = buffer_data;
fclose(fp);
return(1);
}
The write_WAV function is:
int write_WAV(header_type *header, char *data, char *filename)
{
char n_file[50]; //Init. for new filename
int data_size = header->Subchunk2Size; //Hold size of data chunk
//CODE TO ALTER FILENAME (working properly)
//Open new file (COPY_of_filename)
FILE * fp_w = fopen(n_file, "wb");
//Check to see if file was successfully created
if (fp_w==NULL)
{
printf("\nUnable to create file.");
return(-1);
}
//Write header to new file (first 44 bytes)
fwrite(header, 1, 44, fp_w);
//Write data to new file
fwrite(data, 1, data_size, fp_w);
fclose(fp_w);
return (1);
}
I'm running into two main issues:
1) I can only get the header info (first 44 bytes) to write properly in write_WAV() if I open one of the .WAV files in that function, then use fread and a buffer to store it. Does it have to be done this way? Is there another way to use the *header that will result in this data being accessible from read_WAV() without needing to reopen the old file in write_WAV()?
2) I can't get the data samples to copy over properly. Even when I read in the header as above (and check that the header info is all correct), all I get is corrupt noise upon opening the new file. I've been trying to research this, but I've gotten nowhere. Could someone help explain/point to the mistakes in what I've done, and what I need to do in order to resolve them?
I know this is really simple stuff, and I wish that my brain was working enough to figure it out by myself. Like I said, I've read reference pages, but I'm still not getting anywhere. Not really firing on all cylinders right now.
Thank you for any (much needed) assistance!
Your problem is the block scoping of data in main in a few places.
That is, when you read in the file, because of variable scoping, you lose the pointer to the data. That is, when you do the write, the pointer it uses points to random memory.
I think you also have the same problem for the header pointer [although I didn't address that issue below, the fix would be similar]. Also, note that in the two read blocks, the type used for header is inconsistent even though they do the same thing.
Here's a version annotated with the bugs:
int main()
{
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
// NOTE/BUG: this is scoped to _this_ block, so the write section below won't
// see it
// NOTE/BUG: this should be char *data and the function call should use &data
char **data;
read_pcm_wavefile(header, data, *filename);
}
//Run write_WAV
{
pcm_wavefile_header_type *header;
char *filename[] = {//Various files};
// NOTE/BUG: this scoped 'data' declaration has none of the data in the read
// sectioon above
char *data;
write_pcm_wavefile(header, data, *filename);
}
//Run read_WAV again on new files to ensure header info is valid
{
pcm_wavefile_header_type *header;
char *filename[] = {//output files from write};
char *data;
read_pcm_wavefile(header, data, *filename);
}
return(0);
}
Here's a fixed version:
int main()
{
char *data;
//Run read_WAV
{
header_type *header;
char *filename[] = {//Various files};
read_pcm_wavefile(header, &data, *filename);
}
//Run write_WAV
{
pcm_wavefile_header_type *header;
char *filename[] = {//Various files};
write_pcm_wavefile(header, data, filename[0]);
}
free(data);
//Run read_WAV again on new files to ensure header info is valid
{
pcm_wavefile_header_type *header;
char *filename[] = {//output files from write};
read_pcm_wavefile(header, &data, filename[0]);
}
return(0);
}
UPDATE:
I've fixed that up. Still unable to get a proper output, which I'm thinking is in the passing of the data/pointer from each function?
As I mentioned you need to do the same for header because main needs the pointer to be filled in by your read function. As it is, after the read call, the value of header in main is unchanged (i.e. not updated by read_WAV as you'd like).
Change:
int read_WAV(header_type *header, char **data, char *filename)
Into:
int read_WAV(header_type **header, char **data, char *filename)
And, make all corresponding adjustments in main and read_WAV
Also, apply the same scoping fix in main for header that was done for data (i.e. header should not be block scoped, but, rather function scoped).
Because, even with the prototype change to read_WAV, main would lose the header value that read_WAV tried to pass back and write_WAV would get a garbage header pointer.
After you get this working, think about the temporal duration of the block scoped variables vs function scoped variables. In other words, if you set a variable, when does the value "go out of scope" [and become invalid].
For comparison, here's a version that does not use block scoped variables:
int
main(void)
{
char *data;
header_type *header;
char *infiles[FILECOUNT] = {//Various files};
char *outfiles[FILECOUNT] = {//Various files};
for (int fidx = 0; fidx < FILECOUNT; ++fidx) {
//Run read_WAV
read_pcm_wavefile(&header, &data, infiles[fidx]);
//Run write_WAV
write_pcm_wavefile(header, data, outfiles[fidx]);
free(header);
free(data);
//Run read_WAV again on new files to ensure header info is valid
read_pcm_wavefile(&header, &data, outfiles[fidx]);
free(header);
free(data);
}
return 0;
}

fopen does not work properly and I get segmentation fault when I use fclose

I am new c-programmer.I am writing a small student database. I have an array of structs I would like to write it to file. Till now the program works fine. I can print out the data saved in the array called db (abbreviation of database). In order to be able to write data, I opened a new c-file and I wrote a method writeData() that allows me to write data using FILE-object and fopen. Here are the methods of my database located in a header-file:
//header file
#ifndef DB_OPS
#define DB_OPS
#define SIZE 3typedef int bool;
typedef int bool;
#define true 1
#define false 0
struct student{
bool statusFlag;
char lastname[20];
char firstname[20];
int mNr;
char subject[30];
char nationality[20];
};
int createDb(int s);
struct student getData(char * lastname, char * firstname, int matNr, char * courseOfStudy, char * nationality);
void insert_student(struct student * st);
void update_student(int matNr);
bool delete_student(int matNr);
void display_result(bool res, bool operation);
bool search_student(int matNr);
void display_db();
void writeData();//method to write data
void readData();
void print();
#endif
then I defined the method writeData(). Here is the code:
//a c-file
#include <stdlib.h>
#include <stdio.h>
#include "db_ops.h"
void writeData(){
//when i use fopen, the data saved in db will be damaged
FILE * fpw;
fpw=fopen("database.txt","wb");
if(fpw==NULL){
printf("the file cannot be opened");
exit(1);
}
extern struct student *db;
int i;
for(i=0;i<SIZE;i++){
printf("%s, %s, %d, %s , %s\n",
(db+i)->lastname,(db+i)->firstname,(db+i)->mNr, (db+i)->subject, (db+i)->nationality);
}
fclose(fpw);//When I use fclose(),I get segmentation fault: free(): invalid next size
}
Till now I am not able to find a solution or an explanation for that Problem. When I use fopen, I cannot find my data saved in the array db anymore. I do know if my array db which is a pointer is pointing outside of the array. The second problem consists in using fclose, which generates a segmentation fault.Any suggestions?
Here is a piece of code located in a file where I initialized the array db:
// another c-file
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "db_ops.h"
struct student * db;
struct student * ptrDb;
static int insertCounter=1;
int size=0;
int createDb(int s){
size=s;
db= (struct student *)calloc(3,sizeof(struct student *));
if(db==NULL){
printf("dynamic allocation failed");
return EXIT_FAILURE;
}
ptrDb=db;
printf("database was created\n");
}
struct student getData(char * lastname, char * firstname, int matNr, char * subject, char * nationality){
struct student st;
int i;
if(insertCounter<=size){
//get data
st.statusFlag=1;//flag to show, whether the program gets data or not
//0-byte marks the end of the string
memcpy(st.lastname,lastname,strlen(lastname)+1);
memcpy(st.firstname,firstname,strlen(firstname)+1);
st.mNr=matNr;
memcpy(st.subject, subject,strlen(subject)+1);
memcpy(st.nationality,nationality,strlen(nationality)+1);
//printf("%s,%s,%d,%s,%s\n",st.lastname,st.firstname,st.mNr,st.subject,st.nationality);
return st;
}else if(insertCounter>size){
st.statusFlag=0;
return st;
}
}
//coping input by reference
void insert_student(struct student * st){
printf("statusFlag:%d\n",st->statusFlag);
if(st->statusFlag==1){
*ptrDb=*st;
insertCounter++;
ptrDb++;
}else{
printf("##########################################################\n");
printf("no insert is possible, The maximum size has been reached\n");
printf("##########################################################\n");
}
}
Why calloc(3,sizeof(struct student *)) is for struct pointer but not struct member? It seems has to be calloc(3,sizeof(struct student)) for 3 structure members.
It is not known whether student struct pointer and contents are correct. Try to fclose the file immediately after fopen. If there is no segmentation fault, then your problem is in pointer or memory allocation.

Structs and functions

I've declared a struct like this.
typedef struct fileProperties //the struct.
{
char name[256]; /*File or directory name*/
int mode; /*protection and file type*/
int userId; /*User ID of owner*/
int groupId; /*Group ID of owner*/
int size; /*file size in bytes*/
char modifyTime[50]; /*modify time as a string*/
} FILES;
I would like to write to the properties of file1, in a function call like this.
int createStruct()
{
char structBuffer[251];
printf("\n > Please enter a file name to create a struct for.> ");
inputFix(structBuffer, STRUCT_SIZE);
strncpy(file1.name, structBuffer, sizeof(structBuffer));
printf(" > Created.");
return 0;
}
Where inputFix is:
void inputFix(char string[],int length)
{
int ch, len = 0;
fgets(string, length, stdin);
string[strcspn(string, "\r\n")] = '\0';
len = strlen(string);
if (len == length - 1)
{
while((ch = getchar()) != '\n' && ch != EOF);
}
}
STRUCT_SIZE is defined as a size of 250.
At the top of my code I have this statement.
FILES file1;
I have read a couple of tutorials from coding unit and tutorials point in relation to structs.
I can't see why i get an error:
functions.c:59:3: error: unknown type name ‘FILES’
functions.c:62:52: error: request for member ‘name’ in something not a structure or union
Is it not worth using typedef? Am I missing something in relation to using structs, if so a link to another similar question would be appreciated.
It might be relevant that this program is split into 2 files main.c functions. c & .h. Do I need to include the struct in the linker file? the main.c only calls createStruct().
I suppose that the definition of variable FILE file1 is in main.c while function createStruct in file functions.c. In such case, you need to put:
extern FILES file1;
into your hedaer file and to include it at the beginning of functions.c. Otherwise the compiler does not know that there is the variable file1 defined in another file.
So your header.h will look like this:
typedef struct fileProperties //the struct.
{
char name[256]; /*File or directory name*/
int mode; /*protection and file type*/
int userId; /*User ID of owner*/
int groupId; /*Group ID of owner*/
int size; /*file size in bytes*/
char modifyTime[50]; /*modify time as a string*/
} FILES;
extern FILES file1;
Your main.c will look like:
#include "header.h"
FILES file1;
...
and your functions.c will look like
#include "header.h"
int createStruct()
{
...
strncpy(file1.name, structBuffer, sizeof(structBuffer));
...

Resources