I am very new to coding and I'm trying to learn how a compiler thinks.
Anyway, I wrote this code for school where the code is supposed to gather random data from an input.txt file, sort by insertion and then write the sorted version to an output.txt file. Also, the data needs to be 64-bits. I have two problems with the code. One is that during the function that writes it says '.exe has triggered a break point'. I don't understand why this is.
The second is that it says I haven't defined the variable key, even though I think I did. Below is my code. Any help would be appreciated as I'm very new to this.
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
typedef uint64_t u64;
struct file_contents
{
u64 *Data;
u64 Size;
};
file_contents
ReadFile(const char* FileName)
{
file_contents Contents = {};
FILE* File = fopen(FileName, "rb");
if (File)
{
fseek(File, 0, SEEK_END);
Contents.Size = ftell(File);
fseek(File, 0, SEEK_SET);
Contents.Data = (u64*)malloc(Contents.Size);
if (Contents.Data)
{
fread(Contents.Data, 1, Contents.Size, File);
}
fclose(File);
}
return Contents;
}
u64*
SortFile(file_contents Contents)
{
u64 key;
for (int i = 1; i < 100; ++i)
{
Contents.Data[i] = key;
int j;
j = i - 1;
while (i >= 0 && Contents.Data[j] > key)
{
j = j - 1;
key = Contents.Data[j + 1];
}
}
return Contents.Data;
}
void
WriteFile(const char* FileName, file_contents Contents)
{
FILE* File = fopen(FileName, "w");
if (File)
{
if (Contents.Data)
{
fwrite(Contents.Data, 1, Contents.Size, File);
}
fclose(File);
}
}
void
CloseFile(file_contents Contents)
{
if (Contents.Data)
{
free(Contents.Data);
Contents.Data = 0;
Contents.Size = 0;
}
}
void
WriteSortedFile(const char* InputFileName, const char* OutputFileName)
{
file_contents File = ReadFile(InputFileName);
SortFile(File);
WriteFile(OutputFileName, File);
CloseFile(File);
}
int main()
{
file_contents Contents = ReadFile("input.txt");
WriteSortedFile("input.txt", "output.txt");
}
Related
I was trying to figure out the best way to keep a record of file pointers as well as individual information for each file such as a file path.
My question is, having a folder struct that holds an array of file pointers, and a file struct that holds information for files, how could merge these two concepts so that can I hold an array of file pointers, and store the file path for each of those files?
Header file for a folder struct below:
#ifndef FOLDER_STRUCT_H
#define FOLDER_STRUCT_H
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
struct folder_
{
FILE **files;
size_t current_size;
size_t capacity;
};
typedef struct folder_ folder_t;
folder_t *folder_create(size_t initial_size); //-----------------------Create a folder struct
void folder_destroy(folder_t *folder); //------------------------------Destroy a folder struct
bool folder_insert_file(folder_t *const folder, FILE *const file); //--Insert a file
FILE *folder_get_file(folder_t *const folder, size_t index); //--------Get a file by index
FILE **folder_get_file_list(folder_t *const folder); //----------------Get a list of files
int folder_get_size(folder_t *folder); //------------------------------Get folder size
int folder_get_total_capacity(folder_t *folder); //--------------------Get folder capacity
#endif
Header file for a file struct used to record file information such as a file path:
#ifndef FILE_H
#define FILE_H
#include <stdio.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
struct file_
{
FILE *file;
char *file_path;
};
typedef struct file_ file_t;
#endif
The generic approach is if you need both at the same time use another struct, and if you need either use a union probably with a tag field to tell which of the struct it holds. In your case, it sounds like you have 1 folder to n files, so your folder_file_ struct would have an array of files_. If you have more than one folder, then you need an array of folder_file_.
FILE * usually implies an open file handle. Is that really your use case? Opposed to a bunch of paths, and you only open the file as you have to operate on it. Also, why is FILE ** opposed to a FILE *?
Usually is best to let the system manage the file pointers. The file can be reopened outside your struct for example. Or just closed. The struct can get a copy of a FILE* but there is no way to know if it points to the same file as of the moment of creation.
Anyway, sometimes we may need a way to store info for a collection of files.
An EXAMPLE
typedef struct
{
char* name;
FILE* F;
} File;
typedef struct
{
size_t size;
size_t cap; // capacity
size_t inc; // increment
File** info; // data array
} Folder;
Inside File we can store sizes, dates, maybe permissions.
Folder is an array of pointers to File. cap and size are the usual, inc is the size of increment of Folder in files.
A few functions are implemented:
Folder* create(size_t capacity, size_t step);
Folder* destroy(Folder*);
int insert(File*, Folder*);
int show(Folder*, const char*);
int trim(Folder*);
int get_pos(const char* f_name, Folder*);
insert() accepts a File pointer is easy to customize File.
trim() releases all pointers not in use
show() accepts a title, for convenience
get_pos() returns the position of the provided file in the array
destroy() returns NULL to ease in invalidate the pointer in the same line
main for this test
int main(void)
{
const char tst_size = 10;
const char* scan[] = {"File_7533.tst", "File_7500.tst"};
srand(220520);
Folder* tst = create(4, 4);
show(tst, "just created");
char f_name[20] = {0};
for (int i = 0; i < tst_size; i += 1)
{
sprintf(f_name, "File_%04d.tst", 1+rand()%10000);
insert_this(f_name,NULL,tst);
}
sprintf(f_name, "%d files inserted", tst_size);
show(tst, f_name);
trim(tst);
show(tst, "after trim()");
for (int i = 0; i < sizeof(scan) / sizeof(scan[0]);i+=1)
printf( "search por \"%s\" returned %d\n", scan[i],
get_pos(scan[i], tst));
tst = destroy(tst);
return 0;
}
a Folder is created with size 4 and incrementable in groups of 4
10 files are inserted
the contents are listed
search for 2 files
the thing is destroyed
test output
just created
[0/4 files (step = 4)]
insert() size extended to 8
insert() size extended to 12
10 files inserted
[10/12 files (step = 4)]
0 File_2037.tst
1 File_5785.tst
2 File_6602.tst
3 File_7231.tst
4 File_0854.tst
5 File_7102.tst
6 File_7533.tst
7 File_6460.tst
8 File_1717.tst
9 File_1948.tst
trim() new size: 10
after trim()
[10/10 files (step = 4)]
0 File_2037.tst
1 File_5785.tst
2 File_6602.tst
3 File_7231.tst
4 File_0854.tst
5 File_7102.tst
6 File_7533.tst
7 File_6460.tst
8 File_1717.tst
9 File_1948.tst
search for "File_7533.tst" returned 6
search for "File_7500.tst" returned -1
Folder structure destroyed
stuff.h
#ifndef STUFF_H
#define STUFF_H
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct
{
char* name;
FILE* F;
} File;
typedef struct
{
size_t size;
size_t cap; // capacity
size_t inc; // increment
File** info; // data array
} Folder;
Folder* create(size_t capacity, size_t step);
Folder* destroy(Folder*);
int insert(File*, Folder*);
int show(Folder*, const char*);
int trim(Folder*);
int get_pos(const char* f_name, Folder*);
#endif
stuff.c
#include "stuff.h"
Folder* create(size_t capacity, size_t step)
{
Folder* nw = (Folder*)malloc(sizeof(Folder));
if (nw == NULL) return NULL;
nw->size = 0;
nw->cap = capacity;
nw->inc = step;
nw->info = (File**) malloc(nw->cap*sizeof(File*));
for (int i = 0; i < nw->cap; i += 1)
nw->info[i] = NULL;
return nw;
}
Folder* destroy(Folder* f)
{
if (f == NULL) return NULL;
for (int i = 0; i < f->size; i += 1)
{
free(f->info[i]->name);
free(f->info[i]);
}
free(f->info);
free(f);
printf("Folder structure destroyed\n");
return NULL;
}
int insert(File* item, Folder* f)
{
if (f == NULL) return -1;
if (item == NULL) return -2;
if (f->size >= f->cap)
{ // extends folder struct size
size_t new_size = f->cap + f->inc;
File* p = realloc((void*)f->info, new_size*sizeof(File*));
if (p == NULL) return -3; // error extending
f->info = (File**) p;
f->cap = new_size;
printf("insert() size extended to %zd\n", f->cap);
};
// ok, new File then
File* nw = (File*)malloc(sizeof(File));
nw->name = (char*)malloc(1 + strlen(item->name));
strcpy(nw->name, item->name);
nw->F = item->F;
f->info[f->size] = nw;
f->size += 1;
return (int)f->size;
}
int show(Folder* f, const char* msg)
{
if (msg != NULL) printf("%s\n", msg);
printf(
"[%zd/%zd files (step = %zd)\n", f->size, f->cap,
f->inc);
for (int i = 0; i < f->size; i += 1)
{
printf("%3d %s\n", i, f->info[i]->name);
}
printf("\n");
return 0;
}
int trim(Folder* f)
{
if (f == NULL) return -1;
if (f->cap == f->size) return 0; // nothing to do
File* p = realloc((void*)f->info, f->size * sizeof(File*));
if (p == NULL) return -3; // error extending
f->info = (File**) p;
f->cap = f->size;
printf("trim() new size: %zd\n", f->cap);
return 0;
};
int get_pos(const char* f_name, Folder* f)
{
if (f_name == NULL) return -1;
for (int i = 0; i < f->size; i += 1)
if (strcmp(f_name, f->info[i]->name) == 0) return i;
return -1;
}
Note to SO "code reviewers": I do cast all malloc() pointers, as I do not like implicit things and I like them as additional reminders of things to come.
I have an assignment that do FAT12 system. Follow the requirement, I need 2 functions to read sector and multi sector. Those functions in HAL layer. I just tested in app (main) layer below:
In HAL.c:
#define SIZE_OF_SECTOR 512
static FILE* s_pimage = NULL;
void kmc_open_img_file()
{
s_pimage = fopen("floppy.img", "rb");
if(NULL == s_pimage)
{
printf("Can not open file!");
}
}
int32_t kmc_read_sector(uint32_t index, uint8_t *buff)
{
uint32_t offset = 0;
int32_t num_of_bytes = 0;
offset = SIZE_OF_SECTOR * index;
fseek(s_pimage, SIZE_OF_SECTOR * index, SEEK_SET);
num_of_bytes = (int32_t)fread(buff, 1, SIZE_OF_SECTOR, s_pimage);
if (num_of_bytes == 0) printf("Fail");
return num_of_bytes;
}
and in main: (added header file)
int main()
{
kmc_open_img_file();
uint8_t *buff = NULL ;
int32_t a = kmc_read_sector(0, buff);
printf("%d", a);
kmc_close_img_file();
return 0;
}
Result :Fail and 0 byte.
Can anyone help me solve it without extern variable? (this is requirement too)
So I need to write a function that reads all the elements inside a bit file. The point is that I don't know how many elements there could be inside, but I know what type of elements are. So I tried to write this function:
void loadData(Parallelogram **array) {
FILE *data; long size;
//int numberOfElements = 0;
int numberOfObjects = 0;
if ((data = fopen(name, "rb"))!=NULL) {
fseek(data, 0, SEEK_END);
size = ftell(data);
fseek(data, 0, SEEK_SET);
if (size<(long)sizeof(Parallelogram)) {
printf("The file is empty try to open another file maybe");
} else {
Parallelogram *tempArray;
numberOfObjects = size/sizeof(Parallelogram);
tempArray = realloc(*array, numberOfObjects*sizeof(Parallelogram));
if (tempArray==NULL) {
printf("There was an error reallocating memory");
} else { *array = tempArray; }
fread(*array, sizeof(Parallelogram), numberOfObjects, data);
}
}
fclose(data);
}
The elements are struct objects of type Parallelogram, storing a few floats.
The commented out part was me trying another method form another question but not understanding the real mechanism. Anyways when I call the function the array is empty. What am I getting wrong?
EDIT: As requested this is the main function where I call the function loadData()
int main() {
Parallelogram *paraArray = NULL;
loadData(¶Array);
}
EDIT: complete function more or less like the OP's.
You may do something like:
void loadData(Parallelogram **array, size_t * n) {
FILE *data;
if ((data = fopen("file.bin", "rb"))!=NULL) {
Parallelogram buffer[100]; // may be malloc'd
size_t chunk_size = 100;
size_t read_size = 0;
size_t number_of_objects = 0;
Parallelogram *aux = NULL;
*array = NULL;
while ((read_size = fread(buffer, sizeof *buffer, chunk_size, data)) > 0) {
aux = realloc(*array, (number_of_objects + read_size) * sizeof *buffer);
if (aux == NULL) {
// ERROR
free(*array);
// clean, break/exit
}
*array = aux;
memcpy(*array + number_of_objects, buffer, read_size*sizeof *buffer);
number_of_objects += read_size;
}
// check file for errors (ferror()) before exit
fclose(data);
*n = number_of_objects;
}
}
I'm trying to make a Bubble Sort program in a binary file without using any arrays, instead of I will use fseek and fwrite functions.
Here is my code:
typedef struct{ //Films
short int year;
char title[LEN_NAME];
Genero_t gendre;
float rateIMDB;
}Ficha_t;
FILE * fd;
fd = fopen(name,"r+b");
Ficha_t aux1;
Ficha_t aux2;
int i,j,len;
if (fd != NULL)
{
rewind(fd);
fseek(fd, 0, SEEK_END);
len=ftell(fd);
rewind(fd);
for(i=0;i<len;i++);
{
for(j=0;j<len-1;j++)
{
fread(&aux1,sizeof(Ficha_t),1,fd);
fread(&aux2,sizeof(Ficha_t),1,fd);
if(strcmp(aux1.title,aux2.title)<0)
{
fseek(fd,-sizeof(Ficha_t)*2,SEEK_SET); //returning 2 positions for overwriting
fwrite(&aux2, sizeof(Ficha_t), 1, fd);
fwrite(&aux1, sizeof(Ficha_t), 1, fd);
fseek(fd,-sizeof(Ficha_t),SEEK_SET); //returning 1 position for checking again with the next film
}
}
}
}
It's not working since it's displaying the same 2 films, Where am I wrong? What could I do?
As mentioned in the comments, you want:
len=ftell(fd) / sizeof(Ficha_t);
to get the number of records in the file.
If you are trying to seek with offsets to the current location, use SEEK_CUR, not SEEK_SET.
I would add a bunch of printfs for ftell(fd) / sizeof(Ficha_t) so you can see that it's doing everything correctly. Also, you could be checking the return values of functions you are calling (they were probably returning errors as you tried to seek before the beginning and read/write there)
Specific code example:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void fbubble_sort(const char *filename, size_t rec_size, bool (*needSwap)(const void *, const void *)){
FILE *fp = fopen(filename, "r+b");
if(!fp){
perror("fopen, r+");
exit(EXIT_FAILURE);
}
void *first = malloc(rec_size);
void *second = malloc(rec_size);
if(!first || !second){
perror("malloc");
exit(EXIT_FAILURE);
}
enum { NO_SWAP = -1};
long last_swap_pos;
do {
rewind(fp);
long pos_1 = 0;//first record position
last_swap_pos = NO_SWAP;
if(0==fread(first, rec_size, 1, fp))
break;
while((pos_1 <= last_swap_pos || last_swap_pos == NO_SWAP) && 1==fread(second, rec_size, 1, fp) ){
if(needSwap(first, second)){
fseek(fp, pos_1, SEEK_SET);
fwrite(second, rec_size, 1, fp);
fwrite(first, rec_size, 1, fp);
fflush(fp);
last_swap_pos = pos_1;
} else {
//exchange buffer
void *temp = first;
first = second;
second = temp;
}
pos_1 += rec_size;
}
}while(last_swap_pos != NO_SWAP);
free(first);free(second);
fclose(fp);
}
#define DATA_FILE "test.dat"
#define GREATERi(type, member)\
bool greater_i(const void *first, const void *second){\
return ((type*)first)->member > ((type*)second)->member;\
}\
/**/
#define GREATERs(type, member)\
bool greater_s(const void *first, const void *second){\
return strcmp((type*)first)->member, ((type*)second)->member) > 0;\
}\
/**/
#define LESSi(type, member)\
bool less(const void *first, const void *second){\
return ((type*)first)->member < ((type*)second)->member;\
}\
/**/
typedef struct {
unsigned v;
} Record;
GREATERi(Record, v)
int main(void){
void make_test_data(void);
void print_test_data(void);
make_test_data();
print_test_data();
fbubble_sort(DATA_FILE, sizeof(Record), greater_i);
print_test_data();
}
void make_test_data(void){
FILE *fp = fopen(DATA_FILE, "wb");
if(!fp){
perror("fopen, w");
exit(EXIT_FAILURE);
}
Record rec;
for(int i = 0; i < 100; ++i){
rec.v = rand() % 100;
fwrite(&rec, sizeof(rec), 1, fp);
}
fclose(fp);
}
void print_test_data(void){
FILE *fp = fopen(DATA_FILE, "rb");
if(!fp){
perror("fopen, r");
exit(EXIT_FAILURE);
}
Record rec;
int cnt = 0;
while(fread(&rec, sizeof(rec), 1, fp)){
if(cnt)
putchar(' ');
printf("%2u", rec.v);
if(++cnt == 10){
putchar('\n');
cnt = 0;
}
}
putchar('\n');
fclose(fp);
}
I'm writing a media player in pure C and I'm using libvlc. Currently I'm developing media library and i'm writing directory walker and media file parser. It works pretty fine with various metadata like artists or albums, etc., but libvlc_media_get_duration always returns 0. I tried everything and searched everywhere, but I can't make it work. Can anybody help me?
Here is the code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <vlc/vlc.h>
#include <stdarg.h>
#include <stdbool.h>
#include <dirent.h>
#include <sys/stat.h>
void strcopy(char **dst, const char *src) {
unsigned int size = strlen(src);
*dst = (char *) realloc(*dst, sizeof(char) * (size + 1));
strncpy(*dst, src, size);
*(*dst+size) = 0;
}
void strconcat(char **dst, int n, ...) {
va_list args;
unsigned int count = 0;
// Count
va_start(args, n);
for (unsigned short i = 0; i < n; i++)
count += strlen(va_arg(args, char*));
va_end(args);
// Allocate
*dst = (char *) realloc(*dst, sizeof(char) * (count+1));
unsigned int cursor = 0;
va_start(args, n);
for(unsigned short i = 0; i < n; i++) {
char *src = va_arg(args, char*);
strncpy((*dst+cursor), src, strlen(src));
cursor += strlen(src);
*(*dst+cursor) = 0;
}
va_end(args);
}
void /* Process tags and add file to database */
__db_add_file(libvlc_instance_t *inst, const char *url, bool compute_hash) {
// Create new media
libvlc_media_t *media = libvlc_media_new_path(inst, url);
libvlc_media_parse(media);
if (libvlc_media_is_parsed(media)) {
printf("%s\n", url);
printf("%llu\n", libvlc_media_get_duration(media));
}
libvlc_media_release(media);
}
void /* Walker over directory */
__db_dir_walker(libvlc_instance_t *inst, const char *dir_url, bool compute_hash) {
// Build base path
char *base_url = NULL;
if (dir_url[strlen(dir_url)-1] != '/')
strconcat(&base_url, 2, dir_url, "/");
else
strcopy(&base_url, dir_url);
// Create necessary variables
struct dirent *entry;
DIR *dir;
struct stat fs;
// Try to open dir
if (!(dir = opendir(dir_url))) return;
while (entry = readdir(dir)) {
// Strip parent entries
if ((strcmp(".", entry->d_name) == 0) ||
(strcmp("..", entry->d_name) == 0)) continue;
char *dir_full_path = NULL;
strconcat(&dir_full_path, 2, base_url, entry->d_name);
if (stat(dir_full_path, &fs) < 0) return;
if (S_ISDIR(fs.st_mode)) { // Process directory
__db_dir_walker(inst, dir_full_path, compute_hash);
} else { // Process media file
__db_add_file(inst, dir_full_path, compute_hash);
}
}
// Free memory
closedir(dir);
}
void
db_scan_directory(const char *dir_url, bool compute_hash) {
// Try to open target dir
if (!opendir(dir_url)) return;
// Preload vlc instance for tag data retrieving
libvlc_instance_t *inst = libvlc_new(0, NULL);
// Walk over directory
__db_dir_walker(inst, dir_url, compute_hash);
// Free resources
libvlc_release(inst);
}
int main () {
db_scan_directory("/media/storage/music/Blur/", false);
return 0;
}
Thank you!
If there is anybody who wants to know answer on this question too, here it is:
You need to play to get the duration.
Thanks to Jean-Baptiste Kempf from Videolan Forums.
The best method is probably to call libvlc_media_parse() or its asynchronous counter-part libvlc_media_parse_async().
After calling libvlc_media_parse() your meta data (including duration) will be filed.