Parse a char string into an INT C programming - c

I'm trying to parse a char string into an INT.
If I had...
unsigned char color[] = "255"
And wanted to parse this into an INT. How would I go about doing this?
I tried...
unsigned char *split;
split = strtok(color," ,.-");
while(split != NULL)
{
split = strok(NULL, " ,.-);
}
This just gives me the value 255 for split now.
I feel like I need something like...
int y = split - '0'; //but this makes an INT pointer without a cast

To convert a string to integer, call strtol:
char color[] = "255";
long n;
char *end = NULL;
n = strtol(color, &end, 10);
if (*end == '\0') {
// convert was successful
// n is the result
}

If you want to convert without calling strtol you can scan the color array and compare each char against '0' to get the corresponding numeric value, then add the result properly multiplied by a power of 10, i.e.
int i = 0, strlen = 0, result = 0;
while (color[i++]) strlen++;
for (i = 0; i<strlen; i++)
{
result += (color[i] - '0')*pow(10,strlen-1-i);
}

Related

Hex to ascii in c using visual studio

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.

Data type confusion, need integer from char array

Once again I have the wrong data type. This is an arduino project.
I have a char array. The last 9 characters are rgb, I get them as triplets. So 000255000.
I need to pass those to a function but as integers, like 0, 255, 0. I'm ok if 000 turns into 0, but I need 045 to turn into 45.
I've tried to cast them, like:
blue = (int)message[11];
blue += (int)message[12];
blue += (int)message[13];
That did not work. I could however cast them to strings,which I did, then I tried: Yes, I know this was not a great idea, but it was worth a shot.
char tempBlue[4];
blue.toCharArray(tempGreen, sizeof(tempGreen));
iBlue = atoi(tempGreen);
That also did not work.
I'm lost as to how to do this. I have no idea how ( if you can ) concatenate integers or I would have tried that.
EDIT------
Am I asking the wrong question. Should I be doing this the reverse way around. Concatenate first then to integer? I have them as characters to begin with.
To convert each character to its respective int do the following
int first = message[11] - '0';
int second= message[12] - '0';
int third = message[13] - '0';
To see why this works, you can check here: Why does subtracting '0' in C result in the number that the char is representing?
To concatenate ints, you could use this function
unsigned concatenate(unsigned x, unsigned y) {
unsigned pow = 10;
while(y >= pow)
pow *= 10;
return x * pow + y;
}
I did not write this function, it was written by #TBohne originally here
I'd go with:
char *partMessage = (char*)malloc(4);
partMessage[3] = '\0';
strncpy(partMessage, message + 11, 3);
result = (int)strtol(partMessage, NULL, 10);
free(partMessage);
you could try something like this
#include <stdio.h>
int main()
{
// example
char message[] = { "000255000" };
int r=0, g=0, b=0;
// make sure right number of values have been read
if ( sscanf(message, "%03d%03d%03d", &r, &g, &b ) == 3 )
{
printf( "R:%d, G:%d, B:%d\n", r,g,b );
}
else
{
fprintf(stderr, "failed to parse\n");
}
}
sscanf will skip any white space so even a string like message[] = " 000 255 000 "; will work.
Just do the conversion manually:
int convert_digits(char *cp, int count) {
int result = 0;
for (int i = 0; i < count; i += 1) {
result *= 10;
result += (cp[i] - '0');
}
return result;
}
char *input = "000045255";
int main(int ac, char *av[]) {
printf("r=%d g=%d, b=%d\n",
convert_digits(cp, 3),
convert_digits(cp+3, 3),
convert_digits(cp+6, 3));
}
Convert string to a number and then numerically peal off 3 digits at a time.
const char *s = "000255000";
char *endptr;
unsigned long num = strtoul(s, &endptr, 10);
// add error checking on errno, num, endptr) here if desired.
blue = num%1000;
num /= 1000;
green = num%1000;
num /= 1000;
red = num%1000;
// Could add check to insure r,g,b <= 255.

Want to take the amount of data given by a different string's length

I used 'strlen' to find the length of a string, call it string a. I then did some other things to create a binary string. The binary strings value is longer than string a. I want to return the binary string as long as string a. How would I do that?
Let me try to code it out to maybe help clarify:
int main(int argc, char** argv)
{
int i, j, k, l, prefix_length, sum;
char *s, *dot, *binary_string, *ret_val, *temp_string;
char buf[] = "10.29.246.49/32";
s = strtok(buf, "/");
prefix_length = strlen(s);
for(i = 4; i > 0; i--){
dot = strtok(s, ".");
while (dot != NULL){
j = atoi(dot);
sum = sum + j;
s = strtok(NULL, ".");
}
*binary_string = dec_to_bin(sum);
}
strcpy(temp_string, "0");
for(l = prefix_length - strlen(binary_string); i > 0; i--){
strcat(temp_string, binary_string);
strcpy(binary_string, temp_string);
strcpy(tempstring, "0");
}
ret_val = binary_string;
return 0;
}
Also, can you look at my dec_to_bin and tell me if I'm calling it right and what have you:
char dec_to_bin(int decimal)
{
char *ret;
int d = decimal, i;
for (i = 128; i >= 1; i = i/2){
if(d / i){
ret += '1';
d -= i;
}
else
ret += '0';
}
return *ret;
}
Your dec_to_bin is trying to convert a number to a string of '1's and '0's, but is only returning the first char value
You are defining ret as a char * pointer, but you are using it like a std::string which it is not. It is a pointer to memory, and you have to provide it with some memory to point to. As it is you are overwriting random memory, although in debug mode ret probably is initialised to 0, so you will just get a memory exception.
You could allocate the memory with malloc, but this will lead to a world of pain as the way you call the function will simply result in memory leaks.
If you have to use char* pointers and not std::string then I would suggest passing it a buffer to write the string to. You know the string will always be 8 characters long plus the null terminator
char buffer[9];
dec_to_bin(sum, buffer);
ret += '1' is not doing what you think it does. It is adding a char value to a char* pointer which is totally different. You need to store the character at the location pointed to by ret, and then move ret to point to the next location
*ret = '1';
ret = ret + 1;
or
*ret++ = '1';
When this finishes ret will point to the end of the string, so you can't return that. There is not much benefit from returning a value you passed to the routine, but if you must then you need to save it
char* dec_to_bin(int decimal, char *buffer)
{
char *ret = buffer;
int d = decimal, i;
for (i = 128; i >= 1; i = i/2){
if(d / i){
*ret++ = '1';
d -= i;
}
else
*ret++ = '0';
}
return buffer;
}
You should run this program in a debugger, because that will teach you a lot about what is actually going on in your code
If binary_string was a std::string, which it needs to be for binary_string += to work, then
std::string return_val = binary_string.substr(0, strlen(a));
If you are limited to char * then
int l = strlen(a);
char* return_val = new char[l + 1];
strncpy(return_val, binary_string, l);
return_val[l] = 0;
specify variable name in only first call to strtok(). for operations on same string again use strtok() as,
strtok(NULL,".");
to know about using strtok() read this link.
To get the binary string you want, you can follow this procedure,
for(i = 4; i > 0; i--){
dot = strtok(s, ".");
if (dot != NULL){
j = atoi(dot);
sum=sum+j;
s = strok(NULL, ".");
}
else{
k = atoi(s);
sum=sum+j;
}
//printf("%s\n", dot);
}
binarystring=dec2bin(sum);
you can reduce this loop and use,
dot = strtok(s, ".");
while (dot != NULL)
{
j = atoi(dot);
sum=sum+j;
s = strok(NULL, ".");
}
binarystring=dec2bin(sum);
here instead of adding binary number, you can add integers and then convert the sum to binary. the result will be same number right.dec2bin() should convert decimal to binary and return binary number as string. then you add code similar to this to make binary_string length same as length of a,
strcpy(tempstring,"0");
for(i=strlen(a)-strlen(binary_string);i>0;i--)
{
strcat(tempstring,binary_string);
strcpy(binary_string,tempstring);
strcpy(tempstring,"0");
}

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

Resources