how to handle char to hex conversion when result is only one digit/letter? - xor

I am trying to learn to work with XOR, hex, ord and char.
I ran into trouble, when my XOR produced a hex that had only one digit, I solved it dby checking with an if an adding a zero to make it a two digit hex, otherwise when i 'joined' the list, I was missing elements and could not use it for further XOR's.
Am I doing something wrong, or this is the way it works?
s0='Hello World'
s1='supersecret'
def strxor (s0, s1):
cypher_text=[]
for i in range(0,len(s0)):
l=hex(ord(s0[i])^ord(s1[i]))
if len(l)==3:
l=l[0:2]+'0'+l[2:]
cypher_text.append(l[2:])
return ''.join(cypher_text)
cypher_text=3b101c091d53320c000910
without the correction
cypher_text=3b101c91d5332c0910

You are not doing something wrong. This is the way it works.
C version below confirms your results.
#include <string.h>
void testss() {
const char *s0 = "Hello World";
const char *s1 = "supersecret";
for (unsigned i = 0; i<strlen(s0); i++) {
printf("%02X", ((unsigned char) s0[i]) ^ ((unsigned char) s1[i]));
}
printf("\n");
// 3B101C091D53320C000910 testss() output
// 3b101c091d53320c000910 OP cypher_text
// 3b101c 91d5332 c 0 910 OP uncorrected cypher_text (my spaces inserted)
}

Related

Conversion of integer to char array in C

I'm developing an ARM embedded application. I'm kind of stuck on a silly problem - I have an array of unsigned 8-bit integers:
uint8_t days[42] = { 0 };
It's initialized with some data - the initialization algorithm introduces a lot of variables confusing and irrelevant to the problem, so I will not repost it here. I see this array in the debugger variable watch, and I'm certain it is filled with integer values from 0 to 31.
I'd like to take any element of this array, say 15th, and convert it to char* so that it can be displayed on my LCD screen. I rewrite it using sprintf function:
char d[3] = { '0', '0', '0' };
sprintf(d, "%d", days[15]);
Just one note: no, I can't use the stdlib itoa() function, because it does not conform to MISRA-C standards, which I am obliged to follow.
As a result, I only get a binary zero value in my d buffer. Any ideas?
For MISRA-C compliance, you can certainly not use sprintf() or anything else from stdio.h either. You generally want to avoid sprintf like the plague on any embedded system anyhow.
Writing a simple decimal integer to string conversion routine is quite basic stuff... here's my attempt of a MISRA-C (2004 and 2012) compatible version:
#include <stdint.h>
void dec_to_str (char* str, uint32_t val, size_t digits);
int main (void)
{
char str[3u + 1u]; // assuming you want null terminated strings?
dec_to_str(str, 31u, 3u);
return 0;
}
void dec_to_str (char* str, uint32_t val, size_t digits)
{
size_t i=1u;
for(; i<=digits; i++)
{
str[digits-i] = (char)((val % 10u) + '0');
val/=10u;
}
str[i-1u] = '\0'; // assuming you want null terminated strings?
}
Note: the uint32_t variable could get swapped out for an uint8_t, but then you need to add type casts all over the place, to prevent implicit type promotions, as required by MISRA. The code will then turn really ugly, like this:
str[digits-i] = (char)(uint8_t)((uint8_t)(val % 10u) + '0');
The only sane thing to do then, is to split that mess into several lines:
uint8_t ch = (uint8_t)(val % 10u);
ch = (uint8_t)(ch + '0');
str[digits-i] = (char)ch;
#include "stdafx.h"
#include <stdio.h>
int days[2] = {12,14};
char d[3] = {'0', '0', 0};
int _tmain(int argc, _TCHAR* argv[])
{
d[0] = days[1] / 10 + 0x30; // convert 10's digit to ascii
d[1] = days[1] % 10 + 0x30; // convert 1's digit to ascii
// Debugging help
printf(d);
getchar();
return 0;
}

Incorrect result for %p when implementation printf

