File System Open Files Randomly - c

One of my clients asked me to play sound from an SD card. But file selection should be random because the device is used to scare animals in the field(animals should not get used to sound pattern). I can generate random numbers by
void RNG_Generate_Numbers()
{
HAL_RNG_GenerateRandomNumber(&hrng, &random_number.random_number1);
HAL_RNG_GenerateRandomNumber(&hrng, &random_number.random_number2);
}
And I can count files via
void File_Find_File(file_manager_t *file_manage)
{
file_manage->file_result = f_readdir(&file_manage->file_direction, &file_manage->file_info);
if( (file_manage->file_result != FR_OK) || (file_manage->file_info.fname[0] == '\0') )
{
file_manage->file_counter = 0;
}
else
{
++file_manage->file_counter;
}
}
Everything till here is just fine. But when It comes to select files randomly, I could not find any method to do it. Any help is appreciated.
Edit: This is file_manager structure;
typedef struct __file_manager /* struct tag */
{
FATFS drive_handler;
FIL file_handler;
FRESULT file_result;
uint8_t file_disk_status;
DIR file_direction;
FILINFO file_info;
uint8_t file_rx_buffer[512];
char file_current_dir[256];
uint32_t file_bytes_read;
uint32_t file_bytes_write;
size_t file_counter;
}file_manager_t ;

The simplest solution would be to move all files into a single directory and name each file in a sequence starting from zero. Getting a random files name would then be as simple as:
sprintf(file_name, "%d.mp3", rand() % my_files);

Related

Browse a whole folder in C

