Saturday, April 23, 2011

Add node at the end of linked list

Given a singly linked list and node to insert, insert given node at the end of link list.

Below is the code to add node at the end of the linked list:

Here node is of form:

struct Node {
    int data;
    Node * next;
};

Node* AddAtEnd(Node* head, int value)
{
if(head == NULL)
{
head = new Node;
head->next=NULL;
head->data= value;
return head;     
}
Node* node = head;
while( node->next!=NULL)
node = node->next;

Node* tmp = new Node;
tmp->next= NULL;
tmp->data=value;
node->next = tmp;
return head;
}

Wednesday, April 6, 2011

Simple File Enumerator

Here I will explain the design of simple file enumerator program, which enumerates file under given directory.


The program uses FindFirstFile and FindNextFile functions to complete the task. You can read the information about these functions on MSDN.  


The class will accept the Directory path as input and will return the vector containing  file under directory, along with each file size. 


As we will be returning the file name, file size and file path, we will declare a struct which contains this information.



typedef struct
{
std::wstring m_strFilePath;
std::wstring m_strFileName;
DWORD m_nFileSizeHigh;
DWORD m_nFileSizeLow;
} FileInfo;

We will be returning the vector of this struct. Lets declare the typedef for our vector.

typedef std::vector<FileInfo> FileInfo_Vector;

Now we should define the class structure, I mean what are the methods and members this class will contain.



class DirectoryEnumerator
{
public:
     DirectoryEnumerator(const std::wstring & rkstrDirectoryPath);
     ~DirectoryEnumerator();
     HRESULT Init(DWORD dwDirDepth = -1 );
     void GetFilesInfo(FileInfo_Vector& rfileInfoVector);
 


private:
     void EnumerateDir(FileInfo_Vector& rfileInfoVector,
                       const std::wstring& rkstrFolderPath,
                       DWORD dwDirSearchDepth );


private:
     std::wstring  m_strRootDirectoryPath;
     DWORD         m_dwDirSearchDepth;
};

Here Init will get the extra input that is search depth in directory. If you want to search in all the subdirectories the input to Init will be -1, else a depth value. 

Init will check first if the given directory is exist and can be queried, if yes then it will return OK, else it will fail.

Once Init is successful, you can query GetFilesInfo, which will accept reference to vector and will update that vector with file information under directory.


EnumerateDir is our internal function which enumerate the directory and will fetch the required data.


As base structure of class ready, lets move towards actual code.



DirectoryEnumerator::DirectoryEnumerator(const std::wstring & rkstrDirectoryPath)
:m_strRootDirectoryPath(rkstrDirectoryPath)
,m_dwDirSearchDepth(-1)
{
}


DirectoryEnumerator::~DirectoryEnumerator()
{
}


HRESULT DirectoryEnumerator::Init( DWORD dwDirDepth, /* = -1 */ )
{
m_dwDirSearchDepth  = dwDirDepth;

if( m_dwDirSearchDepth == 0 || m_dwDirSearchDepth < -1)
m_dwDirSearchDepth = 1;


std::wstring strRootDir(m_strRootDirectoryPath);


size_t found = strRootDir.find(L"\\*");
if(found == std::wstring::npos)
strRootDir += L"\\*";


WIN32_FIND_DATA FindFileDataStruct;
HANDLE hFind = FindFirstFile(strRootDir.c_str(), &FindFileDataStruct);
if(hFind == INVALID_HANDLE_VALUE)
{


HRESULT  hr = ::GetLastError();
::FindClose(hFind);
return hr ;
}


::FindClose(hFind);
return S_OK;
}



void DirectoryEnumerator::EnumerateDir( FileInfo_Vector& rfileInfoVector, const std::wstring& rkstrFolderPath, DWORD dwDirSearchDepth )
{
std::vector<std::wstring>  SubDirectoryVector;
std::wstring strRootDir(rkstrFolderPath);


size_t found = strRootDir.find(L"\\*");
if(found == std::wstring::npos)
strRootDir += L"\\*";


WIN32_FIND_DATA FindFileDataStruct;
HANDLE hFind = FindFirstFile(strRootDir.c_str(), &FindFileDataStruct);
if(hFind == INVALID_HANDLE_VALUE)
{
::FindClose(hFind);
return;
}


try
{
do
{
BOOL BReturnValue= ::FindNextFile(hFind, &FindFileDataStruct);
if( 0 == BReturnValue )
{
DWORD dwError = ::GetLastError();
if(ERROR_NO_MORE_FILES == dwError)
{
//No more Files. Enumeration completed
}
else
{
//Error occured while enumerating directory
}
break;
}


if (FindFileDataStruct.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if( !(m_dwDirSearchDepth == 1))
SubDirectoryVector.push_back (rkstrFolderPath + L"\\" + FindFileDataStruct.cFileName);
}
else
{
FileInfo fileInfoStruct;
fileInfoStruct.m_strFilePath = rkstrFolderPath;
fileInfoStruct.m_strFileName = FindFileDataStruct.cFileName;
fileInfoStruct.m_nFileSizeHigh = FindFileDataStruct.nFileSizeHigh;
fileInfoStruct.m_nFileSizeLow = FindFileDataStruct.nFileSizeLow;


rfileInfoVector.push_back(fileInfoStruct);
}


}while(true);
}
catch(...)
{
//Exception occured while enumeration.
}
::FindClose(hFind);


if(SubDirectoryVector.empty())
return;


if( dwDirSearchDepth == 0 )
return;


if( dwDirSearchDepth != -1)
dwDirSearchDepth -= 1;


std::vector<std::wstring>::const_iterator it = SubDirectoryVector.begin();

it++; //first directory will be always ".."


for(;it != SubDirectoryVector.end(); it++)
{
EnumerateDir(rfileInfoVector, *it, dwDirSearchDepth);
}
}