Getting gibberish instead of numbers using memcpy and strtoul - c

I have the following piece of code compiling under gcc:
int parseMsg(const char *msg_to_parse, unsigned long *exp_input, unsigned long *sysTicks )
{
int l_msg_size = strlen(msg_to_parse);
if(l_msg_size <10)
return -1;
char l_exp_input_arr[10];
char l_sys_ticks_arr[10];
memcpy(l_sys_ticks_arr,msg_to_parse+12,10);
memcpy(l_exp_input_arr,msg_to_parse,10);
//l_msg_size = strlen(msg_to_parse);
*sysTicks = strtoul(l_sys_ticks_arr,NULL,10);
*exp_input = strtoul(l_exp_input_arr,NULL,10);
return 0;
}
And I'm trying to test it in the following manner:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int parseMsg(const char *msg_to_parse, unsigned long *exp_input, unsigned long *sysTicks );
int main(void) {
char msg[] = "1234567890 59876543213";
unsigned long along1, along2;
along1 =0;
along2=0;
parseMsg(msg,&along1, &along2 );
printf("result of parsing: \n \t Along 1 is %lu \n \t Along 2 is %lu \n",along1, along2);
return 0;
}
But, I'm getting the following result:
result of parsing:
Along 1 is 1234567890
Along 2 is 4294967295
Why is the second unsigned long wrong?
Thanks

The second integer you provide is too big to be represented in memory on your architecture. So, according to its API, strtoul is just returning you ULONG_MAX (=4294967295 on your architecture), along with setting errno to ERANGE
strtoul API is here : http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul/
BUT it may also fail if you gave a smaller integer, because strtoul only stops parsing when it encounters a non-numerical character. Since you didn't ensure that, you cannot be sure that strtoul will not try to parse whatever is in memory just after your strings. (So assuming random, you have 10 chance out of 256 to have a conversion error)
Terminate your strings with \0, it will be ok then :
char l_exp_input_arr[11]; // +1 for \0
char l_sys_ticks_arr[11];
memcpy(l_sys_ticks_arr, msg_to_parse+12, 10);
l_sys_ticks_arr[10] = '\0';
memcpy(l_exp_input_arr, msg_to_parse, 10);
l_exp_input_arr[10] = '\0';

You need to make your two temporary char[] variables one char longer and then make the last character NULL.

Related

How can I scan a string with unknown size and values to use inside a function in C using gets()?

I am trying to convert a number from base b to base 10 using the function base_b_to_10 as below:
long int base_b_to_10(char* B, long int base) //take in the number as string returns it converted to base 10 as long int
{
long int N; //base 10 number:
N = strtol(B, NULL, base); //
return(N);
}
In the main program, the user will input the base of the input number and the input number itself.
The length and the size of the string is unknown and is up to the user to define
This is a simplified version of a big program I am trying to build in which the size of the string B is dynamically allocated in another function so I cannot do something like:
char B[100];
How to solve this? the compiler is returning nothing.
Input string (here: test) can be of any reasonable size. Anyway, there might be some limitations, see: Strtol() and atol() do not convert strings larger than 9 digits
Output string is a pointer (here: *str) to position within input string (here: test). According to this, the size of the string to which str points does not matter. (Note: In this example, str is only valid as long as test is valid).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
long int base_b_to_10(char* B, long int base, char **ret_str)
{
long int N;
N = strtol(B, ret_str, base);
return N;
}
int main()
{
long int val;
char *str;
char test[50] = "43724325HelloWorld";
val = base_b_to_10(test, 10, &str);
printf("val = %ld\n", val);
printf("str = %s\n", str);
return 1;
}
Notes: I adapted your example just to be working (not improving or simplifying anything). It is probably clear that you could also directly use strtol function in the main routine. Moreover, it does not matter, how the input string was allocated (fixed size or dynamic size) - just needs to be allocated and needs to end by \0 (as usual).
If cross platforming is not an issue, and assuming you are running on a linux system, you can make use of asprintf().
It basically formats your string and allocates the memory for you (remember to free it afterwards).
This is not part of the standard library so it has its limitations.
Another approach is to use snprintf() to preddict the size of the output buffer then and use malloc()
#include <stdio.h>
int main ()
{
int cx = snprintf ( NULL, 0, "18 characters long" );
printf("%d", cx);
return 0;
}
// OUTPUT:
// 18
Ok so I solved this problem by first using a buffer string with size 50 (pretty sufficient), than I used the strlen() function to determine the size of the string given by the user, and lastly I allocate this number to the string I will be using for the conversion:
char *str, buffer[50];
printf("enter the input value: ");
gets(buffer);
int i;
i = strlen(buffer);
str = (char*)malloc(i*sizeof(char));
strcpy(str, buffer);
fflush(stdin);
N = base_b_to_10(str, base_in);

