How to split a text file bit by bit into two files - c

How can I split a text file into two other files bit by bit. I need all the even numbered bits in file A and all the odd ones in B. In other words, if File X is:
0101010111110000
Then File A would be: 00001100
and B would be: 11111100
Then I need to save those as .txt files. After that, I will need to merge them back together to get X again.
I am using c.
The code I have so far is as follows:
#include <stdio.h>
void printchar( unsigned char to_print )
{
unsigned char mask = 0x80;
for( int i = 0; i < 8; ++i )
{
if( (mask & to_print) > 0 )
{
printf( "%d", 1 );
}
else
{
printf( "%d", 0 );
}
mask = mask >> 1;
}
printf( "\n" );
}
void split( unsigned char * left, unsigned char * right, unsigned char input1, unsigned char input2 )
{
unsigned char mask = 0x80;
for( int i = 0; i < 4; ++i )
{
(*left) |= ( (input1 & mask) << i );
(*left) |= ( (input2 & mask) >> (4-i) );
mask = mask >> 1;
(*right) |= ( (input1 & mask) << (i+1) );
(*right) |= ( (input2 & mask) >> (3-i) );
mask = mask >> 1;
}
}
int main (int argc, const char * argv[])
{
unsigned char left = 0;
unsigned char right = 0;
unsigned char input1 = 0xA6;
unsigned char input2 = 0xB5;
split( &left, &right, input1, input2 );
printchar( left );
printchar( right );
return 0;
}

read char by char
in youre code build two buffer chars one with even and other with odd bits
to fully build 2 chars you need to read 2 chars from file
when you have read 4 chars from input file you can write 2 chars you have built
and so one
for part to same approach but in reverse.
You should be careful with the order of reading /writing even/odd bits

Related

How to convert strings in array to unsigned integers?

I have the following code:
char switch_list[] = {
"PINB >> 7",
"PIND >> 1",
"PINB >> 1",
"PIND >> 0}"
};
void values(void){
uint8_t switch_value = 0;
if (i == 0){
switch_value = (PINB >> 7) & 1;
}
if (i == 1){
switch_value = (PIND >> 1) & 1;
}
if (i == 2){
switch_value = (PINB >> 1) & 1;
}
if (i == 3){
switch_value = (PIND >> 0) & 1;
}
SOME OTHER OPERATIONS GO HERE
}
I need to interpret the switch_list values as unsigned integers somehow, but I am not able to make any changes to the array (it needs to remain a char array). PINB and the others have defined 8 bit value in the libraries. I would like to create a for loop that looks something like this:
uint8_t switch_value = 0;
for (int i = 0, i < sizeof(switch_list)/sizeof(switch_list[0]); i++){
switch_value = **********[i] & 1;
SOME OTHER OPERATIONS GO HERE
}
}
Where ********* is the same as switch_list but instead of being of char type, it is uint8_t. Can anyone provide any tips?
You can use your knowledge about the array and create a function to convert your values from "PINB >> 7" to PINB >> 7. The assumptions I made are:
The string always starts with "PIN" and then has a "B" or a "D" (can be easily modified )
The string will then do an operation (currently I only support ">>" but this can too be easily modified)
Last char in the string is a 1-char number (again, can be modified according to your knowledge about the string)
Using that, I can create a convert function
unsigned int convert(char * p);
/* PINB and the others have defined 8 bit value in the libraries
so I'm making up their values here for convenience */
unsigned int PINB = 1024;
unsigned int PIND = 2048;
int main(){
// deleted your ending }
// and changed the type of the array
char* switch_list[] = {
"PINB >> 7",
"PIND >> 1",
"PINB >> 1",
"PIND >> 0"
};
unsigned int switch_value;
// , should be ;
// don't compare signed with unsigned
for (unsigned int i = 0; i < sizeof(switch_list)/sizeof(switch_list[0]); i++){
switch_value = convert(switch_list[i]);
printf("%u\n", switch_value);
}
return 0;
}
// assuming string must be exactly long as "PINB >> 7"
unsigned int convert(char * p){
if(!p || strlen(p) != strlen("PINB >> 7")){
printf("error\n");
return (unsigned)-1;
}
unsigned int n;
// use a string compare or, in your case, since only the 4th char is different:
if(p[3] == 'B')
n = PINB;
if(p[3] == 'D')
n = PIND;
// note I'm not handling a case where the 4th letter isn't {'B', 'D'}, according to my assumption (the 1st).
// use your knowledge about the string inside switch_list
return n >> (p[strlen(p) - 1] - '0');
}
Assuming the PINx thingies would evaluate to a type PIN_T you can do:
#include <stdlib.h> /* for size_t */
#include <inttypes.h> /* for uint8_t */
/* other include here */
struct switch_s
{
PIN_T * ppin;
uint8_t offset;
};
struct switch_s switches[] =
{
{&PINB, 7},
{&PIND, 1},
{&PINB, 1},
{&PIND, 0},
/* more here */
};
int main(void)
{
for (size_t i; i < sizeof switches / sizeof *switches; ++i)
{
uint8_t switch_value = (*switches[i].ppin >> switches[i].offset) & 1;
/* Work with switch_value here ... */
}
}

