I have 2 shared libraries(let them be 1.so,2.so) and program(a.out).
2.so is linked to 1.so and a.out - it has some functions that is used in 1 and a.
The code of 2.so is
FILE *in;
char filename[128];
int func_printer(int a)
{
if(strlen(filename)==0)
{
sprintf(filename,"%ld",time(NULL);
}
if((in=fopen(filename,"a"))==NULL)return;
fprintf(in,"%i",a);
fclose(in);
}
a.out has next
extern int func_printer(int);
extern void some_action();
int main()
{
some_action();
func_printer(2);
return 0;
}
And finally 1.so has method some_action
extern int func_printer(int);
void some_action()
{
func_printer(1);
printf("hello world");
return;
}
So when a.out starts, it call's 1.so(some_action()) and it call's 2.so(func_printer). It create file with name of timestamp(t1), write in it some info. After that 1.so calls 2.so(func_printer) and it creates another file's with timestamp.
Is it possible in this situation that some_action write always to t1, but when program starts again it should write to another file. All in all simply when program starts all libraries should know the filename where to write(without hard predifining the file name like char *filename="somefile.txt";)?
It seems like the only thing that writes to a file is 2.so. Just expose a setter:
char filename[128];
void set_filename(char * path) {
strncpy(filename, sizeof(filename), path);
filename[sizeof(filename) - 1] = '\0';
}
int func_printer(int a)
{
FILE *in;
if(strlen(filename)==0) {
sprintf(filename,"%ld",time(NULL);
}
if((in=fopen(filename,"a"))==NULL)return;
fprintf(in,"%i",a);
fclose(in);
}
Related
I am trying to find the file(say marks.txt) in the particular path passed as argument to a function. Is it possible to give the filename and path as arguments to a function which checks if the file exists and prints out the path?
The below function only takes path as argument.
int fileexists(const char *path){
File *ptr = fopen(path, "r");
if (fptr == NULL)
return 0;
fclose(fptr);
return 1;
}
The required function prototype :
int fileexists(const char *path, const char *filename)
There are two parts to this question, and the right answers to them depend on what you're trying to do.
Concatenate a directory name and a file name to form a full path name.
Determine whether a file (referred to by a full path name) exists or not.
Concatenating a directory name and a file name is straightforward. Your friendsstrcpy and strcat will do most of the work. There are a few minor details to be careful of: (a) You'll need a big enough buffer for the full pathname, and you'll need to decide whether to use a fixed-size array (perhaps of size MAX_PATH), or a malloc'ed buffer; (b) you might need to insert an explicit '/' character (and it usually doesn't hurt to stick one in even if the directory string already ends in one); (c) under Windows you might want to use '\\' instead of '/'.
And then determining whether a file named by a full pathname exists is already well answered over at What's the best way to check if a file exists in C?. The big question to ask here is, are you asking whether the file exists in preparation to doing something with the file? If so, you have a serious vulnerability if you check for the file's existence, but then before you do the other thing, something else happens to cause the file to appear or disappear. So rather than checking-and-then-doing, it's usually better to just try doing the other thing, and deal gracefully with any errors.
The function you have checks if the file can be opened, but it will fail for some files that exist but you have no rights to open. I'd use stat instead. To concatenate the path and filename you can use string functions.
The usual Unix C APIs are dismal. It takes lots of effort to do the simplest of things correctly - and even then I'm not sure that I didn't forget some Unix-ism like signal handling or some obscure error cases. I.e. stuff that's rather trivial to get right in modern C++.
I wish someone designed a modern C system API and implemented it for at least Linux, so that our suffering would end...
Usually, string concatenation requires some higher level API to be done while maintaining a modicum of sanity. Thus, the example below uses a strbuilder class to build the string. This makes things vaguely readable and avoids most common mistakes.
#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
struct strbuilder {
unsigned items, item;
size_t length, *lengths;
char *str, *dst;
};
bool strbuilder_pass(struct strbuilder *builder, int *rc);
void strcat_str(struct strbuilder *builder, const char *src);
void strcat_c_ifnone(struct strbuilder *builder, char c);
bool strbuilder_is_freed(const struct strbuilder *builder);
int fileExists(const char *path, const char *filename)
{
const char pathSep = '/';
int rc;
struct strbuilder bld = {0};
while (strbuilder_pass(&bld, &rc))
{
strcat_str(&bld, path);
strcat_c_ifnone(&bld, pathSep);
strcat_str(&bld, filename);
if (!rc)
{
struct stat statbuf;
printf("path = %s\n", bld.str);
rc = stat(bld.str, &statbuf);
}
}
assert(strbuilder_is_freed(&bld));
return rc;
}
int main()
{
int rc = fileExists("/", "dev");
assert(rc == 0);
return 0;
}
The string building is controlled by a strbuilder_pass function, which advances the string builder's state through five passes of operation:
Determine the number of items whose width has to be stored (avoids the need to call strlen twice).
Prepare the length storage vector. Determine the length of the buffer needed.
Prepare the output string buffer. Concatenate the elements into the buffer.
Use the output string buffer.
Free the output string buffer.
This API is not particularly special, but fits this use case. Some other ad-hoc approach would work too, but this is IMHO a bit more elegant.
void strbuilder_free(struct strbuilder *builder)
{
free(builder->lengths);
free(builder->str);
memset(builder, 0, sizeof(*builder));
}
bool strbuilder_pass(struct strbuilder *builder, int *rc)
{
if (!builder->length) {// start of pass 1
builder->length = 1; /*term*/
*rc = EAGAIN;
return true;
}
else if (!builder->lengths) // end of pass 1
{
builder->lengths = malloc(sizeof(*builder->lengths) * builder->items);
if (builder->lengths)
return true;
*rc = ENOMEM;
}
else if (!builder->str) // end of pass 2
{
builder->dst = (builder->str = malloc(builder->length));
builder->item = 0;
builder->length = 0;
if (builder->dst) {
*builder->dst = '\0';
return true;
}
*rc = ENOMEM;
}
else if (builder->dst) // end of pass 3
{
while (*builder->dst) { // include optional content
builder->dst++; // skip
builder->length++;
}
builder->dst = NULL;
*rc = 0;
return true;
}
else if (!builder->dst) // end of pass 4 (if any)
{}
else {
*rc = EINVAL;
}
strbuilder_free(builder);
return false;
}
void strcat_str(struct strbuilder *builder, const char *src)
{
if (!src)
return;
if (!builder->lengths) // pass 1
builder->items ++;
else if (!builder->str) // pass 2
{
size_t len = strlen(src);
builder->lengths[builder->item++] = len;
builder->length += len;
}
else if (builder->dst) // pass 3
{
size_t len = builder->lengths[builder->item++];
if (*builder->dst && (!len || *builder->dst != *src))
{
builder->dst++;
builder->length++;
}
memcpy(builder->dst, src, len);
builder->dst += len;
builder->length += len;
*builder->dst = '\0';
}
}
void strcat_c_ifnone(struct strbuilder *builder, char c)
{
if (!builder->lengths) {} // pass 1
else if (!builder->str) // pass 2
{
if (c) builder->length ++;
}
else if (builder->dst) // pass 3
{
if (!builder->length || builder->dst[-1] != c)
*(builder->dst) = c;
}
}
bool strbuilder_is_freed(const struct strbuilder *builder)
{
return !builder || (!builder->lengths && !builder->str);
}
You probably want something like this (no error checking for brevity):
...
#include <string.h> // for str* functions
#include <unistd.h> // for access
#include <stdlib.h> // for malloc
...
int fileexists(const char *path, const char *filename)
{
char *name= malloc(strlen(path) + strlen(filename) + 1);
strcpy(name, path);
strcat(name, filename);
int retval = access(name, F_OK) == 0;
free(name);
return retval;
}
Call like this:
if (fileexists("/some/path/", "somefilename.txt")) ...
Im trying to write code so that it will open a file (worker and benefits) and then display them when asked at the start. I can do this but I would like to use functions. When I run my program it ends as soon as it starts. How do I set up functions so that they will run.
Ive tried renaming the functions to no sucess. Ive also found no help throught Youtube tutorials.
#include <stdio.h>
#include <stdlib.h>
int ans;
char Benefits[150];
char Worker[150];
int readfile();
int end();
int welcome();
int main()
{
int welcome()
{
puts("Hi, Welcome to whatever this is!!\n");
}
int readfile()
{
FILE*fpointer;
fpointer = fopen("Worker.txt","r");
char Worker[150];
while(!feof(fpointer))
{
fgets(Worker, 150, fpointer);
}
FILE*fpointer1;
fpointer = fopen("Benefits.txt","r");
char Benefits[150];
while(!feof(fpointer))
{
fgets(Benefits, 150, fpointer1);
}
fclose(fpointer);
}
int menu(char Benefits)
{
{
printf("1 - For option 1\n");
printf("2 - For option 2\n");
printf("3 - For option 3\n");
printf("4 - For option 4\n");
printf("5 - exit\n");
scanf("%1d", &ans);
}
{
if (ans==1)
puts(Benefits);
if (ans==2)
puts(Worker);
if (ans==3)
puts("This is option3");
if (ans==4)
puts("This is option4");
}
}
return 0;
}
I expect the output to print either of the files or exit. As of now It skips functions and ends the program.
The functions should be outside the main function. In your main function you call the functions as required.
int main()
{
welcome();
readfile();
etc.
return 0;
}
To be really useful functions can take parameters. If you define readfile like this you declare a parameter called filename that contains the name of the file. You can
use this inside your function instead of writing the exact name of the file.
int readfile (char *filename)
{
...
fpointer = fopen(filename,"r");
...
}
Now in main you can use
int main()
{
welcome();
readfile("Workers.txt");
...
}
This is what makes functions useful. You can now reuse the function for another file
with a different name. This isn't a solution for you but I hope it helps, even if just with your understanding.
I'm having an aggravating issue that I can't understand,
void file_count(FILE* stream,int* const num)
{
int temp;
while((fscanf(stream,"%d",&temp))!=EOF)
{
(*num)++;
}
}
With this piece of program, I read from a file taking all the numbers inside it, and very time I take a number a counter increases so I can count how many elements are in the file.
In this file there are 6 numbers, but if I run this code the counter skyrockets to 32777...
If I compile it with gcc, there's no problem and the counter is 6 as expected. Is this a bug of clang? Is it a feature that I'm not aware of?
The file contains:
22 30 30 21 25 29
The whole code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef char* string;
typedef struct student
{
int flag;
char name[25];
char surname[25];
char dorm[25];
int* grades;
}
Student;
void check_input(const int argc,const string* const argv);
void check_file(FILE* stream);
void file_count(FILE* stream,int* const num);
void update_student(const string* const infos,Student* const student,const int grades,FILE* stream);
void print_student(FILE* stream,Student const student,const int grades);
int main(int argc, string argv[])
{
check_input(argc,argv);
FILE* one,* two;
string info[]={"David","Malan","Mather"};
Student student;
int grades;
one=fopen(argv[1],"r");
check_file(one);
file_count(one,&grades);
update_student(info,&student,grades,one);
fclose(one);
two=fopen(argv[2],"w");
check_file(two);
print_student(two,student,grades);
fclose(two);
free(student.grades);
system("cat out");
return 0;
}
void check_input(const int argc,const string* const argv)
{
if(argc!=3)
{
printf("\x1B[31mError: %s takes two arguments!\x1B[0m\n",argv[0]);
exit(EXIT_FAILURE);
}
}
void check_file(FILE* stream)
{
if(stream==NULL)
{
printf("\x1B[31mError:invalid file.\x1B[0m\n");
exit(EXIT_FAILURE);
}
}
void file_count(FILE* stream,int* const num)
{
int temp;
printf("reading file...\n");
while((fscanf(stream,"%i",&temp))!=EOF)
{
(*num)++;
}
printf("\x1B[33mthe value read were %i\x1B[0m\n",*num);
}
void update_student(const string* const infos,Student* const student,const int grades,FILE* stream)
{
rewind(stream);
student->grades=malloc(grades*sizeof(int));
strcpy(student->name,infos[0]);
strcpy(student->surname,infos[1]);
strcpy(student->dorm,infos[2]);
student->flag=0;
for(int i=0;i<grades;i++)
{
fscanf(stream,"%i",&student->grades[i]);
}
}
void print_student(FILE* stream,Student const student,const int grades)
{
printf("Writing to file..\n");
fprintf(stream,"%i %s %s %s ",student.flag,student.name,student.surname,student.dorm);
for(int i=0;i<grades;i++)
{
fprintf(stream,"%i ",student.grades[i]);
}
printf("\x1B[32mFile successfully written..\x1B[0m\n");
}
Your code is dangerous, because an incorrect file sends it into an infinite loop.
Once fscanf with %d finds an input that cannot be interpreted as an int, the function returns zero without making any progress on consuming the input. Therefore, the loop never reaches EOF.
You can fix this issue by looping only as long as the input is consumed:
while(fscanf(stream,"%d",&temp) == 1) {
...
}
Now you need a way to communicate to the caller if the count is correct or not. You can do that by returning one if EOF is reached, and zero otherwise:
int file_count(FILE* stream,int* const num) {
int temp, last;
while((last = fscanf(stream,"%d",&temp)) == 1) {
(*num)++;
}
return last == EOF;
}
I tried with fscaf==1 it still reaches 32777
This happens because you are not initializing grades in the caller. You should define it as int grades = 0, or add *num = 0 before entering the loop in file_count.
The current ISO C standard defines the return value of fscanf() as
The fscanf function returns the value of the macro EOF if an input failure occurs before the first conversion (if any) has completed. Otherwise, the function returns the number of input items assigned, which can be fewer than provided for, or even zero, in the event of an early matching failure.
Verbatim quote from the ISO-C Standard (no public link available, the standard is not public AFAIK)
If there is data to read, but that data cannot be successfully matched, this function will return 0. It will only return EOF (which is typically -1) if there is no data to read because the stream you are reading from is in EOF state or had another read error.
So if you had a file like that:
23 a 57
The loop will never terminate. On first scan it will read 23 and return 1 (one value matched). On next call it will return 0, as a cannot be matched to an integer. Yet, it also won't move the file pointer beyond a. So on next call, it tries to match a again and it will fail again. This continues endlessly.
I will go ahead and say this is a homework assignment for an intro to Linux class. I would not be posting it without extensive attempts on my own, and seeing as I am a distance student this semester, I cannot make it to campus for tutoring. I need some help finding out what the issue is.
Essentially the assignment asks us to make a program that serves the same basic function as the pwd command in POSIX, to show the absolute path for the current directory. We are to use three functions along with main. We are not to use the getcwd command as well. I'll list them and their purpose
inum_to_filename: Accepts three arguments (inode number to translate, a pointer to a buffer where the name is written, and the size of the buffer). Returns nothing. It is to:
Open the current directory,
Read the first directory entry,
If the inode of the current directory matches the one passed in, copy name to buffer and return.
Otherwise read the next directory entry and repeat the previous step.
filename_to_inum: Accepts one argument (a char * representing the filename). It returns the corresponding inode number. It is to:
Read the information from the files inode into a structure in memory.
If there is any problem, display the appropriate error.
Return the inode number from the structure.
display_path: Accepts one argument (inode from the current working directory). It returns nothing. It is to:
Create an array of characters to use as a buffer for the name of the directory.
Get the inode for the parent directory using filename_to_inode.
If the parent inode is equal to the current inode, we have reached root and can return.
Otherwise, change to the parent directory and use inum_to_filename to find the name for the inode that was passed into the function. Use the buffer from step 1 to store it.
Recursively call display_path to display the absolute path.
Here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
while (counter != 1) {
if (inode_arg == dirent_ptr->d_ino) {
strcat(pathBuffer, "/");
strcat(pathBuffer, dirent_ptr->d_name);
counter = counter + 1;
return;
} else {
dirent_ptr = readdir(dir_ptr);
}
}
closedir(dir_ptr);
}
int filename_to_inum (char *src) {
int res = 0;
struct stat info;
int result = stat(src, &info);
if (result != 0) {
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
} else {
res = info.st_ino;
}
return res;
}
void display_path (int ino_src) {
int bufSize = 4096;
char pathBuffer[bufSize];
int ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt) {
//print for test
inum_to_filename(ino_src, pathBuffer, bufSize);
printf("%s", pathBuffer);
return;
} else {
//print for test
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
}
int main (int argc, char *argv[]) {
int c_ino = filename_to_inum(".");
display_path(c_ino);
printf("\n");
}
As of right now it is displaying "/./MyName" with MyName being my personal named directory on the server. It is the directory I am running the program from. When using pwd I return "/home/MyName". I'm not really sure what my next step to getting the absolute path correct is.
The code is mostly set up to print one name at a time in the correct order, so the primary problem is the use of strcat() rather than strcpy(). Also, detecting when you're in the root directory at the start is important; if you don't, you can end up with /. or something similar (depending on exactly how you coordinate the printing) when the current directory is the root directory.
This version of your code has:
Squished the loop in inum_to_filename(), but also added error reporting. Remember, a process can be run in a directory which it does not have permission to get to (it requires a setuid program, usually — although permissions could be changed after the program is launched). In that case, it may fail to open .. (or .).
Lost variable count; it wasn't serving a useful purpose. Using the assign-and-test idiom allows the code to contain a single call to readdir().
Use strcpy() instead of strcat().
Use type ino_t to store inode numbers. Use size_t for sizes.
Reduce number of intermediate variables in filename_to_inum().
Note that the code in the if (ino_src == ino_prnt) statement body is for the root directory; in the absence of the testing print, it would do nothing.
Note that the printing in the else part is a major part of the operations, not just test printing.
Error check chdir("..");
Detect root in main().
Observe that this code is not directly suitable for rewriting into a function because it changes the process's current directory to / when it succeeds.
Revised code:
#include <assert.h>
#include <dirent.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
static void inum_to_filename(ino_t inode_arg, char *pathBuffer, size_t size_arg)
{
assert(size_arg > 0);
DIR *dir_ptr = opendir(".");
if (dir_ptr == 0)
{
fprintf(stderr, "Failed to open directory '.' (%d: %s)\n", errno, strerror(errno));
exit(EXIT_FAILURE);
}
struct dirent *dirent_ptr;
while ((dirent_ptr = readdir(dir_ptr)) != 0)
{
if (inode_arg == dirent_ptr->d_ino)
{
if (strlen(dirent_ptr->d_name) >= size_arg)
{
fprintf(stderr, "File name %s too long (%zu vs %zu max)\n",
dirent_ptr->d_name, strlen(dirent_ptr->d_name), size_arg);
exit(EXIT_FAILURE);
}
strcpy(pathBuffer, dirent_ptr->d_name);
break;
}
}
closedir(dir_ptr);
}
static ino_t filename_to_inum(char *src)
{
struct stat info;
if (stat(src, &info) != 0)
{
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
}
return info.st_ino;
}
static void display_path(ino_t ino_src)
{
size_t bufSize = 4096;
char pathBuffer[bufSize];
ino_t ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt)
{
// print for test
inum_to_filename(ino_src, pathBuffer, bufSize);
printf("%s", "(root): /\n");
}
else
{
// print for real
if (chdir("..") != 0)
{
fprintf(stderr, "Failed to chdir to .. (%d: %s)\n",
errno, strerror(errno));
}
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("/%s", pathBuffer);
}
}
int main(void)
{
ino_t c_ino = filename_to_inum(".");
ino_t r_ino = filename_to_inum("/");
if (r_ino == c_ino)
putchar('/');
else
display_path(c_ino);
printf("\n");
}
There are undoubtedly other ways to fix this.
Caveat: this is giving me some grief when working in /Volumes/CRUZER/Sub-Directory which is a memory stick. It fails to find the inode (1, which is surprising) when scanning /Volumes, and I've not worked out why. One of my programs — a getpwd implementation — is working fine; another is having a different problem. I expect I'll get to the bottom of it all. Testing on Mac OS X 10.10.5 with GCC 5.1.0.
this is really nice assignment :).
I read and tried your code, and it is almost correct. There were two small issues which were causing the incorrect behaviour.
First issue
When display_path reaches the root folder you don't need to call inum_to_filename and print the name of the folder because you have already printed the first folder of the path in the previous iteration. This prevents your code from showing a "./" in the beginning of the path.
That is, the if condition becomes:
if (ino_src == ino_prnt) {
return;
} else {
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
Second Issue:
You're not initializing propertly the buffer where you save the name of the directory. This causes random values to be displayed. To solve this issue you can just set the initial value of the buffer to zero by using memset.
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
memset(pathBuffer, 0, size_arg);
while (counter != 1) {
...
}
closedir(dir_ptr);
}
Full code working :
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <dirent.h>
#include <sys/stat.h>
void inum_to_filename (int inode_arg, char *pathBuffer, int size_arg) {
DIR *dir_ptr = opendir(".");
struct dirent *dirent_ptr = readdir(dir_ptr);
int counter = 0;
memset(pathBuffer, 0, size_arg);
while (counter != 1) {
if (inode_arg == dirent_ptr->d_ino) {
strcat(pathBuffer, "/");
strcat(pathBuffer, dirent_ptr->d_name);
counter = counter + 1;
return;
} else {
dirent_ptr = readdir(dir_ptr);
}
}
closedir(dir_ptr);
}
int filename_to_inum (char *src) {
int res = 0;
struct stat info;
int result = stat(src, &info);
if (result != 0) {
fprintf(stderr, "Cannot stat ");
perror(src);
exit(EXIT_FAILURE);
} else {
res = info.st_ino;
}
return res;
}
/*
- Create an array of characters to use as a buffer for the name of the directory.
- Get the inode for the parent directory using filename_to_inode.
- If the parent inode is equal to the current inode, we have reached root and can return.
- Otherwise, change to the parent directory and use inum_to_filename to find the name for
the inode that was passed into the function. Use the buffer from step 1 to store it.
- Recursively call display_path to display the absolute path.
*/
void display_path (int ino_src) {
int bufSize = 4096;
char pathBuffer[bufSize];
int ino_prnt = filename_to_inum("..");
if (ino_src == ino_prnt) {
return;
} else {
chdir("..");
inum_to_filename(ino_src, pathBuffer, bufSize);
display_path(ino_prnt);
printf("%s", pathBuffer);
}
}
int main (int argc, char *argv[]) {
int c_ino = filename_to_inum(".");
display_path(c_ino);
printf("\n");
}
Output :
ubuntu#ubuntu-VirtualBox:~/dev$ vi pwd.c
ubuntu#ubuntu-VirtualBox:~/dev$ gcc pwd.c
ubuntu#ubuntu-VirtualBox:~/dev$ ./a.out
/home/ubuntu/dev
ubuntu#ubuntu-VirtualBox:~/dev$ pwd
/home/ubuntu/dev
ubuntu#ubuntu-VirtualBox:~/dev$
i'm current working on a homework assesment where i'm programming a program ment to stitch textfiles with a piece of an ascii image to create a complete image of all the pieces. The way i intended to write the code is having a while loop looking through a directory finding the parts and adding them to an array. However in my AddFile method(or when i call it to be precise) i get a coredump.. I just started working with c so i dont know if it is very obvious to some of you why i get a coredump or more complicated. Also, i originaly wrote the addFile method to use and accept int's instead of the FILE type, at that point it worked perfectly without any coredumps so i suspect (but hey i might be wrong) that it went wrong when i tried to implement it with the FILE type.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int listSize;
int listCapacity;
FILE *fileStream;
}FileList;
void addFile(FileList* list, FILE file)
{
if((*list).listSize<(*list).listCapacity)
{
(*list).fileStream[(*list).listSize]=file;
(*list).listSize+=1;
}
else
{
FILE *tempArray = calloc((*list).listSize,sizeof(FILE));
for(int i=0; i<(*list).listSize; i++)
{
tempArray[i]=(*list).fileStream[i];
}
//Do something with array...
free((*list).fileStream);
(*list).listCapacity=((*list).listCapacity)*2;
(*list).fileStream=calloc((*list).listCapacity,sizeof(FILE));
for(int i=0; i<(*list).listSize; i++)
{
(*list).fileStream[i]=tempArray[i];
}
(*list).fileStream[(*list).listSize]=file;
(*list).listSize+=1;
free(tempArray);
}
}
int main()
{
FileList intList;
intList.listSize=0;
intList.listCapacity=1;
intList.fileStream=calloc(intList.listCapacity,sizeof(int));
int fileYcoord=0;
int fileXcoord=0;
while(1)
{
char fileName [100];
int fileNameLength=sprintf(fileName,"part_%02d-%02d",fileXcoord,fileYcoord);
FILE * pFile = fopen (fileName,"r");
if(pFile!=NULL)
{
printf("- ! found file: %s - name length : %d \n",fileName,fileNameLength);
addFile(&intList,*pFile);
fclose(pFile);
fileXcoord++;
}
else
{
if(fileXcoord!=0)
{
fileYcoord+=1;
fileXcoord=0;
}
else
{
break;
}
}
}
printf("size %d , %d",fileXcoord, fileYcoord);
free(intList.fileStream);
return 0;
}
The call to addFile() is dereferencing a FILE *, producing a value of type FILE. This is wrong, this is an opaque type and should always be handled by pointers.