Hex to ascii in c using visual studio - c

I'm facing some issues while I use toascii() it converts any int to ascii, but not int < 10, it returens \x1 or \x2 and so but not the ascii symbol which it should represent. so, any help please.
My code be like:
char* PostUnpack()
{
char* InStr = "04214FABF666DCE7";
int Len = strlen(InStr);
int Count, OutCount = 0;
int IntToHex;
char HexToChr[3] = "";
char TempCnv;
char RetStr[20] = "" ;
for(Count = 0; Count < Len; Count++)
{
strncpy(HexToChr,&InStr[Count],2);
IntToHex = (int) strtol(HexToChr, NULL, 16);
TempCnv = IntToHex;
toascii(TempCnv);
RetStr[OutCount] = TempCnv;
strncpy(HexToChr, "", strlen(HexToChr));
Count++;
OutCount++;
}
return RetStr;
actually in debug it be like:
\x4!O«öfÜç
while it should be :
!O«öfÜç
because I don't want to print the out put, but I use the return value to be used by some encryption method, and now when I pass this incorrect return value it make an incorrect encryption.

As already pointed out, one of the issues may be that toascii(), although working as designed, is not be producing it's converted value in the way you expect. You must use the return value of the function to get the converted value. For example, as you have called it:
toascii(TempCnv);//the converted value is returned, and you are not capturing it.
^^^^
use either a direct assignment statement to capture the value like this:
char c = toascii(0x51); //example value should produce ASCII character 3
Or you can use the string function sprintf() to place the converted value into a variable:
char c = 0;
sprintf(c, "%c", toascii(0x51));
Also, the range of printable ASCII characters is 0x20 - 0x7E. There is a paper that discusses the problems that are encountered when attempting to work with non-printable characters here

heres one that works
char * conv(char * str)
{
int l = strlen(str);
char buff[3];
buff[2] = 0;
int oidx = 0;
char *out = malloc(l/2 + 1);
int i;
for( i = 0; i < l; )
{
buff[0]= str[i++];
buff[1] = str[i++];
long x = strtol(buff, 0,16);
out[oidx++] = x;
}
out[oidx] = 0;
return strdup(out);
}
int main(void) {
char* InStr = "04214FABF666DCE7";
char* ans = conv(InStr);
free(ans);
}
does not deal with odd length input. Note the allocation of return buffer and freeing by caller. And no check of malloc

It seems the point of toascii() is to limit a value to using at most 7 bits, i.e. toascii(x) is equivalent to x &= 127. This might not be what you expect.
See the documentation for details.

Related

Parse string to number in C

I tried to write a function to convert a string to an int:
int convert(char *str, int *n){
int i;
if (str == NULL) return 0;
for (i = 0; i < strlen(str); i++)
if ((isdigit(*(str+i))) == 0) return 0;
*n = *str;
return 1;
}
So what's wrong with my code?
*n = *str means:
Set the 4 bytes of memory that n points to, to the 1 byte of memory that str points to. This is perfectly fine but it's probably not your intention.
Why are you trying to convert a char* to an int* in the first place? If you literally just need to do a conversion and make the compiler happy, you can just do int *foo = (int*)bar where bar is the char*.
Sorry, I don't have the reputation to make this a comment.
The function definitely does not perform as intended.
Here are some issues:
you should include <ctype.h> for isdigit() to be properly defined.
isdigit(*(str+i)) has undefined behavior if str contains negative char values. You should cast the argument:
isdigit((unsigned char)str[i])
the function returns 0 if there is any non digit character in the string. What about "-1" and "+2"? atoi and strtol are more lenient with non digit characters, they skip initial white space, process an optional sign and subsequent digits, stopping at the first non digit.
the test for (i = 0; i < strlen(str); i++) is very inefficient: strlen may be invoked for each character in the string, with O(N2) time complexity. Use this instead:
for (i = 0; str[i] != '\0'; i++)
*n = *str does not convert the number represented by the digits in str, it merely stores the value of the first character into n, for example '0' will convert to 48 on ASCII systems. You should instead process every digit in the string, multiplying the value converted so far by 10 and adding the value represented by the digit with str[i] - '0'.
Here is a corrected version with your restrictive semantics:
int convert(const char *str, int *n) {
int value = 0;
if (str == NULL)
return 0;
while (*str) {
if (isdigit((unsigned char)*str)) {
value = value * 10 + *str++ - '0';
} else {
return 0;
}
}
*n = value;
return 1;
}
conversion of char* pointer to int*
#include
main()
{
char c ,*cc;
int i, *ii;
float f,*ff;
c = 'A'; /* ascii value of A gets
stored in c */
i=25;
f=3.14;
cc =&c;
ii=&i;
ff=&f;
printf("\n Address contained
in cc =%u",cc);
printf("\n Address contained
in ii =%u",ii);
printf(:\n Address contained
in ff=%u",ff);
printf(\n value of c= %c",
*cc);
printf(\n value of i=%d",
**ii);
printf(\n value of f=%f",
**ff);
}

Populating a buffer from the return of a method fails... ANSI C

The code I have is quite simple in one method I have this:
// This line has an Intellisense Error: Initialization with {...} expected for aggregate object
char str[] = GetBuffer(); // x 64 will give us 512 (sector sized buffer) ;
The GetBuffer metod is this:
char * GetBuffer(void)
{
int idx = 0;
int offset = 0;
char *buffer[512];
for(idx =0; idx < 64; idx ++)
{
// This line has an Itellisense Error: "Expected Expression"
buffer[offset + idx] = {"E","R","A","S","E","D"," ", " "};
offset += 8;
}
return *buffer;
}
Any ideas what's wrong with this?
All I am trying to do - is populate a buffer with 512 bytes which contain the following string repeated: "ERASED " This is ANSI C (not C++) and it has been so long since I coded in ANSI C - please help and be kind!
Using Visual Studio 2012
EDIT 1
Ok lots of things have been fixed thanks to you guys - but no full answer yet.
The str buffer holds 528 characters and not 512 and contains a lot of ERASED as expected but ends with
ýýýý««««««««îþîþ
Any ideas with this? And Oh boy I have a great deal of pure C reading to do - I have forgotten way too much!
You can't initialize an array with the return value from a function.
You could use a pointer instead of an array:
char *str = GetBuffer();
Or you could use strcpy() or a relative — but there are buffer overflow risks:
char str[512];
strcpy(str, GetBuffer());
Your GetBuffer() function also has a lot of problems.
char *GetBuffer(void)
{
int idx = 0;
int offset = 0;
char *buffer[512];
This should probably be char buffer[512];, but...
for(idx =0; idx < 64; idx ++)
{
// This line has an Itellisense Error: "Expected Expression"
buffer[offset + idx] = {"E","R","A","S","E","D"," ", " "};
You can't set arrays like this. And you needed double quotes because of the char *buffer[512] problem.
offset += 8;
}
return *buffer;
}
And you should not return a local variable — it is destroyed when the function returns so it can't be used afterwards.
You might write:
char *GetBuffer(void)
{
char *buffer = malloc(257);
if (buffer != 0)
{
int idx;
for (idx = 0; idx < 256; idx += 8)
strcpy(buffer+idx, "ERASED ");
}
return buffer;
}
There's a small layer of obfuscation going on with the hard-coded lengths and limits; they're correct, but the interconnections between the sizes are not obvious — and ideally, they should be:
strlen("ERASED ") == 8
256 = 32 * strlen("ERASED ")
257 = 32 * strlen("ERASED ") + 1 (the one is for the terminal null)
And then the calling code might be:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *str = GetBuffer();
if (str != 0)
{
printf("<<%s>>\n", str);
free(str);
}
return(0);
}
there is problem with your buffer creation. you'd malloc such that it's not reclaimed by the function invoke routine. Second, you can't do assignment like the line you encountered a Itellisense error.
You can use this:
#include "stdlib.h"
char * GetBuffer(void)
{
int i = 0, idx = 0;
const char * cstr_init = "ERASED ";
char *buffer = (char*)malloc(512);
for (idx = 0; idx < 512; idx+=8) {
for (i = 0; i < 8; i++) {
buffer[idx+i] = cstr_init[i];
}
}
return buffer;
}
There are several things wrong here.
In C, a character array can be initialized with an initializer list or a string literal. You cannot use the return value from a function to initialize the array. So
char str[] = GetBuffer();
will not work.
Also, char* buffer [512] is an array of 512 pointers to char, i.e., an array of 512 strings. buffer [offset + idx] would be one pointer to char. It can hold only one string, but you are trying to assign eight strings to it: "E", "R", etc. If you mean those to be chars and not strings, use single quotes: 'E', etc. However, even that won't work unless you allocate memory to the pointer so that it can hold the string.
As written, the array of pointers is allocated on the stack, so it goes out of scope when the function terminates. return *buffer would return the first string in the array of strings, but that's a local variable, so you're returning the dereferenced value of a pointer that is no longer in scope.
I think a simpler way to accomplish your goal is this:
char str [512] = {'\0'};
for (int i = 0; i < 511; i += 7)
strcat (str + i, "ERASED ");
It's not very general, but it does what you want.
Edited to reflect Jonathan Leffler's comment that strcat (str, "ERASED "), which is what I originally had, is inefficient.

Using atoi() in C to parse character array with binary values

I'm trying to convert a string of binary characters to an integer value.
For example: "100101101001" I would split it into four segments using a for loop then store it in array[4]. However whenever I use the function atoi(), I encounter a problem where it does not convert the character string properly if the string starts with "0".
An example would be "1001" = 1001, but if it is 0110 it would be converted to 110, also with 0001 it would be come only 1.
Here is the code that I made:
for(i = 0; i < strlen(store); i++)
{
bits[counter] = store [i];
counter++;
if(counter == 4)
{
sscanf(bits, "%d", &testing);
printf("%d\n", testing);
counter = 0;
}
}
The atoi() function only converts decimal numbers, in base 10.
You can use strtoul() to convert binary numbers, by specifying a base argument of 2. There is no need to "split" the string, and leading zeroes won't matter of course (as they shouldn't, 000102 is equal to 102):
const char *binary = "00010";
unsigned long value;
char *endp = NULL;
value = strtoul(binary, &endp, 2);
if(endp != NULL && *endp == '\0')
printf("converted binary '%s' to integer %lu\n", binary, value);
atoi() convert from char array to int and not to binary
you can use the following function
int chartobin(char *s, unsigned int *x) {
int len = strlen(s), bit;
*x = 0;
if(len>32 || len<1) return -1;
while(*s) {
bit = (*s++ - '0');
if((bit&(~1U))!=0) return -1;
if (bit) *x += (1<<(len-1));
len--;
}
return 0;
}
Tested and it works

How to fill a string with random (hex) characters?

I have a string (unsigned char) and i want to fill it with only hex characters.
my code is
unsigned char str[STR_LEN] = {0};
for(i = 0;i<STR_LEN;i++) {
sprintf(str[i],"%x",rand()%16);
}
Of course, when running this I get segfaulted
string is an array of char-s not unsigned char-s
you are using str[i] (which is of type unsigned char) as a 1st argument to sprintf, but it requires type char * (pointer).
This should be a little better:
char str[STR_LEN + 1];
for(i = 0; i < STR_LEN; i++) {
sprintf(str + i, "%x", rand() % 16);
}
The first argument to sprintf() should be a char*, but str[i] is a char: this is the cause of the segmentation fault. The compiler should have emitted a warning about this. gcc main.c, without specifying a high warning level, emitted the following:
warning: passing argument 1 of sprintf makes pointer from integer without a cast
A hex representation of a character can be 1 or 2 characters (9 or AB for example). For formatting, set the precision to 2 and the fill character to 0. Also need to add one character for the terminating null to str and set the step of the for loop to 2 instead of 1 (to prevent overwriting previous value):
unsigned char str[STR_LEN + 1] = {0};
int i;
for (i = 0; i < STR_LEN; i += 2)
{
sprintf(&str[i], "%02X", rand() % 16);
}
You could try something like this:
#include <stdio.h>
#include <stdlib.h>
#define STR_LEN 20
int main(void)
{
unsigned char str[STR_LEN + 1] = {0};
const char *hex_digits = "0123456789ABCDEF";
int i;
for( i = 0 ; i < STR_LEN; i++ ) {
str[i] = hex_digits[ ( rand() % 16 ) ];
}
printf( "%s\n", str );
return 0;
}
There are several unclarities and problems in your code. I interpret "hex character" to mean "hex digit", i.e. a symbol from {0,1,2,3,4,5,6,7,8,9,a,b,c,d,e,f}, not "the hexadecimal value of an ascii character's code point". This might or might not be what you meant.
This should do it:
void hex_fill(char *buf, size_t max)
{
static const char hexdigit[16] = "0123456789abcdef";
if(max < 1)
return;
--max;
for(i = 0; i < max; ++i)
buf[i] = hexdigit[rand() % sizeof hexdigit];
buf[max] = '\0';
}
The above will always 0-terminate the string, so there's no requirement that you do so in advance. It will properly handle all buffer sizes.
My variation on some of answers below; note the time seeded rand function and instead of a char using a const size, I use a vector that is then converted to a string array.
Boost variate generator docs
std::string GetRandomHexString(unsigned int count)
{
std::vector<char> charVect = std::vector<char>(count);
//Rand generator
typedef boost::random::mt19937 RNGType;
RNGType rng(std::time(nullptr) + (unsigned int)clock());
//seeding rng
uniform_int<> range(0, 15); //Setting min max
boost::variate_generator<RNGType, boost::uniform_int<> >generate(rng, range); //Creating our generator
//Explicit chars to sample from
const char hexChars[16] = { '0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F' };
//
for (int i = 0; i < count; i++)
{
charVect[i] = hexChars[generate()];
}
//
return std::string(charVect.begin(), charVect.end());;
}
Examples (count = 32):
1B62C49C416A623398B89A55EBD3E9AC
26CFD2D1C14B9F475BF99E4D537E2283
B8709C1E87F673957927A7F752D0B82A
DFED20E9C957C4EEBF4661E7F7A58460
4F86A631AE5A05467BA416C4854609F8

C Library function for converting a string of hex digits to ints?

I have a variable length string where each character represents a hex digit. I could iterate through the characters and use a case statement to convert it to hex but I feel like there has to be a standard library function that will handle this. Is there any such thing?
Example of what I want to do. "17bf59c" -> int intarray[7] = { 1, 7, 0xb, 0xf, 5, 9, 0xc}
No, there's no such function, probably because (and now I'm guessing, I'm not a C standard library architect by a long stretch) it's something that's quite easy to put together from existing functions. Here's one way of doing it decently:
int * string_to_int_array(const char *string, size_t length)
{
int *out = malloc(length * sizeof *out);
if(out != NULL)
{
size_t i;
for(i = 0; i < length; i++)
{
const char here = tolower(string[i]);
out[i] = (here <= '9') ? (here - '\0') : (10 + (here - 'a'));
}
}
return out;
}
Note: the above is untested.
Also note things that maybe aren't obvious, but still subtly important (in my opinion):
Use const for pointer arguments that are treated as "read only" by the function.
Don't repeat the type that out is pointing at, use sizeof *out.
Don't cast the return value of malloc() in C.
Check that malloc() succeeded before using the memory.
Don't hard-code ASCII values, use character constants.
The above still assumes an encoding where 'a'..'f' are contigous, and would likely break on e.g. EBCDIC. You get what you pay for, sometimes. :)
using strtol
void to_int_array (int *dst, const char *hexs)
{
char buf[2] = {0};
char c;
while ((c = *hexs++)) {
buf[0] = c;
*dst++ = strtol(buf,NULL,16);
}
}
Here's another version that allows you to pass in the output array. Most of the time, you don't need to malloc, and that's expensive. A stack variable is typically fine, and you know the output is never going to be bigger than your input. You can still pass in an allocated array, if it's too big, or you need to pass it back up.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
/* str of length len is parsed to individual ints into output
* length of output needs to be at least len.
* returns number of parsed elements. Maybe shorter if there
* are invalid characters in str.
*/
int string_to_array(const char *str, int *output)
{
int *out = output;
for (; *str; str++) {
if (isxdigit(*str & 0xff)) {
char ch = tolower(*str & 0xff);
*out++ = (ch >= 'a' && ch <= 'z') ? ch - 'a' + 10 : ch - '0';
}
}
return out - output;
}
int main(void)
{
int values[10];
int len = string_to_array("17bzzf59c", values);
int i = 0;
for (i = 0; i < len; i++)
printf("%x ", values[i]);
printf("\n");
return EXIT_SUCCESS;
}
#include <stdio.h>
int main(){
char data[] = "17bf59c";
const int len = sizeof(data)/sizeof(char)-1;
int i,value[sizeof(data)/sizeof(char)-1];
for(i=0;i<len;++i)
sscanf(data+i, "%1x",value + i);
for(i=0;i<len;++i)
printf("0x%x\n", value[i]);
return 0;
}

Resources