How to write only 12 bits to a char array in C?

I'm trying to implement a FAT12 file system in which there's a FAT table data structure which is an unsigned char array. I need to write a function which given an array index would write a value to the next 12 bits (because it's FAT12) which is quite tricky because part of the value needs to go to one byte and the other part needs to go the half of the second byte.
This is the get value function I came up with:
//FAT is the unsigned char array
int GetFatEntry(int FATindex, unsigned char * FAT) {
unsigned int FATEntryCode; // The return value
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
if (FATindex % 2 == 1){ // If the index is odd
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode >>= 4; // Extract the high-order 12 bits
}
else{ // If the index is even
FATEntryCode = ((unsigned char)(&FAT[FatOffset])[0] + (((unsigned char)(&FAT[FatOffset])[1]) << 8));
FATEntryCode &= 0x0fff; // Extract the low-order 12 bits
}
return FATEntryCode;
}
I'm struggling to come up with the function which would set a value given a FATindex. I would appreciate any suggestions.
This seems to work. The data that should be written should be in the first 12 bits of data
void WriteFatEntry(int FATindex, unsigned char * FAT, unsigned char data[2]) {
// Calculate the offset of the WORD to get
int FatOffset = ((FATindex * 3) / 2);
unsigned char d;
if (FATindex % 2 != 0){ // If the index is odd
// Copy from data to d and e, and shift everything so that second half of
// e contains first half of data[1], and first half of e contains second
// half of data[0], while second half of d contains first half of data[0].
// First half of d contains a copy of first four bits in FAT[FatOffset]
// so that nothing changes when it gets written
unsigned char e=data[1];
e>>=4;
d=data[0];
e|=(d<<4) & 0b11110000;
d>>=4;
d |= FAT[FatOffset] & 0b11110000;
FAT[FatOffset]=d;
FAT[FatOffset+1] = e;
}
else{ // If the index is even
d = data[1] & 0b11110000;
d |= FAT[FatOffset+1] & 0b00001111;
FAT[FatOffset] = data[0];
FAT[FatOffset+1] = d;
}
}
#include <stdio.h>
#if 1 /* assuming MSB first */
#define MSB (idx)
#define LSB (idx+1)
#else /* assuming LSB first */
#define MSB (idx+1)
#define LSB (idx)
#endif
unsigned fat_getval(unsigned char * tab, unsigned num)
{
unsigned idx;
unsigned val;
idx = num + num/2;
val = (tab[MSB] <<8 ) + (tab[idx+1] ) ;
if (num %2 ==0) val >>= 4;
return val & 0xfff;
}
void fat_putval(unsigned char * tab, unsigned slot, unsigned val)
{
unsigned idx;
idx = slot + slot/2;
if (slot %2 ==0) { /* xyz_ */
val <<= 4;
val |= tab[LSB] & 0xf;
}
else { /* _xyz */
val |= (tab[MSB] & 0xf0) << 8;
}
tab[MSB] = val >>8;
tab[LSB] = val &0xff;
}
#undef MSB
#undef LSB
unsigned char fattable[] = "\x01\x23\x45\x67\x89\xab"; // 12 nibbles
int main(void)
{
unsigned idx, ret;
for (idx = 0; idx < 6; idx++) { // 6 bytes -> 12 nibbles */
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(0,0xabc):\n");
fat_putval(fattable, 0, 0xabc);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Put(3,0xdef):\n");
fat_putval(fattable, 3, 0xdef);
for (idx = 0; idx < 6; idx++) {
printf(" %02x", fattable[idx] );
}
printf("\n");
printf("Get(0 to 4):\n");
for (idx = 0; idx < 4; idx++) { // 12 / 3 ~> 4 * 12bit entries
ret = fat_getval( fattable, idx);
printf("%u := %x\n", idx, ret );
}
printf("\n");
return 0;
}

endian-independent base64_encode/decode function

I was googling around for these two C functions that I happen to need, and the cleanest I came across was http://fm4dd.com/programming/base64/base64_stringencode_c.htm But it looks to me like the following little part of it...
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
}
...is going to be endian-dependent (ditto a corresponding encodeblack() that you can see at the above url). But it's otherwise nice and clean, unlike some of the others: one had three of its own header files, another called its own special malloc()-like function, etc. Anybody know of a nice, small, clean (no headers, no dependencies, etc) version, like this one, that's more architecture-independent?
Edit reason I'm looking for this is that base64_encode() will be done in a php script that's part of an html page, passing that encoded string to an executed cgi program on a far-away box. And that cgi then has to base64_decode() it. So architecture-independence is just an added safety, just in case the cgi's running on a non-intel big-endian box (intel's little).
Edit as per comment below, here's the complete code along with a few changes I made...
/* downloaded from...
http://fm4dd.com/programming/base64/base64_stringencode_c.htm */
/* ------------------------------------------------------------------------ *
* file: base64_stringencode.c v1.0 *
* purpose: tests encoding/decoding strings with base64 *
* author: 02/23/2009 Frank4DD *
* *
* source: http://base64.sourceforge.net/b64.c for encoding *
* http://en.literateprograms.org/Base64_(C) for decoding *
* ------------------------------------------------------------------------ */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* ---- Base64 Encoding/Decoding Table --- */
char b64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
/* decodeblock - decode 4 '6-bit' characters into 3 8-bit binary bytes */
void decodeblock(unsigned char in[], char *clrstr) {
unsigned char out[4];
out[0] = in[0] << 2 | in[1] >> 4;
out[1] = in[1] << 4 | in[2] >> 2;
out[2] = in[2] << 6 | in[3] >> 0;
out[3] = '\0';
strncat(clrstr, out, sizeof(out));
} /* --- end-of-function decodeblock() --- */
char *base64_decode(char *b64src /*, char *clrdst */) {
static char clrdstbuff[8192];
char *clrdst = clrdstbuff;
int c, phase, i;
unsigned char in[4];
char *p;
clrdst[0] = '\0';
phase = 0; i=0;
while(b64src[i]) {
c = (int) b64src[i];
if(c == '=') {
decodeblock(in, clrdst);
break; }
p = strchr(b64, c);
if(p) {
in[phase] = p - b64;
phase = (phase + 1) % 4;
if(phase == 0) {
decodeblock(in, clrdst);
in[0]=in[1]=in[2]=in[3]=0; }
} /* --- end-of-if(p) --- */
i++;
} /* --- end-of-while(b64src[i]) --- */
return ( clrdstbuff );
} /* --- end-of-function base64_decode() --- */
/* encodeblock - encode 3 8-bit binary bytes as 4 '6-bit' characters */
void encodeblock( unsigned char in[], char b64str[], int len ) {
unsigned char out[5];
out[0] = b64[ in[0] >> 2 ];
out[1] = b64[ ((in[0] & 0x03) << 4) | ((in[1] & 0xf0) >> 4) ];
out[2] = (unsigned char) (len > 1 ? b64[ ((in[1] & 0x0f) << 2) |
((in[2] & 0xc0) >> 6) ] : '=');
out[3] = (unsigned char) (len > 2 ? b64[ in[2] & 0x3f ] : '=');
out[4] = '\0';
strncat(b64str, out, sizeof(out));
} /* --- end-of-function encodeblock() --- */
/* encode - base64 encode a stream, adding padding if needed */
char *base64_encode(char *clrstr /*, char *b64dst */) {
static char b64dstbuff[8192];
char *b64dst = b64dstbuff;
unsigned char in[3];
int i, len = 0;
int j = 0;
b64dst[0] = '\0';
while(clrstr[j]) {
len = 0;
for(i=0; i<3; i++) {
in[i] = (unsigned char) clrstr[j];
if(clrstr[j]) {
len++; j++; }
else in[i] = 0;
} /* --- end-of-for(i) --- */
if( len ) {
encodeblock( in, b64dst, len ); }
} /* --- end-of-while(clrstr[j]) --- */
return ( b64dstbuff );
} /* --- end-of-function base64_encode() --- */
#ifdef TESTBASE64
int main( int argc, char *argv[] ) {
char *mysrc = (argc>1? argv[1] : "My bonnie is over the ocean ");
char *mysrc2 = (argc>2? argv[2] : "My bonnie is over the sea ");
char myb64[2048]="", myb642[2048]="";
char mydst[2048]="", mydst2[2048]="";
char *base64_enclode(), *base64_decode();
int testnum = 1;
if ( strncmp(mysrc,"test",4) == 0 )
testnum = atoi(mysrc+4);
if ( testnum == 1 ) {
strcpy(myb64,base64_encode(mysrc));
printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc,myb64);
strcpy(myb642,base64_encode(mysrc2));
printf("The string [%s]\n\tencodes into base64 as: [%s]\n",mysrc2,myb642);
printf("...\n");
strcpy(mydst,base64_decode(myb64));
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb64,mydst);
strcpy(mydst2,base64_decode(myb642));
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",myb642,mydst2);
} /* --- end-of-if(testnum==1) --- */
if ( testnum == 2 ) {
strcpy(mydst,base64_decode(mysrc2)); /* input is b64 */
printf("The string [%s]\n\tdecodes from base64 as: [%s]\n",mysrc2,mydst);
} /* --- end-of-if(testnum==2) --- */
if ( testnum == 3 ) {
int itest, ntests = (argc>2?atoi(argv[2]):999);
int ichar, nchars = (argc>3?atoi(argv[3]):128);
unsigned int seed = (argc>4?atoi(argv[4]):987654321);
char blanks[999] = " ";
srand(seed);
for ( itest=1; itest<=ntests; itest++ ) {
for ( ichar=0; ichar<nchars; ichar++ ) mydst[ichar] = 1+(rand()%255);
mydst[nchars] = '\000';
if ( strlen(blanks) > 0 ) strcat(mydst,blanks);
strcpy(myb64,base64_encode(mydst));
strcpy(mydst2,base64_decode(myb64));
if ( strcmp(mydst,mydst2) != 0 )
printf("Test#%d:\n\t in=%s\n\tout=%s\n",itest,mydst,mydst2);
} /* --- end-of-for(itest) --- */
} /* --- end-of-if(testnum==3) --- */
return 0;
} /* --- end-of-function main() --- */
#endif
No, it is not endian-dependent. Base64 in itself is 4 bytes to 3 bytes encoding, and doesn't care about the actual representation in memory. However, if you expect to transfer little/big endian data, you must normalize the endianness before encoding and after decoding.
That fragment just addresses all bytes independently. It would be endian-dependent if it loaded 4 bytes in uint32_t or so and using some bit twiddling produced an output that would be copied into the result buffer as is.
However that code is dangerously broken with its strncat and wouldn't work with embedded NUL bytes. Instead you should use something like
void decodeblock(unsigned char in[], unsigned char **clrstr) {
*((*clrstr) ++) = in[0] << 2 | in[1] >> 4;
*((*clrstr) ++) = in[1] << 4 | in[2] >> 2;
*((*clrstr) ++) = in[2] << 6 | in[3] >> 0;
}
which would work with embedded NULs.
In terms of endianess and having code compatible on platforms of differing endianess...
Firstly, there is the endianess of the processing platform hardware, the endianess of the data being transmitted and the endianess of the base64 encoding/decoding process.
The endianess of the base64 coding determines whether, to form the first character, we take the lower 6-bits of the first byte, or the upper 6-bits of the first byte. It appears base64 uses the latter which is big-endian format.
You will need your encoder/decoder to match regardless of the platform, so the code you show with the fixed bit-shifting is already going to work on either big or little endian platforms. You don't want your little endian platform to use little-endian bit shifting by placing the lower 6-bits of the first byte into the first encoded character. If it did, it would not be compatible with other platforms, so in this case you don't want platform dependent code.
However, when it comes to the data, you may need to convert the endianess, but do this with the binary data, not as part of the base64 coding or the encoded text.