Using sprintf to convert an unsigned long to char array producing 0

I am trying to convert an unsigned long using the sprintf function in c. Code goes like:
char ID[6];
sprintf(ID,"%lu",a.id);
a.id is a number that is passed in that can range from 0 > but I only want the first 6 regardless. Using printf("%lu",a.id); prior to conversion prints the right number but once I try print the string from the char the outcome is 0. Not too sure why this is happening any advice would be much appreciated.
... once I try print the string from the char the outcome is 0
Code is risking undefined behavior (UB): buffer overrun, potential wrong specifier.
but I only want the first 6 regardless.
Insure the buffer is big enough for 6 characters and a terminating null character.
//char ID[6];
char ID[6+1];
Handle a.id outside the expected range of 0...999999 with % some_unsigned_constant. This does print the last 6.
// sprintf(ID,"%lu",a.id);
sprintf(ID,"%lu",a.id % 1000000u);
As type of a.id, not posted, 2 steps may be useful to make sure a matching print specifier is used.
// sprintf(ID,"%lu",a.id % 1000000u);
unsigned long ul = a.id
sprintf(ID,"%lu", ul % 1000000u);
To print the first six, even if outside the 0...999999 range, use snprintf() which will print only up to the first 6.
char ID[6+1];
snprintf(ID, sizeof ID, "%lu", (unsigned long) a.id);
And the correct way to do what the OP wants is to
#include <stdio.h>
int main()
{
char ID[6];
unsigned long x = 3453342432;
int r = snprintf(ID, sizeof(ID), "%lu",x);
printf("%d %s\n", r, ID);
return 0;
}
Note that the snprintf result is a number of characters that would had been written. It was noted by others that you must reserve one character extra space for terminating NULL.

Converting a binary string to integer

When I try and convert my binary string to int I am receiving a couple of mistakes that I can not figure out. First I am reading from a file and the leading zeros are not showing up when I convert and the new line is showing zero.
This code I am using from this questions: Convert binary string to hexadecimal string C
char* binaryString[100];
// convert binary string to integer
int value = (int)strtol(binaryString, NULL, 2);
//output string as int
printf("%i \n",value)
My txt file and what I am expecting as an output:
00000000
000000010001001000111010
00000000000000000000000000000001
101010111100110100110001001001000101
What I get:
0
0
70202
1
-1127017915
This line:
char* binaryString[100];
Is declaring an array of 100 char pointers (or 100 strings). You probably meant this to declare a buffer of 100 characters to be interpreted as a single string:
char binaryString[100];
char *binaryString[100];
// You are creating an array of pointers in this scenario, use char binaryString[100] instead;
int value = (int)strtol(binaryString, NULL, 2);
// 101010111100110100110001001001000101 Is a 36 bit number, int (in most implementations) is 32 bit. use long long (64 bit in visual c++) as type and strtoll as function instead.
printf("%i \n",value)
Must be printf("%lld \n", value).
In summary:
#include "stdio.h"
#include "stdlib.h" // required for strtoll
int main(void)
{
char str[100] = "101010111100110100110001001001000101";
long long val = 0;
val = strtoll(str, NULL, 2);
//output string as int
printf("%lld \n", val);
return 0;
}
if im understanding this correctly you want to take a binary string so ones and zeros and convert it to a Hex string so 0-F, if so the problem is with the Write not the Convert, you specified '%i' as the written value format, what you need to do for hex is specify '%x'
Change this "printf("%i \n",value)" to "printf("%x\n",value)"

Converting string to int without removing zero's