I'm working on my own printf code and I got 2 problems that I hoped you might be able to help me with.
The first one is with the %p option :
This option gives me the pointer address of a void* in hex form.
So what I'm doing is this :
void printp(void *thing)
{
dectohex((long)&thing, 1);
}
where dectohex is just a function converting a decimal to hex.
The result will always be correct, except for the last 3 characters. Always. For example :
me : 0x5903d8b8 , printf : 0x5903da28.
And these characters don't change very often, whereas the other part changes at each call like its supposed to.
The other problem I have is with the %O option. I can't manage to convert a signed int to an unsigned int. printf prints huge numbers for negative int's, and no casts seems to work since I wouldn't have the place to store it anyways.
EDIT:
Thanks sooo much for the answers, so apparently for the first problem i was just a little stupid. For the second question i'm gonna try the different solutions you gave me and update you if i manage to do it.
Again thanks so much for your time and patience, and sorry for the delay in my response, i checked the email alert for any answer but it doesn't work apparently.
REEDIT: After reading your answers to my second question more carefully, i think some of you think i asked about %o or %0. I was really talking about %O as in %lo i think. In the man it tells me "%O : The long int argument is converted to unsigned octal". My problem is before converting the long int to octal, i need to convert it to something unsigned.
If uintptr_t/intmax_t is defined (it is optional), convert the pointer to that integer type and then print.
Otherwise, if sizeof(uintmax_t) >= sizeof (void *) , convert to uintmax_t. uintmax_t is a required type, but may not be sufficiently large.
void printp(void *thing) {
uintptr_t j = (uintptr_t) thing;
char lst[(sizeof j * CHAR_BIT + 3)/ 4 + 1]; // Size needed to print in base 16
char *p = &lst[sizeof lst] - 1;
*p = '\0';
do {
p--;
*p = "0123456789ABCDEF"[j%16];
j /= 16;
} while (p > lst);
fputs(p, stdout);
}
The %O problem is likely a sign extension issue. (#mafso) Insure valuables used are unsigned, like unsigned and unsigned long. Without seeing the code difficult to know for sure.
About the first issue you're having, just to make sure, you want to print the address of thing (note that thing itself is a pointer) or the address of the origin of thing (the pointer to the pointer thing)?
You're currently printing the pointer to the pointer.
Change
dectohex((long)&thing, 1);
to
dectohex((long)thing, 1);
if that is the case.
About the %O problem, can you give a code example?
You need "unsigned long long" for your cast.
Pointers are unsigned, but long is signed.
The number of bits in any data type is implementation-dependent; however these days it is common for long and unsigned long to be 32 bits.
edit: to be more clear, you can't count on anything about the number of bits in C, C++ or Objective-C, it's always implementation-dependent. For example it was at one time common to have nine bit bytes and thirty-six bit words. That's why the Internet Protocols always specify "octets" - groups of eight bites - rather then "bytes".
That's one advantage of Java, in that the number of bits in each data type is strictly definited.
About your second question regarding zero-padding and negative integers, which seems entirely separate from the first question about hex output. You can handle negative numbers like this (although in 32-bit it does not work with the value -2147483648 which is 0x80000000).
#include <stdio.h>
#define MAXDIGITS 21
int printint(int value, int zeropad, int width)
{
int i, z, len = 0;
char strg [MAXDIGITS+1];
strg [MAXDIGITS] = 0;
if (value < 0) {
value = - value;
putchar ('-');
len = 1;
}
for (i=MAXDIGITS-1; i>=0; i--) {
strg [i] = '0' + value % 10;
if ((value /= 10) == 0)
break;
}
if (zeropad)
for (z=MAXDIGITS-i; z<width; z++) {
putchar ('0');
len++;
}
for (; i<MAXDIGITS; i++) {
putchar (strg [i]);
len++;
}
return len;
}
int main (int argc, char *argv[])
{
int num = 0, len;
if (argc > 1) {
sscanf (argv[1], "%d", &num);
// try the equivalent of printf("%4d, num);
len = printint (num, 0, 4);
printf (" length %d\n", len);
// try the equivalent of printf("%04d, num);
len = printint (num, 1, 4);
printf (" length %d\n", len);
}
return 0;
}

Array unwanted characters in C

Ok,I am beginner in C.I was thought that for a array to hold to characters in need to declare it as:
char a[10];
So I will have 10 elements from (0 to 9)
but it is not working.It is giving me unwanted characters.Can you tell me the problem is.My code:
#include<stdio.h>
#include<stdlib.h>
int main(void)
{
printf("%s",rand_string());
}
int rand_string(void)
{
srand(time(NULL));
char a[7];
int e;
int d;
a[0]='l';
a[1]='o';
a[2]='n';
a[3]='g';
a[4]=' ';
d=(rand()%6) + 97;
a[5]=d;
e=(rand()%10) + 48;
a[6]=e;
printf("\n%s\n",a);
return a;
}
I get results like:
long f99
|/
What I expect:
long f9
Ok so in total I have 4 questions:
*How to fix the problem of unwanted characters and why is it giving unwated characters?
*Is my way of generating random numbers with limit ok?
*how to write the first 4 letters "long" in one line rather that for each line in an array?
*How to combine 2 strings?
You need to NULL terminate your string. Extend the array by one and add a[7] = 0; in there and you'll be set.
Editorial note: Your program has another big problem in that you are returning a pointer to a local variable. You may want to change rand_string to fill in a buffer provided by main instead. Here's a quick example with both of these modifications:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void rand_string(char a[8])
{
srand(time(NULL));
int e;
int d;
a[0]='l';
a[1]='o';
a[2]='n';
a[3]='g';
a[4]=' ';
d=(rand()%6) + 97;
a[5]=d;
e=(rand()%10) + 48;
a[6]=e;
a[7]=0;
printf("\n%s\n",a);
}
int main(void)
{
char buffer[8];
rand_string(buffer);
printf("%s", buffer);
return 0;
}
The first question is already answered by Carl Norum.
Is my way of generating random numbers with limit ok?
Yes, but defining a function would be nice, wouldn't it? Calling like a[0] = randomBetween(97, 102); is much more readable though.
EDIT: As in a comment above stated: you even could write
a[0] = randomBetween('a', 'f'); Just a little bit more readable ;-)
how to write the first 4 letters "long" in one line rather that for each line in an array?
There is no way, instead you could copy the elements in a loop or using a function like memcpy, strcpy. Taking your question wordly:
a[0] = 'l'; a[1] = 'o'; a[2] = 'n'; a[3] = 'g';
But this is not what you want, I guess :-) See also the strcpy-example below.
How to combine 2 strings?
Again, either using a loop or the functions mentioned above:
char *first = "Hello ";
char *second = "World";
char combined[12];
int currentIndex = 0, i = 0;
// copy characters from "first" as long we did not find a \0
while(first[i] != 0)
combined[currentIndex++] = first[i++];
i = 0;
// copy characters from "second" as long we did not find a \0
while(second[i] != 0)
combined[currentIndex++] = second[i++];
// finally don't forget to null-terminate!
combined[currentIndex] = 0;
Using e.g. strcpy is much easier ;-)
char *first = "Hello ";
char *second = "World";
char combined[12];
strcpy(combined, first);
strcpy(&combined[6], second);
What are we doing here? The first strcpy-call copies simply "first" to "combined". But the second calls seems to be interesting. There we copy "second" to the 7th position (start counting from 0, therefor 6). At this position was the \0-character after the first function call. But we don't want the string to end here, so we override it with the first character of the second string. One nice thing is that strcpy automatically copies the terminating \0 at the end. Quite simple, isn't it?