Best Way to Simulate Logic Gates in C?

Hi I was wondering if anyone would be able to explain to me what is the best path to take if I wanted to simulate logic gates in a c program?
Lets say for example I create a program and use command line arguments
AND GATE
[console]% yourProgram 11001010 11110000
<console>% 11000000
If anyone could explain to me what the best route is to start with, I would greatly appreciate it. This is the code I have so far...
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int result = atoi(argv[1])&&atoi(argv[2]);
printf("Input 1 is %d\n",atoi(argv[1]));
printf("Input 2 is %d\n",atoi(argv[2]));
printf("Result is %c\n",result);
}
return 0;
In addition to the comment suggesting basic corrections, if you want to make it a bit more useful and flexible, you could calculate the most significant bit and then use that to format a simple binary print routine to examine your bitwise operation.
The primary concepts are taking the input as a string of binary digits and converting them to a number with strtoul (base 2), and then following &'ing the inputs together to obtain result it is just a matter of computing how many bytes to print out and whether to format a single byte into nibbles or simply separate multiple bytes.
#include <stdio.h>
#include <stdlib.h>
/* BUILD_64 */
#if defined(__LP64__) || defined(_LP64)
# define BUILD_64 1
#endif
/* BITS_PER_LONG */
#ifdef BUILD_64
# define BITS_PER_LONG 64
#else
# define BITS_PER_LONG 32
#endif
/* CHAR_BIT */
#ifndef CHAR_BIT
# define CHAR_BIT 8
#endif
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep);
static __always_inline unsigned long msbfls (unsigned long word);
int main (int argc, char **argv) {
if ( argc < 3) {
fprintf (stderr, "error: insufficient input. usage: %s b1 b1\n", argv[0]);
return 1;
}
/* input conversion and bitwise operation */
unsigned long b1 = strtoul (argv[1], NULL, 2);
unsigned long b2 = strtoul (argv[2], NULL, 2);
unsigned long result = b1 & b2;
/* variables to use to set binary print format */
unsigned char msb, msbmax, width, sepwidth;
msb = msbmax = width = sepwidth = 0;
/* find the greatest most significant bit */
msbmax = (msb = msbfls (b1)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (b2)) > msbmax ? msb : msbmax;
msbmax = (msb = msbfls (result)) > msbmax ? msb : msbmax;
msbmax = msbmax ? msbmax : 1;
/* set the number of bytes to print and the separator width */
width = (msbmax / CHAR_BIT + 1) * CHAR_BIT;
sepwidth = width > CHAR_BIT ? CHAR_BIT : CHAR_BIT/2;
/* print the output */
printf("\n Input 1 : %s\n", binstrfmt (b1, width, sepwidth, '-'));
printf(" Input 2 : %s\n", binstrfmt (b2, width, sepwidth, '-'));
printf(" Result : %s\n\n", binstrfmt (result, width, sepwidth, '-'));
return 0;
}
/** returns pointer to formatted binary representation of 'n' zero padded to 'sz'.
* returns pointer to string contianing formatted binary representation of
* unsigned 64-bit (or less ) value zero padded to 'sz' digits with char
* 'sep' placed every 'szs' digits. (e.g. 10001010 -> 1000-1010).
*/
char *binstrfmt (unsigned long n, unsigned char sz, unsigned char szs, char sep) {
static char s[2 * BITS_PER_LONG + 1] = {0};
char *p = s + 2 * BITS_PER_LONG;
unsigned char i;
for (i = 0; i < sz; i++) {
p--;
if (i > 0 && szs > 0 && i % szs == 0)
*p-- = sep;
*p = (n >> i & 1) ? '1' : '0';
}
return p;
}
/* return the most significant bit (MSB) for the value supplied. */
static __always_inline unsigned long msbfls(unsigned long word)
{
if (!word) return 0;
int num = BITS_PER_LONG - 1;
#if BITS_PER_LONG == 64
if (!(word & (~0ul << 32))) {
num -= 32;
word <<= 32;
}
#endif
if (!(word & (~0ul << (BITS_PER_LONG-16)))) {
num -= 16;
word <<= 16;
}
if (!(word & (~0ul << (BITS_PER_LONG-8)))) {
num -= 8;
word <<= 8;
}
if (!(word & (~0ul << (BITS_PER_LONG-4)))) {
num -= 4;
word <<= 4;
}
if (!(word & (~0ul << (BITS_PER_LONG-2)))) {
num -= 2;
word <<= 2;
}
if (!(word & (~0ul << (BITS_PER_LONG-1))))
num -= 1;
return num;
}
Example Output
$ ./bin/andargs 11001010 11110000
Input 1 : 1100-1010
Input 2 : 1111-0000
Result : 1100-0000
$ ./bin/andargs 1100101011110000 1111000011001010
Input 1 : 11001010-11110000
Input 2 : 11110000-11001010
Result : 11000000-11000000
Use this code. (for AND operation):
#include <stdio.h>
#include <stdlib.h>
int main( int argc, char *argv[] ) {
if( argc >= 3){
int i=0;
printf("1st i/p = %s\n2nd i/p = %s\n",argv[1],argv[2]);
for (i=0; argv[1][i]!='\0'; i++){ //this assumes there are 2 inputs, of equal size, having bits(1,0) as its digits
argv[1][i] = argv[1][i] & argv[2][i]; //modifies argv[1] to your required answer
}
printf("Answer: %s\n",argv[1]);
}
return 0;
}