I'm trying to list all the contents of a folder (including subfolder and its files)
Like ls -R with Linux
(I am using windows 10)
I already have this basic code with "dirent.h"
#include <stdio.h>
#include <dirent.h>
int main()
{
DIR *rep ;
struct dirent *file ;
rep = opendir ("c:\test") ;
if (rep != NULL)
{
while (file = readdir(rep))
printf ("%s\n", file->d_name) ;
(void) closedir (rep) ;
}
return 0;
}
It lists the contents of a folder well but does not browse the sub-folders
For example it could browse a whole hard drive
like C: /
I can't use d_type for detect if the content is a file or a folder
Because with windows the struct is:
struct dirent
{
long d_ino; /* Always zero. */
unsigned short d_reclen; /* Always zero. */
unsigned short d_namlen; /* Length of name in d_name. */
char d_name[260]; /* [FILENAME_MAX] */ /* File name. */
};
So I'm stuck on this problem, if anyone has an idea, or even a code
COMPILER: MinGW32 1.5.0
Here is an example of directory list for Windows.
I used Microsoft Visual Studio Community 2019 to build. It works as a Unicode Windows application. That is files and folders having name with non ASCII characters are handled correctly.
To achieve that, I used Windows typical data types and functions:
char -> WCHAR
strcpy -> wcscpy
strcat -> wcscat
strncmp -> wcsncmp
printf -> wprintf
Depending on the compiler you use, you may use the standard data types and functions.
String constant are prefixed with L to specify an Unicode string (16 bit characters).
The main function is ScanDir which take the starting directory and a file mask. Example of call:
ScanDir(L"C:\\Users\\fpiette\\Documents", L"*.jpg");
ScanDir will scan the specified folder for all files and then scan again for all directories, calling ScanDir recursively. For each file, the size and filename are displayed (Of course you may display other properties like time stamp and attributes). For each directory, the name is displayed.
Basically, iterating a directory is done using Windows FindFirstFile and FileNextFile.
Source code:
#include <stdio.h>
#include <stdlib.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
BOOL ScanDir(
WCHAR* srcDir,
WCHAR* fileMask)
{
WIN32_FIND_DATA fd;
HANDLE fh;
BOOL more;
WCHAR fromDir[MAX_PATH];
BOOL found;
_int64 fileSize;
wcscpy(fromDir, srcDir);
wcscat(fromDir, L"\\");
wcscat(fromDir, fileMask);
// First step: process files in current dir
fh = FindFirstFile(fromDir, &fd);
more = fh != INVALID_HANDLE_VALUE;
found = FALSE;
while (more) {
// Ignore directories in first step
if (0 == (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
if (!found) {
// For the first file found, display the title
found = TRUE;
wprintf(L"\nDirectory %s\n\n", srcDir);
}
fileSize = ((_int64)fd.nFileSizeHigh << 32) + fd.nFileSizeLow;
// display file information
wprintf(L"%12lld %s\n", fileSize, fd.cFileName);
}
more = FindNextFile(fh, &fd);
}
FindClose(fh);
// Second step: recursively process subfolders
wcscpy(fromDir, srcDir);
wcscat(fromDir, L"\\*.*");
fh = FindFirstFile(fromDir, &fd);
more = fh != INVALID_HANDLE_VALUE;
while (more) {
// Ignore files in second step
if (0 != (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
// We have a directory, process it recursively
if (wcsncmp(fd.cFileName, L".", 2) && // Ignore current directory "."
wcsncmp(fd.cFileName, L"..", 3)) { // Ignore parent directory ".."
wcscpy(fromDir, srcDir);
wcscat(fromDir, L"\\");
wcscat(fromDir, fd.cFileName);
if (!ScanDir(fromDir, fileMask))
return 0;
}
}
more = FindNextFile(fh, &fd);
}
FindClose(fh);
return TRUE;
}
int main()
{
// Change console output to unicode 16 bit (default is OEM)
_setmode(_fileno(stdout), _O_U16TEXT);
ScanDir(L"C:\\Users\\fpiette\\Documents", L"*.jpg");
return 0;
}

Creating a file with the name of a structure i just read from another file

I am trying to read a structure from the file f and i need some arrays of that structure ( "nume" and "firma.nrang") to be written into another file with the name of "localitate" which is also an array of the structure i am reading.
If two structures from f have the same "localitate" array, then their "nume" and "firma.nrang" fields need to be written in the same file called "localitate". I hope i explained well enough. However, i dont know why i cannot open the files i am creating, which i specifically wanted to be text and not binary. What is the problem?
This is my code which doesnt work properly:
typedef struct
{
char localitate[10];
int nrang;
} FIRMA;
typedef struct
{
char nume[20];
int varsta;
FIRMA firma;
} ANG;
ANG x;
FILE *p;
for (i=0; i<m+n; i++)
{
fread(&x,sizeof(x),1,f);
p=fopen(x.firma.localitate,"a");
if (p==NULL)
{
printf("eroare");
exit (1);
}
fwrite(&x.nume,sizeof(x.nume),1,p);
fwrite(&x.firma.nrang,sizeof(x.firma.nrang),1,p);
fclose(p);
}

Reading structure tags from a header file?

So I wanted to configure different structures for which I have a header file such as:
header.h
typedef struct
{
uint32_t hola;
uint32_t adios;
}Signal_t;
typedef struct
{
bool goodbye;
uint32_t hello;
} FrameTx_t;
In order to do so, at some point, within my source code, I will need to detect which kind of structure is to be configured by the received text.
id. est: If I have a JSON file that goes somewhere along:
JSON_File.txt
{"Signal_t" :
{
"hola" : 1024,
"adios" : 555555
}
}
I need to recognize that the to-be-configured structure is of type Signal_t.
For now I have developed a simple code in which, after parsing the text, I can obtain the name of the structure in a string format, and then I created the following function to determine which structure is to be configured:
Code.c
int structure_Select(char* structName, int sizeOfStructName) {
char Signal_tName[] = "Signal_t";
char FrameTx_tName[] = "FrameTx_t";
int idx=0;
if ((sizeof(Signal_tName) - 1) == sizeOfStructName) {
for (idx = 0;idx < sizeOfStructName;idx++) {
if (Signal_tName[idx] != structName[idx]) {
break;
}
}
if (idx == sizeOfStructName) {
printf("%s", Signal_tName);
return 0;
}
}
if ((sizeof(FrameTx_tName) - 1) == sizeOfStructName) {
for (idx = 0;idx < sizeOfStructName;idx++) {
if (FrameTx_tName[idx] != structName[idx]) {
break;
}
}
if (idx == sizeOfStructName) {
printf("%s", FrameTx_tName);
return 1;
}
}
}
I can assure you it works; it just does not go as "automatic" as I would like it to be...
I would like for the program to be able to read the header file and automatically recognize: "Oh okay, so I'm dealing with a Signal_t data type, I'm gonna then read two different data from the stream and assign data1 to Signal_t.hola and data2 to Signal_t.adios"
The assignation is clearly not a problem; only determining from an existing structure within a file the name of it or a way to differentiate between structs.
So far I've thought about the following possibilities outside of what I already have, but I'm cycled within it:
o Create a mini "C-structure parser" function
o Is there ANY way to get the name of a structure tag within C that I don't know of?
I'm open to suggestions, whether it's just ideas that I could work on and I'm not seeing or if any of you has dealed with a similar issue in the past and instead of using a list of char variables, actually reads the header file for the structure names... thanks in advance!
.
.
.
TL;DR: Is there any way to read structures' tags from a header file as a string?
Edit: This is what I mean with structure tag/type alias:
//structure to get a rectangle
typedef struct {
int left;
int bottom;
int right;
int top;
} rect_t; //this rect_t is what I mean by structure tag...
//I checked the name and it should be type alias***

In C how can I find in a directory all the file names and store them in a array of strings of characters?

I create a code in C to find all file names in a directory, this code is recursive so if it finds other directories within this will review the others directories. The search in the directory and the search of files works well,, because i printed on screen what the program read and i realized that find all filenames and does not repeat any filename. The problem i have is that i saves into an array of strings of characters the file name found, and when you find all the files i will have in the main the arrangement of strings with all the file names, but when i printed on screen that arrangement there is not all the files in it, but a few repeated files names. The ultimate goal of this program is not print all file names in screen, the purpose is to save in the arrangement all the file names .I can not see the error, if someone can tell me something that I'm doing wrong I'll be grateful.
void findfiles(char *root,char *p[],int *tam){
DIR * dir;
struct dirent *entrada;
struct stat stt;
dir = opendir(root);
char *aux;
char nombre[BUFFER_TAM];
char buf[30];
if (dir == NULL) {
printf("hola4\n");
return;
}
while ((entrada = readdir(dir)) != NULL) {
if (strcmp(entrada->d_name,".")==0 || strcmp(entrada->d_name,"..")==0);
else {
if (entrada->d_type == DT_DIR){
strcpy(nombre,root);
strcat(nombre,"/");
strcat(nombre,entrada->d_name);
findfiles(nombre,p,tam);
}
else {
strcpy(nombre,root);
strcat(nombre,"/");
strcat(nombre,entrada->d_name);
p[*tam]=malloc(strlen(nombre)+1);
p[*tam]=nombre;
*tam = *tam +1;
}
}
}
}
void main(){
char *archivos[BUFFER_TAM];
char root[BUFFER_TAM]="/home/jesusmolina/Documentos";
int i=0,tam=0;
findfiles(root,archivos,&tam);
for (i;i<tam;i++)
printf("%s\n",archivos[i]);
}
p[*tam]=malloc(strlen(nombre)+1);
p[*tam]=nombre;
You allocate a chunk of memory, then immediately lose the pointer to that memory and leak it. You probably wanted:
p[*tam]=malloc(strlen(nombre)+1);
strcpy(p[*tam], nombre);

Segmentation fault while convering large number of xml files into text

#include<stdio.h>
#include<stdlib.h>
#include<dirent.h>
#include<string.h>
int main()
{
FILE *fin,*fout;
char dest[80]="/home/vivs/InexCorpusText/";
char file[30];
DIR *dir;
char c,state='1';
int len;
struct dirent *ent;
if((dir=opendir("/home/vivs/InexCorpus"))!=NULL)
{
while((ent=readdir(dir))!=NULL)
{
if(strcmp(ent->d_name,".") &&
strcmp(ent->d_name,"..") &&
strcmp(ent->d_name,".directory"))
{
len=strlen(ent->d_name);
strcpy(file,ent->d_name);
file[len-3]=file[len-1]='t';
file[len-2]='x';
//strcat(source,ent->d_name);
strcat(dest,file);
printf("%s\t%s\n",ent->d_name,dest);
fin=fopen(ent->d_name,"r");
fout=fopen(dest,"w");
while((c=fgetc(fin))!=EOF)
{
if(c=='<')
{
fputc(' ',fout);
state='0';
}
else if(c=='>')
state='1';
else if(state=='1')
{
if(c!='\n')
fputc(c,fout);
if(c=='.')
{
c=fgetc(fin);
if(c==' '||c=='\n'||c=='<')
{
fputc('\n',fout);
ungetc(c,fin);
}
else fputc(c,fout);
}
}
}
}
close(fin);
close(fout);
strcpy(dest,"/home/vivs/InexCorpusText/");
}
closedir(dir);
}
else
{
printf("Error in opening directory\n");
}
return 0;
}
I was trying to convert xml files to text. This code simply remove tags and nothing else.
When i execute this code for around 300 files, it doesn't show any error but when number goes to 500 or more i receive a segmentation fault after processing around 300 files.
At least one reason 'right from the start':
Here is struct dirent declaration from man:
On Linux, the dirent structure is defined as follows:
struct dirent {
ino_t d_ino; /* inode number */
off_t d_off; /* offset to the next dirent */
unsigned short d_reclen; /* length of this record */
unsigned char d_type; /* type of file; not supported
by all file system types */
char d_name[256]; /* filename */
};
You are in trouble on any name longer than 30 (actually 29) chars. Memory overwrite occurs because file has only 30 bytes (reserve 1 for '\0' terminator):
char file[30];
...
strcpy(file,ent->d_name);
There are two structures within XML that it does not appear that you account for.
Attribute contents can contain unescaped > characters, which could throw off your count. See http://www.w3.org/TR/REC-xml/#NT-AttValue.
CDATA sections can contain both < and > characters as literal text, as long as they do not appear as part of the closing ]]> string. See http://www.w3.org/TR/REC-xml/#NT-CharData. This could seriously throw off your logic.
Why don't you look in your files to see if any contain the text CDATA?
You might want to consider using xsltproc or libxslt; a very simple XSLT transform would give you exactly what you want. See Extract part of an XML file as plain text using XSLT for such a transform engine.
OK, another problematic place:
len=strlen(ent->d_name);
....
file[len-3]=file[len-1]='t';
file[len-2]='x';
Because d_name could have less than 3 characters it could again lead to memory overwrite.
You should be careful with functions like strlen() and always validate their result.

Resources