How to manually convert decimal value to hexadecimal string in C?

n.b. I know that this question has been asked on StackOverflow before in a variety of different ways and circumstances, but the search for the answer I seek doesn't quite help my specific case. So while this initially looks like a duplicate of a question such as How can I convert an integer to a hexadecimal string in C? the answers given, are accurate, but not useful to me.
My question is how to convert a decimal integer, into a hexadecimal string, manually. I know there are some beat tricks with stdlib.h and printf, but this is a college task, and I need to do it manually (professor's orders). We are however, permitted to seek help.
Using the good old "divide by 16 and converting the remainder to hex and reverse the values" method of obtaining the hex string, but there must be a big bug in my code as it is not giving me back, for example "BC" for the decimal value "188".
It is assumed that the algorithm will NEVER need to find hex values for decimals larger than 256 (or FF). While the passing of parameters may not be optimal or desirable, it's what we've been told to use (although I am allowed to modify the getHexValue function, since I wrote that one myself).
This is what I have so far:
/* Function to get the hex character for a decimal (value) between
* 0 and 16. Invalid values are returned as -1.
*/
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
/* Function asciiToHexadecimal() converts a given character (inputChar) to
* its hexadecimal (base 16) equivalent, stored as a string of
* hexadecimal digits in hexString. This function will be used in menu
* option 1.
*/
void asciiToHexadecimal(char inputChar, char *hexString)
{
int i = 0;
int remainders[2];
int result = (int)inputChar;
while (result) {
remainders[i++] = result % 16;
result /= (int)16;
}
int j = 0;
for (i = 2; i >= 0; --i) {
char c = getHexValue(remainders[i]);
*(hexString + (j++)) = c;
}
}
The char *hexString is the pointer to the string of characters which I need to output to the screen (eventually). The char inputChar parameter that I need to convert to hex (which is why I never need to convert values over 256).
If there is a better way to do this, which still uses the void asciiToHexadecimal(char inputChar, char *hexString) function, I am all ears, other than that, my debugging seems to indicate the values are ok, but the output comes out like \377 instead of the expected hexadecimal alphanumeric representation.
Sorry if there are any terminology or other problems with the question itself (or with the code), I am still very new to the world of C.
Update:
It just occurred to me that it might be relevant to post the way I am displaying the value in case its the printing, and not the conversion which is faulty. Here it is:
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
(Everything in this code snip-pit works except for hexString)
char getHexValue(int value)
{
if (value < 0) return -1;
if (value > 16) return -1;
if (value <= 9) return (char)value;
value -= 10;
return (char)('A' + value);
}
You might wish to print out the characters you get from calling this routine for every value you're interested in. :) (printf(3) format %c.)
When you call getHexValue() with a number between 0 and 9, you return a number between 0 and 9, in the ASCII control-character range. When you call getHexValue() with a number between 10 and 15, you return a number between 65 and 75, in the ASCII letter range.
The sermon? Unit testing can save you hours of time if you write the tests about the same time you write the code.
Some people love writing the tests first. While I've never had the discipline to stick to this approach for long, knowing that you have to write tests will force you to write code that is easier to test. And code that is easier to test is less coupled (or 'more decoupled'), which usually leads to fewer bugs!
Write tests early and often. :)
Update: After you included your output code, I had to comment on this too :)
char* binaryString = (char*) malloc(8);
char* hexString = (char*) malloc(2);
asciiToBinary(*(asciiString + i), binaryString);
asciiToHexadecimal(*(asciiString + i), hexString);
printf("%6c%13s%9s\n", *(asciiString + i), binaryString, hexString);
hexString has been allocated one byte too small to be a C-string -- you forgot to leave room for the ASCII NUL '\0' character. If you were printing hexString by the %c format specifier, or building a larger string by using memcpy(3), it might be fine, but your printf() call is treating hexString as a string.
In general, when you see a
char *foo = malloc(N);
call, be afraid -- the C idiom is
char *foo = malloc(N+1);
That +1 is your signal to others (and yourself, in two months) that you've left space for the NUL. If you hide that +1 in another calculation, you're missing an opportunity to memorize a pattern that can catch these bugs every time you read code. (Honestly, I found one of these through this exact pattern on SO just two days ago. :)
Is the target purely hexadecimal, or shall the function be parametizable. If it's constrained to hex, why not exploit the fact, that a single hex digit encodes exactly four bits?
This is how I'd do it:
#include <stdlib.h>
#include <limits.h> /* implementation's CHAR_BIT */
#define INT_HEXSTRING_LENGTH (sizeof(int)*CHAR_BIT/4)
/* We define this helper array in case we run on an architecture
with some crude, discontinous charset -- THEY EXIST! */
static char const HEXDIGITS[0x10] =
{'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
void int_to_hexstring(int value, char result[INT_HEXSTRING_LENGTH+1])
{
int i;
result[INT_HEXSTRING_LENGTH] = '\0';
for(i=INT_HEXSTRING_LENGTH-1; value; i--, value >>= 4) {
int d = value & 0xf;
result[i] = HEXDIGITS[d];
}
for(;i>=0;i--){ result[i] = '0'; }
}
int main(int argc, char *argv[])
{
char buf[INT_HEXSTRING_LENGTH+1];
if(argc < 2)
return -1;
int_to_hexstring(atoi(argv[1]), buf);
puts(buf);
putchar('\n');
return 0;
}
I made a librairy to make Hexadecimal / Decimal conversion without the use of stdio.h. Very simple to use :
char* dechex (int dec);
This will use calloc() to to return a pointer to an hexadecimal string, this way the quantity of memory used is optimized, so don't forget to use free()
Here the link on github : https://github.com/kevmuret/libhex/
You're very close - make the following two small changes and it will be working well enough for you to finish it off:
(1) change:
if (value <= 9) return (char)value;
to:
if (value <= 9) return '0' + value;
(you need to convert the 0..9 value to a char, not just cast it).
(2) change:
void asciiToHexadecimal(char inputChar, char *hexString)
to:
void asciiToHexadecimal(unsigned char inputChar, char *hexString)
(inputChar was being treated as signed, which gave undesirable results with %).
A couple of tips:
have getHexValue return '?' rather than -1 for invalid input (make debugging easier)
write a test harness for debugging, e.g.
int main(void)
{
char hexString[256];
asciiToHexadecimal(166, hexString);
printf("hexString = %s = %#x %#x %#x ...\n", hexString, hexString[0], hexString[1], hexString[2]);
return 0;
}
#include<stdio.h>
char* inttohex(int);
main()
{
int i;
char *c;
printf("Enter the no.\n");
scanf("%d",&i);
c=inttohex(i);
printf("c=%s",c);
}
char* inttohex(int i)
{
int l1,l2,j=0,n;
static char a[100],t;
while(i!=0)
{
l1=i%16;
if(l1>10)
{
a[j]=l1-10+'A';
}
else
sprintf(a+j,"%d",l1);
i=i/16;
j++;
}
n=strlen(a);
for(i=0;i<n/2;i++)
{
t=a[i];
a[i]=a[n-i-1];
a[n-i-1]=t;
}
//printf("string:%s",a);
return a;
//
}
In complement of the other good answers....
If the numbers represented by these hexadecimal or decimal character strings are huge (e.g. hundreds of digits), they won't fit in a long long (or whatever largest integral type your C implementation is providing). Then you'll need bignums. I would suggest not coding your own implementation (it is tricky to make an efficient one), but use an existing one like GMPlib

How to convert integer to char without C library?

In a c programming exercise I am asked to convert an int to char without using the C library.
Any idea how to go about it?
edit: what I mean by int is the built in C/C++ type
Thanks.
Cast it?
char c = (char)i;
Or maybe you meant this?
char c = (char)('0' + i);
I'm sure this isn't what you mean though... I'm guessing you want to create a string (char array)? If so, then you need to convert it one digit at a time starting with the least significant digit. You can do it recursively, in pseudo-code:
function convertToString(i)
if i < 10
return convertDigitToChar(i)
else
return convertDigitToString(i / 10) concat convertDigitToChar(i % 10)
Here / is integer division and % is integer modulo. You also need to handle negative numbers. This can be done by checking first if you have a negative number, calling the function on the aboslute value and adding the minus sign if necessary.
In C for performance you would probably implement this with a loop instead of using recursion, and by directly modifying the contents of a character array instead of concatenating strings.
If you really want a string:
#include <stdio.h>
char *tochar(int i, char *p)
{
if (i / 10 == 0) {
// No more digits.
*p++ = i + '0';
*p = '\0';
return p;
}
p = tochar(i / 10, p);
*p++ = i % 10 + '0';
*p = '\0';
return p;
}
int main()
{
int i = 123456;
char buffer[100];
tochar(i, buffer);
printf("i = %s\n", buffer);
}
For completeness, if the task is to convert int to string as anthares suspects, you can use Mark's second answer to convert each digit of the integer. To get each digit, you have to look into the division and modulo operators.

Resources