Wednesday, December 15, 2021

Getting file/folder list in Windows and Linux

Getting file/folder list in Windows and Linux without using libraries is a tricky business. In Windows Visual Studio, there is also a character set setting (Project properties - Advanced - Character Set) which has to be taken into account.

#ifdef _WIN32
#include <windows.h> //NOTE: The first include must be windows.h
#include <stdio.h>
#include <tchar.h>
#include <strsafe.h>
#include<comdef.h> //to convert WCHAR to char*
#pragma comment(lib, "User32.lib")
namespace FileUtils { //NOTE: namespace must come after #include statements, otherwise you will get strange errors.
//https://docs.microsoft.com/en-us/windows/win32/fileio/listing-the-files-in-a-directory
int GetAll(DWORD fileAttribute, const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
WIN32_FIND_DATA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
DWORD dwError = 0;
TCHAR szDir[MAX_FOLDER_NAME_LENGTH];
#ifdef UNICODE //Project properties - Advanced - Character Set
//convert const char* to LPCWSTR:
int size = MultiByteToWideChar(CP_ACP, 0, folderName, -1, NULL, 0);
TCHAR folderNameLPCWSTR[MAX_FOLDER_NAME_LENGTH];
MultiByteToWideChar(CP_ACP, 0, folderName, -1, (WCHAR*)folderNameLPCWSTR, size);
// Prepare string for use with FindFile functions. First, copy the string to a buffer, then append '\*' to the directory name.
StringCchCopy(szDir, MAX_FOLDER_NAME_LENGTH, (STRSAFE_LPCWSTR)folderNameLPCWSTR);
StringCchCat(szDir, MAX_FOLDER_NAME_LENGTH, TEXT("\\*"));
#else //Multi-Byte
sprintf(szDir, "%s\\*", folderName);
#endif
// Find the first file in the directory:
//hFind = FindFirstFile(szDirLPCWSTR, &ffd);
hFind = FindFirstFile(szDir, &ffd);
if (INVALID_HANDLE_VALUE == hFind) {
printf("Error: Folder (%s) does not exist!\n", folderName);
return 0;
}
// List all the files in the directory with some info about them.
size_t nFiles = 0;
do {
if (ffd.dwFileAttributes & fileAttribute) {
//convert wchar to char*:
_bstr_t b(ffd.cFileName);
const char* fileName = b;
strcpy(fileNames[nFiles], fileName);
//filesize.LowPart = ffd.nFileSizeLow;
//filesize.HighPart = ffd.nFileSizeHigh;
//_tprintf(TEXT(" %s %ld bytes\n"), ffd.cFileName, filesize.QuadPart);
nFiles++;
if (nFiles > MAX_NB_OF_FILES) {
printf("Error: nFiles (%d) > MAX_NB_OF_FILES (%d)!\n", nFiles, MAX_NB_OF_FILES);
return 0;
}
}
} while (FindNextFile(hFind, &ffd) != 0);
dwError = GetLastError();
if (dwError != ERROR_NO_MORE_FILES) {
printf("Error: %d\n", dwError);
return 0;
}
FindClose(hFind);
//return dwError;
return nFiles;
}
int GetAllFolders(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(FILE_ATTRIBUTE_DIRECTORY, folderName, fileNames);
}
#define FILE_ATTRIBUTE_FILE (8224)
int GetAllFiles(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(FILE_ATTRIBUTE_FILE, folderName, fileNames);
}
#else //POSIX, Linux
//https://stackoverflow.com/a/4204758/51358
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#define FILE_ATTRIBUTE_DIRECTORY (4)
#define FILE_ATTRIBUTE_FILE (8)
namespace FileUtils {
int GetAll(const char* folderName, unsigned char d_type, char fileNames[][MAX_FILE_NAME_LENGTH]) {
DIR* d = opendir(folderName);
int nFiles = 0;
if (d) {
struct dirent* dir;
while ((dir = readdir(d)) != NULL) {
if(d_type == dir->d_type) {
//printf("name: %s, type: %d\n", dir->d_name, dir->d_type);
strcpy(fileNames[nFiles], dir->d_name);
nFiles++;
}
}
closedir(d);
}
return nFiles;
}
int GetAllFolders(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(folderName, FILE_ATTRIBUTE_DIRECTORY, fileNames);
}
int GetAllFiles(const char* folderName, char fileNames[][MAX_FILE_NAME_LENGTH]) {
return GetAll(folderName, FILE_ATTRIBUTE_FILE, fileNames);
}
#endif // _WIN32
}

Wednesday, December 1, 2021

Vectors for Software Engineers

Vectors are common in simulations but software engineers can forget the basics of vector operations. Here is a quick refresher:


In equation (1), we have a velocity vector of point m with respect to point c, expressed as a sum of two vectors.

In equation (2), we have the same equation but in scalar form. The "(n)" represents the reference frame in which the components of the vectors are expressed. In order to perform addition, all vector components must be expressed in the same reference frame.

If you want more detail, check out my advanced dynamics lecture notes (PDF).