Structs and functions - c

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));
...

Related

how to Organize a program into header and c files

I am required to organize the following c code into header (s) and c file (s). However, im unable to do so myself.
The code is as follows:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUFFER_SIZE 256
#define PROGRAMMES_SIZE 2
#define DELIMETER ","
struct programme
{
char name[32];
char code[8];
int credits;
};
struct programme parseProgramme(char *);
struct programme createProgramme(char[], char[], int);
void printProgramme(struct programme);
void updateProgrammeName(struct programme *, char[]);
int main()
{
char buffer[BUFFER_SIZE];
struct programme programmes[PROGRAMMES_SIZE];
FILE *input = fopen("input", "r");
if (input == NULL)
exit(1);
int i;
for (i = 0; i < PROGRAMMES_SIZE; i++)
{
fgets(buffer, BUFFER_SIZE, input);
programmes[i] = parseProgramme(buffer);
}
for (i = 0; i < PROGRAMMES_SIZE; i++)
printProgramme(programmes[i]);
fclose(input);
return 0;
}
struct programme parseProgramme(char *buffer)
{
char name[32];
char code[8];
int credits;
// parse name
strcpy(name, strtok(buffer, DELIMETER));
// parse code
strcpy(code, strtok(NULL, DELIMETER));
// parse credits
credits = atoi(strtok(NULL, DELIMETER));
return createProgramme(name, code, credits);
}
struct programme createProgramme(char name[], char code[], int credits)
{
struct programme programme;
strcpy(programme.name, name);
strcpy(programme.code, code);
programme.credits = credits;
return programme;
}
void printProgramme(struct programme programme)
{
puts(programme.name);
puts(programme.code);
printf("%d\n", programme.credits);
}
void updateProgrammeName(struct programme *programme, char name[])
{
strcpy(programme->name, name);
}
Please be noted that its not required to update any of the following definitions or implementations of the code listed above, stated by my collage professor. Just to organize them accordingly, any help is apricated!.
There is no strict need to create a separate header file here, because there is no code re-use.
However, if some of the code were to be reused in other files, then it would start to make sense. So let's say we want to move some functionality to a library.
Then it would make sense to split up the functions to a separate file, and create a header file which would also be roughly representing the API.
So let's skip some code and look at main.c:
int main()
{
char buffer[BUFFER_SIZE];
struct programme programmes[PROGRAMMES_SIZE];
FILE *input = fopen("input", "r");
if (input == NULL)
exit(1);
int i;
for (i = 0; i < PROGRAMMES_SIZE; i++)
{
fgets(buffer, BUFFER_SIZE, input);
programmes[i] = parseProgramme(buffer);
}
for (i = 0; i < PROGRAMMES_SIZE; i++)
printProgramme(programmes[i]);
fclose(input);
return 0;
}
And obviously the functions would be in e.g. program.c:
struct programme parseProgramme(char *buffer)
{
char name[32];
char code[8];
int credits;
// parse name
strcpy(name, strtok(buffer, DELIMETER));
// parse code
strcpy(code, strtok(NULL, DELIMETER));
// parse credits
credits = atoi(strtok(NULL, DELIMETER));
return createProgramme(name, code, credits);
}
struct programme createProgramme(char name[], char code[], int credits)
{
struct programme programme;
strcpy(programme.name, name);
strcpy(programme.code, code);
programme.credits = credits;
return programme;
}
void printProgramme(struct programme programme)
{
puts(programme.name);
puts(programme.code);
printf("%d\n", programme.credits);
}
void updateProgrammeName(struct programme *programme, char name[])
{
strcpy(programme->name, name);
}
Now we can easily see, that PROGRAMMES_SIZE and BUFFER_SIZE are not used in the functions, and should be defined in main.c.
On the other hand, DELIMETER is only used in the functions, so it should be defined at the top in program.c.
We can move the struct and function definitions to program.h. It's good practice to prevent recursive inclusion, we could use some simple ifndef for that:
#ifndef PROGRAM_H
#define PROGRAM_H
struct programme
{
char name[32];
char code[8];
int credits;
};
struct programme parseProgramme(char *);
struct programme createProgramme(char[], char[], int);
void printProgramme(struct programme);
void updateProgrammeName(struct programme *, char[]);
#endif /* PROGRAM_H */
Finally, you should look which standard library functions are used in either .c file and add the necessary #include at the top of main.c and program.c. For example, main.c uses fgets and program.c uses puts. So both should #include <stdio.h>.
I'll leave the rest for you as an exercise.

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;
}

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;
}

