i wanted to split this hexstring, convert em, and store em in an array.
but it seems there is something off from my work, and i don't know what.
I intend to split this string
27CA6B
to
27
CA
6B
but the output is always only the first string.
like
27
51819
0
please somebody help, here is my code
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
int main(void)
{
char bc[] = "27CA6B";
char *theEnd;
long result;
long resulta;
long resultb;
long resultc;
result = strtol (bc, &theEnd, 0);
resulta = strtol (theEnd, &theEnd, 16 );
resultb = strtol (theEnd, NULL, 0);
//int i = 0;
//printf("%c%c%c%c%c%c\n", bc[0], bc[1], bc[2], bc[3], bc[4], bc[5]);
printf("%ld\n", result, &bc[0]);
printf("%ld\n", resulta, &bc[1]);
printf("%ld\n", resultb, &bc[2]);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char bc[] = "27CA6B";
unsigned char result[(sizeof(bc)-1)/2] = {0};
int i = 0;
for(char *p = bc; *p; p += 2){
char part[3] = {0};
memcpy(part, p, 2);//Extract 2 characters
result[i++] = strtoul(part, NULL, 16);
}
for(i = 0; i < sizeof(result); ++i){
printf("%3u %c%c\n", result[i], bc[i*2], bc[i*2+1]);
}
return 0;
}
expand loop
unsigned char result1,result2,result3;
int i = 0;
char part[3] = {0};
memcpy(part, bc + i, 2); i += 2;
result1 = strtoul(part, NULL, 16);
memcpy(part, bc + i, 2); i += 2;
result2 = strtoul(part, NULL, 16);
memcpy(part, bc + i, 2); i += 2;
result3 = strtoul(part, NULL, 16);
i = 0;
printf("%3u %c%c\n", result1, bc[i], bc[i+1]); i += 2;
printf("%3u %c%c\n", result2, bc[i], bc[i+1]); i += 2;
printf("%3u %c%c\n", result3, bc[i], bc[i+1]); i += 2;
The "issue" that you see in because of this line
resulta = strtol (theEnd, &theEnd, 16 );
there, theEnd points to CA6B which, as per the base 16, is a valid input as whole, so the whole string is consumed and converted. The decimal representation value is 51819, which you see as output.
The best way to achieve this would be (based on your approach) to take a pointer to the starting of the array, and "clip" it on alternate indexes.
That said, all your printf() statements are logically wrong, as you have only one format specifier but you supply two arguments, so as the last one will be ignored silently.
Related
I'm playing around doing a few challenges of reverse engineering with ghidra.
I have analyzed a bin file, which should contain some information about a password.
When you run the file, you can give it some input, and it will check if it's the correct password.
Here is the pseudo-c code that is responsible for doing this (The comments are me):
__isoc99_scanf(&DAT_00400a82,local_28); // input scanned from user
__s2 = (char *)FUN_0040078d(0x14); // password retrieved from function
iVar1 = strcmp(local_28,__s2); // comparing strings
if (iVar1 == 0) { // if they are equal, do this
FUN_00400978(&local_48);
}
Ok, so i tried looking up the function FUN_0040078d:
void * FUN_0040078d(int param_1)
{
int iVar1;
time_t tVar2;
void *pvVar3;
int local_c;
tVar2 = time((time_t *)0x0);
DAT_00601074 = DAT_00601074 + 1;
srand(DAT_00601074 + (int)tVar2 * param_1);
pvVar3 = malloc((long)(param_1 + 1));
if (pvVar3 != (void *)0x0) {
local_c = 0;
while (local_c < param_1) {
iVar1 = rand();
*(char *)((long)local_c + (long)pvVar3) = (char)(iVar1 % 0x5e) + '!';
local_c = local_c + 1;
}
*(undefined *)((long)pvVar3 + (long)param_1) = 0;
return pvVar3;
}
/* WARNING: Subroutine does not return */
exit(1);
}
So theres a lot of information here. But overall, what I think happens is that an array of chars is constructed, by doing the operation:
(char)(iVar1 % 0x5e) + '!';
Which I have no idea what means (what does modulo on chars do? and does + '!' ) just mean concatenate a "!".
Overall I'm haivng some issues reading this, and I'm wondering if it's possible to predict what this function would output for specific inputs. In this case the function is given 14 as input.
Maybe the use of the rand() means that it cannot be deconstructed?
Can anyone give a guess/tell me whatthis function would likely output for input 14?
you got to remember that every char is a character representation of an 8bit value. Thus every operator is valid within the realm of chars.
I made this example for you to understand it better.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
char character = 'A'; // 65 in dec
char bang = '!'; // 33 in dec
printf("'A' in dec: %d\n", (int)character);
printf("'!' in dec: %d\n", (int)bang);
// now the modulo operator works the same in chars
character = 'a';
char new_value = (char)character%64;
printf("a %% 64 : char_value: %c, int_value: %d\n", new_value, (int)new_value);
// you got to remember that chars are just a coded 8bit value
char at_symbol = '#'; // 64 in dec
// now the modulo operator works the same in chars
character = 'a';
new_value = (char)character%at_symbol;
printf("a %% # : char_value: %c, int_value: %d\n", new_value, (int)new_value);
// it works the same with every other operator
int value1 = 300; //this is your random value
char hex_value = 0x5E; //94 in dec or ^ in char
new_value = (char)(value1%hex_value); //300 % 94 = 18;
new_value += bang; //18 + 33 = 51 in dec or the number 3 symbol in char;
printf("dec_val: %d, char encoding: %c\n", (int)new_value, new_value);
}
as per your previous comment, here's a simplified version of your function
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
long GLOBAL_COUNTER = 0;
typedef char undefined;
void * array_constructor(int size);
int main(int argc, char **argv)
{
char* random_string = (char*)array_constructor(0x14);
printf("%s", random_string);
free(random_string);
}
void * array_constructor(int size)
{
int random_value;
//time_t cur_time;
void *array;
int counter;
//cur_time = time(NULL);
GLOBAL_COUNTER = GLOBAL_COUNTER + 1;
srand(0);//srand(GLOBAL_COUNTER + (int)cur_time * param_1);
array = malloc((long)(size + 1));//returns a void array of param_1 + 1 elements
if (array == NULL)
exit(1);
counter = 0;
while (counter < size) {
random_value = rand();
int char_value = (char)(random_value % 0x5e) + '!';//Range of possible values 33-127
// This is due to the fact that random value can have any value given the seed
// but its truncated to a modulo 0x5e so its new range is 0 - 0x5e(94 in dec)
// and you add the bang symbol at the end so 0 + 33 = 33 and 94 + 33 = 127
*(char *)((long)counter + (long)array) = char_value;
// this statement is the same as
// array[counter] = char_value
counter++;
}
*(undefined *)((long)array + (long)size) = 0; //it puts the \0 at the end of the string
return array;
}
now the only problem that you had was with the undefined typedef. this code is a simplification of yours. but it works.
I am not how to use the unions to print the integer array here. Please correct me to get the out.
val.str is being printed correctly - as '+100-100-100+760' and the first element of the output array seems to be loaded the value correctly. Then the same memory is overridden and printing some garbage value and this is something I don't know how to solve.
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
//Variable Decalartion
int i = 0, x = 100, y = -100, z = -100, p = 760;
int len_str;
char temp[4];
union Data{
char str[16];
unsigned int buff[8];
};
void Init(union Data val, unsigned int *dest);
int main(void){
union Data val;
unsigned int x[8];
Init(val,x);
for (i = 0; i < 8; i++)
{
printf("0x%04X ",x[i]);
}
return 0;
}
void Init(union Data val, unsigned int *dest)
{
len_str = sizeof(val.str);
sprintf(temp,"%+04d",x);
strcpy(val.str,temp);
sprintf(temp,"%+04d",y);
strcat(val.str,temp);
sprintf(temp,"%+04d",z);
strcat(val.str,temp);
sprintf(temp,"%+04d",p);
strcat(val.str,temp);
printf("%s\n",val.str);
printf("\n");
for (i = 0; i < len_str+1; i += 2)
{
val.buff[i / 2] = ((unsigned int)(unsigned char)val.str[i] << 8) |
(unsigned int)(unsigned char)val.str[i + 1];
dest[i / 2] = val.buff[i / 2];
}
}
The output that is displayed is,
+100-100-100+760
0x2B31 0x401111C8 0x8049A58 0x8048782 0x0001 0xBFFB5E74 0xBFFB5E7C 0x401B0E4D
Thanks,
Akhil
There are many serious errors in this code.
As user694733 noted, char temp[4]; is too small. you have a buffer overflow there.
You make this call: Init(val,x); with unititialized data in val.
Note that the sizeof int is platform specific. You seem to assume it is 16bits?
It is 32bits on PCs and modern ARM processors. But may be 16bits on lower end processors.
I have for example a string (mathematical equation in postfix notation) that looks like this: The numbers are 5.33,5.32,6.33,3.22
5.335.32*6.333.22++
I'm looking to make it into prefix notation but simply reversing the string won't work due to the fact it has to retain the value of the number.
I've thought of doing a normal character by character swap in a for loop, and when encountering a digit make that into a substring and place it on afterwards but I haven't gotten it to work properly and now I'm stuck.
My end-goal is to make a binary expression tree out of that, so if there's an easier way than doing this also please let me know.
A stack-based approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *postfix_to_prefix(const char *string) {
char operator, *stack[1024];
int s = 0, number, fraction;
const char *tokens = string;
while (1) {
if (sscanf(tokens, "%1d.%2d", &number, &fraction) == 2) {
stack[s] = malloc(sizeof("1.00"));
(void) sprintf(stack[s++], "%4.2f", number + (fraction / 100.0));
tokens += strlen("1.00");
} else if (sscanf(tokens, "%c", &operator) == 1) {
char *operand1 = stack[--s];
char *operand2 = stack[--s];
stack[s] = malloc(strlen(operand1) + strlen(operand1) + sizeof(operator) + sizeof('\0'));
(void) sprintf(stack[s++], "%c%s%s", operator, operand1, operand2);
free(operand1);
free(operand2);
tokens += sizeof(operator);
} else {
break;
}
}
return stack[--s];
}
int main() {
const char *string = "5.335.32*6.333.22++";
printf("%s\n", string);
char *inverted = postfix_to_prefix(string);
printf("%s\n", inverted);
free(inverted);
return 0;
}
OUTPUT
> ./a.out
5.335.32*6.333.22++
++3.226.33*5.325.33
>
This is a bare bones implementation with no real error checking nor other finishing touches. You'll want to check that non-communitive operations like subtraction and division come out with the operands in the correct order and reverse them if not.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char exp[] = "5.335.32*6.333.22++";
size_t len = strlen(exp);
char temp[len];
char *p = temp;
for(int i = len-1; i >= 0; ){
if(isdigit(exp[i])){
memcpy(p, &exp[i-4+1], 4);//all number have a length of 4
p += 4;
i -= 4;
} else {
*p++ = exp[i--];//length of op is 1
}
}
memcpy(exp, temp, len);//Write back
puts(exp);//++3.226.33*5.325.33
return 0;
}
A simple problem but I can't get documentation about this kind of format: I want to print a float in a Fortran scientific notation, with its integer part always being zero.
printf("%0.5E",data); // Gives 2.74600E+02
I want to print it like this:
.27460E+03
How can I get this result as clean as possible?
If you only care about the integer part being 0 and not really leaving out the 0, i.e. if you're fine with 0.27460E+03 instead of .27460E+03 you could do something similar to this:
#include <stdio.h>
#include <stdlib.h>
void fortran_printf();
int main(void)
{
double num = 274.600;
fortran_printf(num);
exit(EXIT_SUCCESS);
}
void fortran_printf(double num)
{
int num_e = 0;
while (num > 1.0) {
num /= 10;
num_e++;
}
printf("%.5fE+%02d", num, num_e);
}
Otherwise you have to take a detour over strings. Note that the code above is only meant to get you started. It certainly doesn't handle any involved cases.
I tried doing this with log10() and pow(), but ended up having problems with rounding errors. So as commented by #Karoly Horvath, string manipulation is probably the best approach.
#include <stdlib.h>
char *fortran_sprintf_double(double x, int ndigits) {
char format[30], *p;
static char output[30];
/* Create format string (constrain number of digits to range 1–15) */
if (ndigits > 15) ndigits = 15;
if (ndigits < 1) ndigits = 1;
sprintf(format, "%%#.%dE", ndigits-1);
/* Convert number to exponential format (multiply by 10) */
sprintf(output, format, x * 10.0);
/* Move the decimal point one place to the left (divide by 10) */
for (p=output+1; *p; p++) {
if (*p=='.') {
*p = p[-1];
p[-1] = '.';
break;
}
}
return output;
}
A string manipulation approach:
int printf_NoIntegerPart(double x, int prec) {
char buf[20 + prec];
sprintf(buf, "%+.*E", prec - 1, x * 10.0); // use + for consistent width output
if (buf[2] == '.') {
buf[2] = buf[1];
buf[1] = '.';
}
puts(buf);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // --> +.27460E+03
}
This will print "INF" for |x| > DBL_MAX/10
printf() will not meet OP’s goal in one step using some special format. Using sprintf() to form the initial textual result is a good first step, care must be exercised when trying to do “math” with string manipulation.
Akin to #user3121023 deleted answer.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int printf_NoIntegerPart(double x, int prec) {
assert(prec >= 2 && prec <= 100);
char buffer[prec + 16]; // Form a large enough buffer.
sprintf(buffer, "%.*E", prec - 1, x);
int dp = '.'; // Could expand code here to get current local's decimal point.
char *dp_ptr = strchr(buffer, dp);
char *E_ptr = strchr(buffer, 'E');
// Insure we are not dealing with infinity, Nan, just the expected format.
if (dp_ptr && dp_ptr > buffer && E_ptr) {
// Swap dp and leading digit
dp_ptr[0] = dp_ptr[-1];
dp_ptr[-1] = dp;
// If x was not zero …
if (x != 0) {
int expo = atoi(&E_ptr[1]); // Could use `strtol()`
sprintf(&E_ptr[1], "%+.02d", expo + 1);
}
}
return puts(buffer);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // ".27460E+03"
return 0;
}
Faced same issue while fortran porting.
DId not found std C format :(
Implemented both approaches - with log10/pow and with string manipulation.
#include <ansi_c.h>
#define BUFFL 16
// using log10 , 3 digits after "."
char* fformat1(char* b, double a) {
int sign = 1;
double mant;
double order;
int ord_p1;
if (a<0) {
sign =-1;
a = -a;
}
order=log10 (a);
if (order >=0) ord_p1 = (int) order +1; // due sto property of int
else ord_p1 = (int) order;
mant=a/(pow(10,ord_p1));
sprintf(b,"%.3fE%+03d",mant,ord_p1);
if (sign==-1) b[0]='-';
return b;
}
// using string manipulation
char* fformat2(char* b, double a) {;
int sign = 1;
int i;
int N=3;
if (a<0) {
sign =-1;
a = -a;
}
sprintf(b,"%0.3E",a*10); // remember - we *10 to have right exponent
b[1]=b[0]; // 3.123 => .3123
b[0]='.';
for (i=N; i>=0; i--) // and shif all left
b[i+1]=b[i];
b[0]='0'; // pad with zero 0.312
if (sign==-1) b[0]='-'; // sign if needed
return b;
}
int main () {
char b1[BUFFL]; // allocate buffer outside.
char b2[BUFFL];
char b3[BUFFL];
char b4[BUFFL];
char b5[BUFFL];
printf("%s %s %s %s %s \n", fformat(b1,3.1), fformat(b2,-3.0), fformat(b3,3300.),
fformat(b4,0.03), fformat(b5,-0.000221));
printf("%s %s %s %s %s \n", fformat2(b1,3.1), fformat2(b2,-3.0), fformat2(b3,3300.),
fformat2(b4,0.03), fformat2(b5,-0.000221));
return 1;
}
from a char array like {T,E,S,T,1,2,3,E,N,D}, I need to get an integer from certain positions. Following with the example, I would like to get an integer from positions 4, 5, 6. So, myInt = 123.
I tried following method but haven't got desired integer.
char receivedata[bytes];
concatVars = concatenate(atoi(receivedata[6] - '0', receivedata[7] - '0');
concatVars = concatenate(concatVars, receivedata[8] - '0');
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
This should do what you want:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
int arrToInt(char* arr, int len) {
int toRet = 0;
for(int i = 0; i < len; i++) {
if (isdigit(arr[i])) {
toRet *= 10;
toRet += arr[i] - '0';
}
}
return toRet;
}
int main(int argc, char* argv[]) {
char test[] = {'T', 'E', 'S', 'T', '1', '2', '3', 'E', 'N', 'D'};
int asInt = arrToInt(test, 10);
printf("Got: %d\n", asInt);
}
Output (compiling with -std=c99 to make the int i = 0 inline declaration work):
Got: 123
One way of doing this would be:
int myInt = (((int)myArray[4] - 48) * 100) + (((int)myArray[5] - 48) * 10) + (((int)myArray[6] - 48) * 1);
Note that 48 is the ASCII position of the number 0, thus by converting a character to int and then subtracting 48 you get the numeric value.
Standard library's string-to-integer conversion functions (e.g. strtol) stop automatically once they reach a non-numeric character in the input character sequence. So all you have to do is tell such function where to start. In your case this will perform the conversion
const char *s = "TEST123END";
long myLong = strtol(s + 4, NULL, 10);
int myInt = myLong;
You just have to handle possible errors.
#include <stdio.h>
#include <string.h>
int main(){
char *str = "TEST123END";
char s4_6[4] = {0};
int n;
memcpy(s4_6, str+4, 3);
//if(1==sscanf(str, "%*[^0-9]%d", &n))
//if(1==sscanf(str+4, "%d", &n))
if(1==sscanf(s4_6, "%d", &n))
printf("%d\n", n);
return 0;
}
Here is one way:
int myInt = atoi(&myArray[4]);
Adding to ced-b's response, I prefer this syntax:
myArray[5] - '0'
That is, make it clear you are subtracting off the '0'.
Note: I used specific offset into the string because the OP asked for: "I need to get an integer from certain positions", which I interpreted as specific offset into the string. Based on the accepted answer I seem to have interpreted that wrong.