Reputation: 61515
I am trying to read in an input file 64 bits at a time, then do some calculations on those 64 bits, the problem is I need to convert the ascii text to hexadecimal characters. I have searched around but none of the answers posted seem to work for my situation.
Here is what I have:
int main(int argc, int * argv)
{
char buffer[9];
FILE *f;
unsigned long long test;
if(f = fopen("input2.txt", "r"))
{
while( fread(buffer, 8, 1, f) != 0) //while not EOF read 8 bytes at a time
{
buffer[8] = '\0';
test = strtoull(buffer, NULL, 16); //interpret as hex
printf("%llu\n", test);
printf("%s\n", buffer);
}
fclose(f);
}
}
For an input like this:
"testing string to hex conversion"
I get results like this:
0
testing
0
string t
0
o hex co
0 nversion
Where I would expect:
74 65 73 74 69 6e 67 20 <- "testing" in hex
testing
73 74 72 69 6e 67 20 74 <- "string t" in hex
string t
6f 20 68 65 78 20 63 6f <- "o hex co" in hex
o hex co
6e 76 65 72 73 69 6f 6e <- "nversion" in hex
nversion
Can anyone see where I misstepped?
Upvotes: 0
Views: 3096
Reputation: 4093
Consider using limits.h as well.
I went a bit overboard but perhaps some of this fits:
Edit: [
Ehrmf. Perhaps a define of BITS_ULL is more fitting to your quest.
I.e. something in the direction of:
#define BITS_ULL (sizeof(unsigned long long) * CHAR_BIT)
#define BYTE_ULL (sizeof(unsigned long long))
And then read BYTE_ULL bytes, but make shure to check size of read bytes and not if it is -1 as latter could be a smash. I'm a bit unsure what you mean by "calculations" on read bits.
You could read BYTE_ULL bytes and cast to unsigned long long by address of buffer[0], or bit shift taking byte order into consideration. Or former and sort bytes with char pointer.
Also note that I have used len instead of null terminated / C string.
Oh, this is lots of fun :) - I'm learning, and this kind of hacking is heaven.
]
#include <stdio.h>
#include <limits.h> /* BITS */
#include <ctype.h> /* isprint() */
#define CHUNK_BITS 62
#define CHUNK_CHAR (CHUNK_BITS / CHAR_BIT)
#define HEX_WIDTH 2
/* print len hex values of s, separate every sep byte with space,
* but do not add trailing space. */
void prnt_cshex(const char *s, int len, int sep)
{
const unsigned char *p = (const unsigned char*)s;
int i;
for (i = 1; i <= len; ++p, ++i)
fprintf(stdout,
"%02x"
"%s",
*p,
(i < len && !((i)%sep) ? " " : ""));
}
/* Print len bytes of s, print dot if !isprint() */
void prnt_csbytes(const char *s, int len)
{
int i = 0;
for (i = 0; i < len; ++s, ++i)
fprintf(stdout,
"%c",
(isprint(*s) ? *s : '.'));
}
/* Pass file as first argument, if none, use default "input.txt" */
int main(int argc, char *argv[])
{
const char *fn = "input.txt";
FILE *fh;
char buffer[CHUNK_CHAR];
const char *p = &buffer[0];
size_t k;
if (argc > 1)
fn = argv[1];
if ((fh = fopen(fn, "rb")) == NULL) {
fprintf(stderr, " * Unable to open \"%s\"\n", fn);
goto fail_1;
}
fprintf(stdout,
"Processing \"%s\"\n"
"Chunks of %d bytes of %d bits = %d bits\n",
fn,
CHUNK_CHAR, CHAR_BIT, CHUNK_CHAR * CHAR_BIT);
if (CHUNK_BITS != CHUNK_CHAR * CHAR_BIT) {
fprintf(stdout,
"%d bits chunk requested. Won't fit, trunkated to\n"
"%d * %d = %d\n"
"%d bits short.\n\n",
CHUNK_BITS,
CHUNK_CHAR, CHAR_BIT, CHUNK_BITS / CHAR_BIT * CHAR_BIT,
CHUNK_BITS - CHUNK_CHAR * CHAR_BIT);
}
while ((k = fread(buffer, 1, CHUNK_CHAR, fh)) == CHUNK_CHAR) {
prnt_cshex(p, CHUNK_CHAR, HEX_WIDTH); /* Print as hex */
printf(" ");
prnt_csbytes(p, CHUNK_CHAR); /* Print as text */
putchar('\n');
}
if (!feof(fh)) {
fprintf(stderr, " * Never reached EOF;\n");
goto fail_close;
}
/* If input file does not fit in to CHUNK, report this */
if (k > 0) {
printf("%d byte tail: '", k);
prnt_csbytes(p, k);
printf("'\n");
}
fclose(fh);
return 0;
fail_close:
fclose(fh);
fail_1:
return 1;
}
Upvotes: 1
Reputation: 55533
strtoull()
Converts a string that is in hex format (e.g. 0xFFAABBEE) to it's integer format.
What you really need is a function to convert a string to a hex string, like this:
char *strToHex(const char *input)
{
char *output = calloc(1, strlen(input) * 3 + 1);
char *o = output;
int i = 0;
for (; input[i] != '\0'; o += 3, i++)
{
sprintf(o, "%.2X ", input[i]);
}
// don't forget to free output!
return output;
}
Upvotes: 1
Reputation: 7320
You can try doing getchar()
8 times (each value returned by getchar
is 1 byte = 8 bits) and then using atoh
or something - I'm not even sure if atoh
exists, but barring that do something like atoi
followed by itoh
.. or write your own function to convert it.
Upvotes: 0
Reputation: 5456
The function strtoull
(with 16) converts HEX string to number, not ASCII char to HEX string.
To print a char in HEX form, you should do something like printf("%02x ",buffer[0]);
Upvotes: 1
Reputation: 20764
strtoull converts a number represented by a string into an unsigned long long. Your input to this function (eg. string "testing") makes no sense as it has to be a number.
printf("%llu\n", strtoull("123")); // prints 123
To get the result you want, you have to print each character of the string like this:
for(int i=0; i<8; i++)
printf( "%02X ", (unsigned char) buffer[i]);
Upvotes: 1