Structure as a parameter of extern function 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.

How to link main function with header file and create it's dll file?

I am very beginner to work with dll and linking various file.
I just know write main() function and all other in same .c file and run it.
I have one program which works for pattern matching. It takes the string and check whether it exist in entire text string or not. like
Text string: my name is john
string to be matched: name
Answer: Yes
main function is like this:
int main(int argc, const char *argv[])
{
char target[200];
char *ch = target;
char pattern[20];
int i,k,count,l;
printf("\nEnter the string: \n");
fgets(target,100,stdin);
printf("Enter the string to be matched: \n");
fgets(pattern,20,stdin);
l=strlen(pattern);
i = kmp(target, strlen(target)-1, pattern, strlen(pattern)-1);
//printf("I is : %d\n",i);
if (i == -1)
puts("False");
else
puts("True");
getch();
return 0;
}
Which calls function kmp() and get result back. We can also print the result in kmp() function. kmp() function is as follow:
int kmp(char *target, int tsize, char *pattern, int psize)
{
int i;
int *pi = compute_prefix_function(pattern, psize);
int k = -1;
if (!pi)
return -1;
for (i = 0; i < tsize; i++) {
while (k > -1 && pattern[k+1] != target[i])
k = pi[k];
if (target[i] == pattern[k+1])
k++;
if (k == psize - 1) {
free(pi);
return i-k;
}
}
free(pi);
return -1;
}
In kmp we call compute_prefix_function(pattern, psize); which is as below:
int *compute_prefix_function(char *pattern, int psize)
{
int k = -1;
int i = 1;
int *pi = malloc(sizeof(int)*psize);
if (!pi)
return NULL;
pi[0] = k;
for (i = 1; i < psize; i++) {
while (k > -1 && pattern[k+1] != pattern[i])
k = pi[k];
if (pattern[i] == pattern[k+1])
k++;
pi[i] = k;
}
return pi;
}
Header files need to be called:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
What I want to do is:
Creating an implementations in a dll/shared library format. essentially, the dll should have a function extension which take a string and return a bool saying if the string exists or not.
For that which function I need to put in .c file and header file and how to create .dll file for this?
I am using windows 7, VS 2010 and C programming.
Please explain me step by step.
I'll say more about the DLL further down, but for a start, here is the layout of the source files you'll need to do that.
You'll need three files:
main.c
kmp.h
kmp.c.
Code structure:
File main.c
#include <stdio.h>
#include "kmp.h" // this will make the kmp() function known to main()
int main(int argc, const char *argv[])
{
char target[200];
... same code as you aready have
}
File kmp.h
// prototype to make kmp() function known to external programs (via #include)
extern int kmp(char *target, int tsize, char *pattern, int psize);
File kmp.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
// declare kmp prototype as DLL-export
_declspec(dllexport) int kmp(char *target, int tsize, char *pattern, int psize);
// prototype for internal helper function
static int *compute_prefix_function(char *pattern, int psize);
//
// implementation of kmp() function (and helper)
//
int kmp(char *target, int tsize, char *pattern, int psize)
{
int i;
... same program code as you aready have
}
int *compute_prefix_function(char *pattern, int psize)
{
int k = -1;
... same program code as you aready have
}
.
Now, for a first step, you can make these three files, and compile them in your current project (i.e. split your current project source into those three files, just leave out the line in kmp where it says __declspec(dllexport) and compile as before (non-DLL) to see if all works).
.
You will then need to create a DLL project for kmp.h and kmp.c (that will compile a KMP.DLL and KMP.LIB). Then you create a normal program (like your current sample) with main.c and need to link it with KMP.LIB / KMP.DLL
The following may be a bit fuzzy, because I only have VS2005 here, but the steps to create the DLL project should be essentially somewhat like this:
new project: Type Win32 / Win32-Project
name KMP
in the wizard choose Type DLL and check "Empty Project"
add your kmp.c and kmp.h files
In your main project (the one with the main.c program), you can then do
File Menu > Add > Existing Project > KMP.vcproj
This will automatically build and link the DLL from with your main.c program project.

Resources