I have string like
char str[10] = "0123456789";
I need to convert it into int. I tried it with atoi but this function removes 0. I searched it in google and found the same question here. Many answers have provided solution using strtol but its not working. Following is the code I am using for strtol:
#include <stdio.h>
#include <stdlib.h>
int main()
{
char str[30] = "0123456789 This is test";
char *ptr;
int ret;
ret = strtol(str, &ptr, 10);
printf("The number is %d\n", ret);
printf("String part is %s\n", ptr);
return(0);
}
Output:
The number is 123456789
String part is This is test
What's wrong I am doing in this case. How to convert string to int without removing zero's.
You need to format your output accordingly.
%d just prints the int in decimal using the shortest string representation (no leading zeros)
%8d (for example) will print the int in decimal in a field of size 8 (leading spaces if needed)
%08d (for example) will print the int in decimal in a field of size 8 with leading zeros.

String conversion to int

I have a pointer lpBegin pointing to a string "1234". Now i want this string compare to an uint how can i make this string to unsigned integer without using scanf? I know the string number is 4 characters long.
You will have to use the atoi function. This takes a pointer to a char and returns an int.
const char *str = "1234";
int res = atoi(str); //do something with res
As said by others and something I didn't know, is that atoi is not recommended because it is undefined what happens when a formatting error occurs. So better use strtoul as others have suggested.
Definitely atoi() which is easy to use.
Don't forget to include stdlib.h.
You can use the strtoul() function. strtoul stands for "String to unsigned long":
#include <stdio.h>
#include <stdlib.h>
int main()
{
char lpBegin[] = "1234";
unsigned long val = strtoul(lpBegin, NULL, 10);
printf("The integer is %ul.", val);
return 0;
}
You can find more information here: http://www.cplusplus.com/reference/clibrary/cstdlib/strtoul/
You could use strtoul(lpBegin), but this only works with zero-terminated strings.
If you don't want to use stdlib for whatever reason and you're absolutely sure about the target system(s), you could do the number conversion manually.
This one should work on most systems as long as they are using single byte encoding (e.g. Latin, ISO-8859-1, EBCDIC). To make it work with UTF-16, just replace the 'char' with 'wchar_t' (or whatever you need).
unsigned long sum = (lpbegin[0] - '0') * 1000 +
(lpbegin[1] - '0') * 100 +
(lpbegin[2] - '0') * 10 +
(lpbegin[3] - '0');
or for numbers with unknown length:
char* c = lpBegin;
unsigned long sum = 0;
while (*c >= '0' && *c <= '9') {
sum *= 10;
sum += *c - '0';
++c;
}
I think you look for atoi()
http://www.elook.org/programming/c/atoi.html
strtol is better than atoi with better error handling.
You should use the strtoul function, "string to unsigned long". It is found in stdlib.h and has the following prototype:
unsigned long int strtoul (const char * restrict nptr,
char ** restrict endptr,
int base);
nptr is the character string.
endptr is an optional parameter giving the location of where the function stopped reading valid numbers. If you aren't interested of this, pass NULL in this parameter.
base is the number format you expect the string to be in. In other words, 10 for decimal, 16 for hex, 2 for binary and so on.
Example:
#include <stdlib.h>
#include <stdio.h>
int main()
{
const char str[] = "1234random rubbish";
unsigned int i;
const char* endptr;
i = strtoul(str,
(char**)&endptr,
10);
printf("Integer: %u\n", i);
printf("Function stopped when it found: %s\n", endptr);
getchar();
return 0;
}
Regarding atoi().
atoi() internally just calls strtoul with base 10. atoi() is however not recommended, since the C standard does not define what happens when atoi() encounters a format error: atoi() can then possibly crash. It is therefore better practice to always use strtoul() (and the other similar strto... functions).
If you're really certain the string is 4 digits long, and don't want to use any library function (for whatever reason), you can hardcode it:
const char *lpBegin = "1234";
const unsigned int lpInt = 1000 * (lpBegin[0] - '0') +
100 * (lpBegin[1] - '0') +
10 * (lpBegin[2] - '0') +
1 (lpBegin[3] - '0');
Of course, using e.g. strtoul() is vastly superior so if you have the library available, use it.

Resources