 |
|
 |
not given entire picture ...this is the thing one begineer will already know
|
|
|
|
 |
|
|
 |
|
 |
Best pointer to pointer example with matrices
|
|
|
|
 |
|
 |
Hi, thanks for this example!
I would like to comment that under Visual Studio 2010 dereferencing val (i.e. *val) gives a compiler error. I think that this is actually wrong, it should read *a in the example code.
|
|
|
|
 |
|
 |
Really helpful tutorial about allocating memory to double indirected pointers.
|
|
|
|
 |
|
 |
Here is the example of great usage of this code.
#include "stdafx.h"
#include <memory.h>
#include <string.h>
#include <stdlib.h>
#include <malloc.h>
#include <Windows.h>
// cipher datastructure
typedef struct _crypt_info_
{
unsigned char *key; // XOR key
int keylen; // length of the key in bytes
unsigned char *plaindata; // pointer to plain data buffer
int plaindatalen; // plain data length
int indx; // debug field
unsigned char *cryptdata; // pointer to cipher data
int cryptdatalen; // cipher data buffer length
}sCryptinfo, *psCryptinfo;
/*
* This function allocates memory and initializes fields.
* It returns a pointer to the crypt info.
* Parameters:
* int - number of threads
* int - plane data length
* int - key length
* unsigned char* - xor key
* Returns:
* psCryptinfo * - pointer to psCryptinfo
* user need to fee all memory by calling freeM
*/
psCryptinfo *allocM(int noofprocess, int datalen, int keylen, unsigned char *key)
{
static const char eMsg[] = "No Memory Availabe\n";
psCryptinfo *ppcrypto = (psCryptinfo *)malloc(sizeof (psCryptinfo *)* noofprocess);
for (int i=0; i<noofprocess; i++){
*(ppcrypto+i) = (psCryptinfo )malloc (sizeof(sCryptinfo));
memset((void *)*(ppcrypto+i), 0,sizeof(sCryptinfo));
}
for (int i=0; i<noofprocess; i++){
psCryptinfo tcrypto = *(ppcrypto+i);
tcrypto->indx = i;
tcrypto->cryptdatalen = datalen;
tcrypto->cryptdata = (unsigned char *)malloc((datalen*sizeof(char))+1);
if (tcrypto->cryptdata)
memset(tcrypto->cryptdata,0,datalen);
tcrypto->key = (unsigned char *)malloc((keylen*sizeof(char))+1);
if (tcrypto->key)
memset(tcrypto->key,0,keylen);
tcrypto->keylen = keylen;
tcrypto->plaindata = (unsigned char *)malloc((datalen*sizeof(char))+1);
if (tcrypto->plaindata)
memset (tcrypto->plaindata,0,datalen);
tcrypto->plaindatalen = datalen;
if (tcrypto->key)//copy the key
strcpy_s((char *)tcrypto->key,keylen+1,(char *)key);//copy key
}
return ppcrypto;
}
/*
* This function frees all memory allocated in allocM
* Parameters:
* pcryptinfo - pointer to cryptinfo
* int - no of threads
* Returns:
* void
*
*/
void freeM(psCryptinfo *ppcrypto, int nprocess)
{
psCryptinfo tempCrypt;
for (int i=0; i< nprocess; i++){
tempCrypt = *(ppcrypto+i);
if (tempCrypt->cryptdata)
free (tempCrypt->cryptdata);
if (tempCrypt->key)
free (tempCrypt->key);
if (tempCrypt->plaindata)
free (tempCrypt->plaindata);
free(tempCrypt);
}
free(ppcrypto);
}
/*
*
* This function calculates and returns N sized blocks.
* Parameters:
* int - keysize in bytes
* Returns
* N blk size
*
*/
int calcBlkSize (int sz)
{
return ((sz << 3)*sz );
}
/*
* This function gets the key size and returns the length of the key in bytes.
* It takes a pointer to the key file as a parameter.
* Parameters:
* FILE * - pointer to key file
* returns
* key length in bytes
*
*/
long findkeysize(FILE *fp)
{
static const char eMsg[] = "Error accessing file\n";
long current = ftell(fp); // save the current file pointer
if (fseek(fp, 0, SEEK_SET)){ // move the pointer to begining
fwrite(eMsg,sizeof (char),strlen(eMsg),stderr);
return 0;
}
long begin = ftell(fp); // read the file pointer
if (fseek(fp, 0, SEEK_END)){ // move the file pointer to end
fwrite(eMsg,sizeof (char),strlen(eMsg),stderr);
return 0;
}
long end = ftell(fp); // read file pointer
if (fseek(fp, current, SEEK_SET)){ // restore file pointer
fwrite(eMsg,sizeof (char),strlen(eMsg),stderr);
return 0;
}
return end - begin; // difference between end and begin
}
/*
*
* This function rotates and returns the key so that it's prepared for XOR.
* Parameters:
* unsigned char * - pointer to current key
* int - size in bytes
* returns
* returns rotated key (user parameter is updated)
*
*/
void GetNewKey( unsigned char *currentkey, int sizeinbytes)
{
unsigned char lowbit=0,highbit;
for (int i=0; i<sizeinbytes; i++){
highbit = (*(currentkey+i) >>7); //save the high bit
*(currentkey+i)= (*(currentkey+i)<<1)|lowbit; //rotate left by 1 bit
// and or with last high bit
lowbit = highbit; //need to save for next byte
}
*currentkey |= lowbit; //last bit moves to first byte of the key
}
/*
*
* This function encrypts data without error checking.
* It stores the encrypted data in an encrypted buffer pointer.
* No Boundary condtions is verified
* Parameters:
* unsigned char * - pointer to plain data buffer
* unsigned char * - pointer to key
* unsigned char * - pointer to encrypted buffer
* int - length of key in bytes
* returns
* returns encrypted data in encrypted buffer pointer
*
*/
void BlkEncryption(unsigned char *data,
unsigned char *key,
unsigned char *encryptdata,
int keysizeinbytes
)
{
int indx=0;
int nbits = keysizeinbytes<<3;
for (int j=0; (j < nbits); j++){
for (int i=0; i<keysizeinbytes; i++){
*(encryptdata+indx+i) = (*(data+indx+i) ^ *(key+i)); // xOR data with key
}
indx += keysizeinbytes;
GetNewKey(key,keysizeinbytes);
}
}
/*
*
* This function encrypts data without error checking.
* It stores the encrypted data in an encrypted buffer pointer.
* Boundary condtions is verified
* Parameters:
* unsigned char * - pointer to plain data buffer
* unsigned char * - pointer to key
* unsigned char * - pointer to encrypted buffer
* int - length of key in bytes
* int - truncated buffer length
* returns
* returns encrypted data in encrypted buffer pointer
*
*/
void BlkEncryptionPartial(unsigned char *data,
unsigned char *key,
unsigned char *encryptdata,
int keysizeinbytes,
int blkactlen)
{
int indx=0;
for (int j=0; (j < (keysizeinbytes<<3)); j++){
for (int i=0; i<keysizeinbytes; i++){
if ((indx+i) >= blkactlen){
return; //it must be eof so key not same is ok
}
*(encryptdata+indx+i) = (*(data+indx+i) ^ *(key+i));
}
indx += keysizeinbytes;
GetNewKey(key,keysizeinbytes);
}
}
/*
*
* This is worker thread - which cipher data
* Parameters:
* void * - pointer to data structure
* returns
* returns 0 - as successs
*
*/
// worker thread
DWORD WINAPI ThreadCryptProcess (void *pparam)
{
psCryptinfo psdata = (psCryptinfo)pparam;
int blksz = calcBlkSize(psdata->keylen);
// is block length and actual data length are not same
// we need to transform data while check for actual data length
if (blksz < psdata->plaindatalen){//partial plain data?
BlkEncryptionPartial(psdata->plaindata,
psdata->key,
psdata->cryptdata,
psdata->keylen,
psdata->plaindatalen);
}
else{// complete block size data
BlkEncryption(psdata->plaindata,
psdata->key,
psdata->cryptdata,
psdata->keylen);
}
return 0;
}
/*
*
* This is the heart of this program
* reads files and ciphers data
* Parameters:
* char * - key file name
* char * - plaindata file name (optional)
* char * - cipher file name (opitional)
* int - no of threads
* returns
* returns false if error else return true for success
*
*/
bool cipherMain (char *keyfname, char *plaindatafname, char *cipherfname, int nprocess)
{
FILE *fpPlaindata = NULL, *fpCryptodata = NULL;
FILE *fpkey = NULL;
const static char eMsg[6][32] = {"Failed to record data\n",
"Failed to create thread\n",
"Failed to Open Key File\n",
"Failed to read key\n",
"Failed to Open Plain data File\n",
"Failed to Opne cipher File\n"};
HANDLE *hThreads = (HANDLE *)malloc(sizeof (HANDLE)*nprocess);
memset((void*)hThreads,0,sizeof(HANDLE));
DWORD dwGenericThread;
psCryptinfo tcrypto;
int keylen = 0, datalen = 0;
// extract the key from the file
fopen_s(&fpkey,keyfname,"rb");
if (!fpkey){
fwrite(eMsg[2],sizeof(char),strlen(eMsg[2]),stderr);
return false;
}
int blklen = 0;
keylen = findkeysize(fpkey);
blklen = calcBlkSize(keylen);
char *key = (char *)malloc((sizeof(char)*keylen)+1);
memset(key,0,keylen+1);
if (!feof(fpkey)){
fread(key,sizeof(char),keylen,fpkey);
fclose(fpkey);
}
else{
fclose(fpkey);
free(key);
fwrite(eMsg[3],sizeof(char),strlen(eMsg[3]),stderr);
return false;
}
//allocates memory based on number of process and key size
psCryptinfo *ppcrpInfo = allocM(nprocess,blklen,keylen,(unsigned char *)key);
int len= 0;
int processcount = 0;
//open plain file
if (strlen(plaindatafname) == 0)
fpPlaindata = stdin;
else{
fopen_s(&fpPlaindata,plaindatafname,"rb");
}
if (!fpPlaindata){
fwrite(eMsg[4],sizeof(char),strlen(eMsg[4]),stderr);
free(key);
freeM(ppcrpInfo, nprocess);
return false;
}
//open cipher file
if (strlen(cipherfname) == 0)
fpCryptodata = stdout;
else{
fopen_s(&fpCryptodata,cipherfname,"wb");
}
if (!fpCryptodata){// we have problem opening file
fwrite(eMsg[5],sizeof(char),strlen(eMsg[5]),stderr);
free(key);
if (fpPlaindata != stdin)
fclose(fpPlaindata);
freeM(ppcrpInfo, nprocess);
return false;
}
// repeat until entire plain data file is ciphered
while(!feof(fpPlaindata)){
processcount = 0;
for (int i=0; i<nprocess; i++){
tcrypto = *(ppcrpInfo+i);
// read data from the file in block data
if (!feof(fpPlaindata)){//if not end of file read plain data
tcrypto->plaindatalen = fread(tcrypto->plaindata,
sizeof(char),
blklen,
fpPlaindata);
}else{
tcrypto->plaindatalen = 0;
}
if (tcrypto->plaindatalen){//create thread according to availability of data
hThreads[i] = CreateThread(NULL,
0,
ThreadCryptProcess,
(void *)*(ppcrpInfo+i),
0,
&dwGenericThread
);
if (hThreads[i] != NULL)
processcount++;
else{
fwrite(eMsg[1],sizeof(char),strlen(eMsg[1]),stderr);
}
}
}
// since data need to be recorded in synchronizely we need to
// wait for all thread completes
WaitForMultipleObjectsEx(processcount,hThreads,true,INFINITE,false);
for (int j=0; j<processcount; j++){
tcrypto = *(ppcrpInfo+j);
//resotre the key back - testinf purpose
//strcpy_s((char *)tcrypto->key,keylen+1, key);
// release thread handle
if (hThreads[j]){
CloseHandle(hThreads[j]);
hThreads[j] = NULL;
}
len = fwrite(tcrypto->cryptdata,
sizeof(char),
tcrypto->cryptdatalen,
fpCryptodata);
if (len != tcrypto->cryptdatalen)
fwrite(eMsg[0],sizeof(char),strlen(eMsg[0]),stderr);
}
}
// close files
if (fpPlaindata != stdin)
fclose(fpPlaindata);
if (fpCryptodata != stdout)
fclose(fpCryptodata);
// free resources
free(key);
freeM(ppcrpInfo, nprocess);
//returns true for success
return true;
}
/*
* This function will convert a WCHAR string to a CHAR string.
*
* Param 1 :: Pointer to a buffer that will contain the converted string. Ensure this
* buffer is large enough; if not, buffer overflow errors will occur.
* Param 2 :: Constant pointer to a source WCHAR string to be converted to CHAR
*/
void wtoc(CHAR* Dest, const WCHAR* Source)
{
int i = 0;
while(Source[i] != '\0')
{
Dest[i] = (CHAR)Source[i]; //convert WCHAR to CHAR
++i;
}
Dest[i] = '\0';//added string terminator
}
/*
* This function will display command line options.
*/
void CommandLineArgumentHelper()
{
fwrite("encryptUtil [-n #] [-k keyfile] [-p plainfile] [-c cipherfile]\n\0",sizeof(char),63,stderr);
fwrite("-n # Number of threads to create\n\0",sizeof(char),33,stderr);
fwrite("-k keyfile Path to file containing key\n\0",sizeof(char),39,stderr);
fwrite("-p plainfile for encrypt\n\0",sizeof(char),25,stderr);
fwrite("-c cipherfile for cryputed file\n\0",sizeof(char),32,stderr);
}
int _tmain(int argc, _TCHAR* argv[])
{
static const _TCHAR *Options [] = {L"-n", L"-k", L"-p", L"-c", L"-?"};
//encryptUtil [-n #] [-k keyfile]
//-n # Number of threads to create
//-k keyfile Path to file containing key
//-p plainfile for encrypt
//-c cipherfile for cryputed file
//parse parameters
int optind=1; // traverse arguments parameters
int nprocess = 1; // receive #of threads
char keyfname[256] = "\0"; // receive keyfile name
char plainfname[256] = "\0"; // receive plain file name
char cipherfname[256] = "\0"; // receive cipher file name
_TCHAR sw[256]; // temporary buffer
// extract user provided command line information
if (argv[optind][0]=='?'){
CommandLineArgumentHelper();
exit(0);
}
while ((optind < argc) &&
(argv[optind][0]=='-')) {
wcscpy_s(sw,256, argv[optind]);
if (_tcscmp(sw,Options[0]) == 0) {
optind++;
nprocess = _wtoi(argv[optind]);
}
else if (_tcscmp(sw,Options[1])==0) {
optind++;
wtoc(keyfname,argv[optind]);
}
else if (_tcscmp(sw,Options[2])==0) {
optind++;
wtoc(plainfname,argv[optind]);
}
else if (_tcscmp(sw,Options[3])==0) {
optind++;
wtoc(cipherfname,argv[optind]);
}
else if (_tcscmp(sw,Options[4])==0) {
CommandLineArgumentHelper();
exit(0);
}
optind++;
}
//check if keyfile name is provided?
if (strlen(keyfname) == 0){
CommandLineArgumentHelper();
exit(0);
}
// main program to cipher file
cipherMain (keyfname, plainfname, cipherfname, nprocess);
fwrite("cipher completed\n",sizeof(char),18,stderr);
return 0;
}
|
|
|
|
 |
|
 |
this is a g8t tutorial for beginners like me in 2 dim array pointers
|
|
|
|
 |
|
 |
not because your article is wrong, but that it does not present something new, better or an alternative to what people in programming have been doing since the birth of the C language ( more or less ) since its beginning.
And that you do not at least present the better C++ alternative of new and delete.
Also, if you want your article to be a beginner tutorial on memory allocation and pointer arithmetic, you should describe and show what this is; * operator, what it does ( dereference ), ... and how this works.
M.
Maximilien Lincourt
Your Head A Splode - Strong Bad
|
|
|
|
 |
|
 |
Maximilen,
Thanks for the feed back. I totally agree with you. I will add statements to mention that it is meant for beginners and also as you suggested the description of pointer operator.
Once again thanks for the suggestions. This is the first time I am attempting something like this.
Regards,
Rajesh
|
|
|
|
 |
|