Is there any function in C or C++ to perform the inverse of an snprintf, such that
char buffer[256]
snprintf( buffer, 256, "Number:%i", 10);
// Buffer now contains "Number:10"
int i;
inverse_snprintf(buffer,"Number:%i", &i);
// i now contains 10
I can write a function that meets this requirement myself, but is there already one within the standard libraries?
Yes, there is sscanf(). It returns the number of tokens successfully matched to the input, so you can check the return value to see how far it made it into the input string.
if (sscanf(buffer, "Number:%i", &i) == 1) {
/* The number was successfully parsed */
}
In addition to sscanf(), if you are only going to scan numbers, you can safely scan numeric values using the strto*() functions: strtol(), strtoll(), strtoul(), strtoull(), strtof(), strtod(), strtold(). You can also use atoi(), atol() and atoll(), but note that these functions return 0 if the string is not an integer that can be converted.
Related
I am working on a project that takes a Lua string and converts it into a C string – not at all difficult, of course. However, I run into trouble when attempting to convert a binary representation of a function, i.e. one produced by a call to string.dump, to a C string. I am having trouble reading the entire string.
While it is not the ultimate goal of the project, consider the following simple example where I print out the characters in a string one-by-one using a C function called chars that I have registered for use in Lua:
static void chars(char* cp) {
char* pointer = cp;
while (*pointer) {
printf("%c\n", *pointer);
++pointer;
}
return;
}
static int lua_chars(lua_State* L) {
lua_len(L, 1);
size_t len = static_cast<size_t>(lua_tonumber(L, -1)) + 1;
lua_pop(L, 1);
if (len > 0) {
char* cp = static_cast<char*>(malloc(len));
strcat(cp, lua_tostring(L, 1));
chars(cp);
free(cp);
}
return 0;
}
Calling chars from a Lua script would look like this:
chars("Hello World!")
and would print out the characters one by one with each followed by a newline.
Now to the actual issue. Consider this example where I declare a function in Lua, dump it with string.dump, and then pass that string to the function chars to print out its characters individually:
local function foo()
print("foo")
return
end
local s = assert(string.dump(foo))
chars(s)
The string s in its entirety, not printed with my function chars, looks something like this:
uaS?
xV(w#=stdin#A#$#&?&?printfoo_ENV
However, chars only prints the first five bytes:
u
a
S
(Note there are supposed to be two lines of whitespace before the 'u'.)
I am almost certain that this is due to null characters within the string, which I think interferes with lua_tostring's functionality. I have come across lua_Writer for reading chunks, but I have no idea how to use/code it. How can I successfully convert the entire string on the Lua stack to a C string?
I am almost certain that this is due to null characters within the
string
Yes, it's exactly because Lua strings can contain zeroes.
which I think interferes with lua_tostring's functionality.
And this is false. lua_tostring() works as intended. It's just strcat() you're using will only copy the data up to the nearest zero byte.
If you need to copy the string, use memcpy, passing it both the pointer to Lua string data and Lua string length (lua_len, lua_rawlen, etc).
But just for printing you don't even need to copy anything. Pass the len variable as an argument to chars(), and check that length instead of waiting for zero byte.
The Problem isn't lua_tostring but strcat which copies until it finds an null characters. Same Problem with your chars function.
That should work:
memcpy(cp, lua_tostring(L, 1), len);
chars(cp, len);
...
static void chars(char* cp, size_t len) {
for (size_t i = 0; i < len; ++i, ++cp) {
putchar(*cp);
}
}
Is it possible to display a single dimensional array of values using SetWindowsText() in a text box on windows api?
for example. SetWindowText(hwndStatic3, sArray);
******************EDIT************
I have a textbox on the windows api where I use GetWindowText() to retrieve the string written in the text box then I convert the string to decimal array. I then convert this decimal array value to hexadecimal value as I am trying to print those values using SetwindowsText within another textbox. However only the last value of the array is printing. How can I print all the values?
******************EDIT************
code:
GetWindowText(hwndtext1, value, 256);
for (i = 15; i >= 0; i--)
{
temp[i] = atoll(value); //converts sting to decimal
ulltoa(temp[i] , sArray, 16); //converts decimal to hexadecimal
buf[i] = temp[i];
}
SetWindowText(hwndStatic3, sArray);
SetWindowText is just a macro with signature:
BOOL SetWindowText(HWND, const TCHAR*);
Depending on your build settings, it will call one of the following:
BOOL SetWindowTextA(HWND, const char*); //ansi version
BOOL SetWindowTextW(HWND, const wchar_t*); //unicode version
where TCHAR is defined as:
#ifdef _UNICODE
typedef wchar_t TCHAR;
#else
typedef char TCHAR;
#endif
So, an array of strings is not compatible with SetWindowText but an array of characters will work, provided that the array is of type TCHAR *, or of type (char * or wchar_t *) that is compatible with your settings.
First, atoll and ulltoa aren't documented with the Microsoft Visual C/C++ (which is what I use for Windows) so I'm working from documentation I found online. Either your versions do more than those I've found documented, or you've left out some significant code from your example.
Based on the loop control, I'm guessing that you expect to always find 15 values in the string you read from the first control. BUT... the atoll and ulltoa functions only operate on one value at a time and do nothing to advance through the input list. So your loop is converting the first number from string to 64 bit int and then converting that into a string 15 times.
Since you say the last value is the only one you see, your functions must actually be parsing the value string in some way that is not apparent in your example. However, ulltoa seems to always be placing the value into the same place in the same string variable, with each subsequent call in the loop overwriting the previous call. My lazy self would add a bit like this:
int len = 0;
char szOutput[15*20]; // enough space for 15 64 bit hex strings
GetWindowText(hwndtext1, value, 256);
for (i = 15; i >= 0; i--)
{
temp[i] = atoll(value); //converts sting to decimal
ulltoa(temp[i] , sArray, 16); //converts decimal to hexadecimal
buf[i] = temp[i];
len += sprintf( szOutput+len, "%s ", sArray );
}
szOutput[len-1] - '\0'; // remove the final space
SetWindowText(hwndStatic3, szOutput);
Of course, with the sprintf you could also skip the ulltoa call entirely and change the sprintf line to:
len += sprintf( szOutput+len, "%16.16I64X", temp[i] );
(or whatever flavor/form of the hex output you want (see the printf format documentation for details.) If you want your list to be one item per line, then replace the trailing space with a newline. Oh, the I64 in the %16.16I64X is a Microsoft thing that might be different in other compilers/libraries.
FYI, the sprintf technique I used lets the function keep appending to the end of the buffer but incrementing the offset into the buffer (len) by the length of the string just appended, which is the value returned by sprintf. It is a quick and easy way to assembling string lists such as yours.
I am really confused. I have to be missing something rather simple but nothing I am reading about strtol() is making sense. Can someone spell it out for me in a really basic way, as well as give an example for how I might get something like the following to work?
string input = getUserInput;
int numberinput = strtol(input,?,?);
The first argument is the string. It has to be passed in as a C string, so if you have a std::string use .c_str() first.
The second argument is optional, and specifies a char * to store a pointer to the character after the end of the number. This is useful when converting a string containing several integers, but if you don't need it, just set this argument to NULL.
The third argument is the radix (base) to convert. strtol can do anything from binary (base 2) to base 36. If you want strtol to pick the base automatically based on prefix, pass in 0.
So, the simplest usage would be
long l = strtol(input.c_str(), NULL, 0);
If you know you are getting decimal numbers:
long l = strtol(input.c_str(), NULL, 10);
strtol returns 0 if there are no convertible characters at the start of the string. If you want to check if strtol succeeded, use the middle argument:
const char *s = input.c_str();
char *t;
long l = strtol(s, &t, 10);
if(s == t) {
/* strtol failed */
}
If you're using C++11, use stol instead:
long l = stol(input);
Alternately, you can just use a stringstream, which has the advantage of being able to read many items with ease just like cin:
stringstream ss(input);
long l;
ss >> l;
Suppose you're given a string char const * str. Now convert it like this:
#include <cstdlib>
#include <cerrno>
char * e;
errno = 0;
long n = std::strtol(str, &e, 0);
The last argument 0 determines the number base you want to apply; 0 means "auto-detect". Other sensible values are 8, 10 or 16.
Next you need to inspect the end pointer e. This points to the character after the consumed input. Thus if all input was consumed, it points to the null-terminator.
if (*e != '\0') { /* error, die */ }
It's also possible to allow for partial input consumption using e, but that's the sort of stuff that you'll understand when you actually need it.
Lastly, you should check for errors, which can essentially only be overflow errors if the input doesn't fit into the destination type:
if (errno != 0) { /* error, die */ }
In C++, it might be preferable to use std::stol, though you don't get to pick the number base in this case:
#include <string>
try { long n = std::stol(str); }
catch (std::invalid_argument const & e) { /* error */ }
catch (std::out_of_range const & e) { /* error */ }
Quote from C++ reference:
long int strtol ( const char * str, char ** endptr, int base );
Convert string to long integer
Parses the C string str interpreting its content as an integral number of the specified base, which is returned as a long int value. If endptr is not a null pointer, the function also sets the value of endptr to point to the first character after the number.
So try something like
long l = strtol(pointerToStartOfString, NULL, 0)
I always use simply strol(str,0,0) - it returns long value. 0 for radix (last parameter) means to auto-detect it from input string, so both 0x10 as hex and 10 as decimal could be used in input string.
I have a small query regarding reading a set of characters from a structure. For example: A particular variable contains a value "3242C976*32" (char - type). How can I get only the first 8 bits of this variable. Kindly help.
Thanks.
Edit:
I'm trying to read in a signal:
For Ex: $ASWEER,2,X:3242C976*32
into this structure:
struct pg
{
char command[7]; // saves as $ASWEER,2,X:3242C976*32
char comma1[1]; // saves as ,2,X:3242C976*32
char groupID[1]; // saves as 2,X:3242C976*32
char comma2[1]; // etc
char handle[2]; // this is the problem, need it to save specifically each part, buts its not
char canID[8];
char checksum[3];
}m_pg;
...
When memcopying buffer into a structure, it works but because there is no carriage returns it saves the rest of the signal in each char variable. So, there is always garbage at the end.
you could..
convert your hex value in canID to float(depending on how you want to display it), e.g.
float value1 = HexToFloat(m_pg.canID); // find a conversion script for HexToFloat
CString val;
val.Format("0.3f",value1);
the garbage values aren't actually being stored in the structure, it only displays it as so, as there is no carriage return, so format the message however you want to and display it using the CString val;
If "3242C976*3F" is a c-string or std::string, you can just do:
char* str = "3242C976*3F";
char first_byte = str[0];
Or with an arbitrary memory block you can do:
SomeStruct memoryBlock;
char firstByte;
memcpy(&firstByte, &memoryBlock, 1);
Both copy the first 8bits or 1 byte from the string or arbitrary memory block just as well.
After the edit (original answer below)
Just copy by parts. In C, something like this should work (could also work in C++ but may not be idiomatic)
strncpy(m_pg.command, value, 7); // m.pg_command[7] = 0; // oops
strncpy(m_pg.comma, value+7, 1); // m.pg_comma[1] = 0; // oops
strncpy(m_pg.groupID, value+8, 1); // m.pg_groupID[1] = 0; // oops
strncpy(m_pg.comma2, value+9, 1); // m.pg_comma2[1] = 0; // oops
// etc
Also, you don't have space for the string terminator in the members of the structure (therefore the oopses above). They are NOT strings. Do not printf them!
Don't read more than 8 characters. In C, something like
char value[9]; /* 8 characters and a 0 terminator */
int ch;
scanf("%8s", value);
/* optionally ignore further input */
while (((ch = getchar()) != '\n') && (ch != EOF)) /* void */;
/* input terminated with ch (either '\n' or EOF) */
I believe the above code also "works" in C++, but it may not be idiomatic in that language
If you have a char pointer, you can just set str[8] = '\0'; Be careful though, because if the buffer is less than 8 (EDIT: 9) bytes, this could cause problems.
(I'm just assuming that the name of the variable that already is holding the string is called str. Substitute the name of your variable.)
It looks to me like you want to split at the comma, and save up to there. This can be done with strtok(), to split the string into tokens based on the comma, or strchr() to find the comma, and strcpy() to copy the string up to the comma.
My question is exactly the same as this one. That is, I'm trying to use scanf() to receive a string of indeterminate length, and I want scanf() to dynamically allocate memory for it.
However, in my situation, I am using VS2010. As far as I can see, MS's scanf() doesn't have an a or m modifier for when scanning for strings. Is there any way to do this (other than receiving input one character at a time)?
Standard versions of scanf() do not allocate memory for any of the variables it reads into.
If you've been hoodwinked into using a non-standard extension in some version of scanf(), you've just had your first lesson in how to write portable code - do not use non-standard extensions. You can nuance that to say "Do not use extensions that are not available on all the platforms of interest to you", but realize that the set of platforms may change over time.
Must you absolutely use scanf ? Aren't std::string s; std::cin >> s; or getline( std::cin, s ); an option for you?
If you want to use scanf you could just allocate a large enough buffer to hold any possible value, say 1024 bytes, then use a maximum field width specifier of 1024.
The m and a are specific non-standard GNU extensions, so thats why Microsofts compiler does not support them. One could wish that visual studio did.
Here is an example using scanf to read settings, and just print them back out:
#include <stdio.h>
#include <errno.h>
#include <malloc.h>
int
main( int argc, char **argv )
{ // usage ./a.out < settings.conf
char *varname;
int value, r, run = 1;
varname = malloc( 1024 );
// clear errno
errno = 0;
while( run )
{ // match any number of "variable = #number" and do some "processing"
// the 1024 here is the maximum field width specifier.
r = scanf ( "%1024s = %d", varname, &value );
if( r == 2 )
{ // matched both string and number
printf( " Variable %s is set to %d \n", varname, value );
} else {
// it did not, either there was an error in which case errno was
// set or we are out of variables to match
if( errno != 0 )
{ // an error has ocurred.
perror("scanf");
}
run = 0;
}
}
return 0;
}
Here is an example settings.conf
cake = 5
three = 3
answertolifeuniverseandeverything = 42
charcoal = -12
You can read more about scanf on the manpages.
And you can of course use getline(), and after that parse character after character.
If you would go into a little more what you are trying to achieve you could maybe get an better answer.
I think, in real world, one need to have some maximum limit on length of user input.
Then you may read the whole line with something like getline(). See http://www.cplusplus.com/reference/iostream/istream/getline/
Note that, if you want multiple input from user, you don't need to have separate char arrays for each of them. You can have one big buffer, e.g. char buffer[2048], for using with getline(), and copy the contents to a suitably allocated (and named) variable, e.g. something like char * name = strdup( buffer ).
Don't use scanf for reading strings. It probably doesn't even do what you think it does; %s reads only up until the next whitespace.