combining MSB and LSB in short

I have a function that return 1 Byte
uint8_t fun();
the function should run 9 times , so I get 9 Byte I want to make the last8 one as 4 short values here what I've done but I'm not sure that the value that I get are correct :
char array[9];
.............
for ( i = 0; i< 9 ; i++){
array[i] = fun();
}
printf( " 1. Byte %x a = %d , b=%d c =%d \n" ,
array[0],
*(short*)&(array[1]),
*(short*)&(array[3]),
*(short*)&(array[5]),
*(short*)&(array[7]));
is that right ?
It's better to be explicit and join the 8-bit values into 16-bit values yourself:
uint8_t bytes[9];
uint16_t words[4];
words[0] = bytes[1] | (bytes[2] << 8);
words[1] = bytes[3] | (bytes[4] << 8);
words[2] = bytes[5] | (bytes[6] << 8);
words[3] = bytes[7] | (bytes[8] << 8);
The above assumes little-endian, by the way.
You will get alignement problems. Any pointer to a short can be seen as a pointer to char, but on non 8 bit machines, the inverse is not guaranteed.
IMHO, this would be safer :
struct {
char arr0;
union {
char array[8];
uint16_t sarr[4];
} u;
} s;
s.arr0 = fun();
for ( i = 0; i< 8 ; i++){
s.u.array[i] = fun();
}
printf( " 1. Byte %x a = %d , b=%d c =%d d=%d\n" ,
s.arr0,
s.u.sarr[0],
s.u.sarr[1],
s.u.sarr[2],
s.u.sarr[3]);
But I suppose you deal correctly with endianness on your machine and know how the conversion 2 chars <=> 1 short works ...
Try using struct to arrange the data and shift operations to convert for enianism.
// The existence of this function is assumed from the question.
extern unsigned char fun(void);
typedef struct
{
unsigned char Byte;
short WordA;
short WordB;
short WordC;
short WordD;
} converted_data;
void ConvertByteArray(converted_data* Dest, unsigned char* Source)
{
Dest->Byte = Source[0];
// The following assume that the Source bytes are MSB first.
// If they are LSB first, you will need to swap the indeces.
Dest->WordA = (((short)Source[1]) << 8) + Source[2];
Dest->WordB = (((short)Source[3]) << 8) + Source[4];
Dest->WordC = (((short)Source[5]) << 8) + Source[6];
Dest->WordD = (((hshort)Source[7]) << 8) + Source[8];
}
int main(void)
{
unsigned char array[9];
converted_data convertedData;
// Fill the array as per the question.
int i;
for ( i = 0; i< 9 ; i++)
{
array[i] = fun();
}
// Perform the conversion
ConvertByteArray(&convertedData, array);
// Note the use of %h not %d to specify a short in the printf!
printf( " 1. Byte %x a = %h , b=%h c =%h d =%h\n",
(int)convertedData.Byte, // Cast as int because %x assumes an int.
convertedData.WordA,
convertedData.WordB,
convertedData.WordC,
convertedData.WordD );
return 0;
}

Resources