I am facing an issue with arduino, since I want to change the state of my device using an enum, but it doesn't seeem to work, my code looks like below. I am not entirely sure where it goes wrong, I think as well that the comparison between settingTo and toP2P could be wrong?
Thanks in advance!
String toP2P = "503250"
String toABP = "414250";
String settingTo = LoRa_Tx.dataRX.substring(indx);
if( settingTo == toP2P ) {
//switching to P2P
Serial.println("current mode 1 "+(String) LoRa_Tx.current_modeRxTx);
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaMod){
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaMod;
}
} else if(settingTo == toABP){
//switching to ABP
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaWan){
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaWan;}
}
}
My class has the enum defined as
typedef enum modeRxTx{LoRaMod, LoRaWan, Idle} ;
modeRxTx current_modeRxTx = Idle;
In general, you should avoid the String class, as it will eventually cause problems. However, given that the LoRa_Tx appears to have a String member, here is one way to watch for those two modes:
if ((indx > -1) && (LoRa_Tx.dataRx.length() >= indx+5)) {
const char *settingTo = &LoRa_Tx.dataRx.c_str()[ indx ];
if ( strncmp_P( settingTo, PSTR("503250"), 6 ) == 0 ) {
//switching to P2P
Serial.print( F("current mode 1 ") ); // <-- saves RAM!
Serial.println( LoRa_Tx.current_modeRxTx );
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaMod) {
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaMod;
}
} else if ( strncmp_P( settingTo, PSTR("414250"), 6 ) == 0 ) {
//switching to ABP
if(LoRa_Tx.current_modeRxTx != LoRa_Tx.LoRaWan) {
LoRa_Tx.current_modeRxTx = LoRa_Tx.LoRaWan;
}
}
}
Instead of creating a substring, it just makes a pointer to the actual characters of data_Rx. The c_str() function returns a pointer to the first character (zero-based index) or the String, and the [ indx ] is the first of the mode number characters. Finally, the & is a pointer to the first mode number character.
Next, it uses a standard library function, strncmp_P (documented here), to compare those mode number characters with the modes you are looking for, and it only compares up to 6 characters. You don't say if there's a delimiter after "503250", so I don't know if "50325076" is possible and should be rejected.
The strncmp_P expects to get a PROGMEM string as the second argument, not just a const char *, so that's what the PSTR macro does. This saves RAM because the PSTR will be stored and compared from FLASH memory (aka PROGMEM). The Serial.print statements should use the F() macro for the same reason.
Related
The answer provided in wide char and win32::api works for passing utf-16 to the Win API. But how do I convert utf16 strings returned by the Win API? (I am trying to use GetCommandLineW).
I have tried both Unicode::String and Encode::decode without success. I'm guessing that perhaps the data needs to be packed or unpacked first, but how?
After that, the next problem is how to deal with a pointer-to-pointer-to-utf16 like the one returned by CommandLineToArgvW.
Thanks for any help.
When you specify the return value is a string, Win32::API assumes it's a terminated by a byte with value 0, but bytes with that value are common in UTF-16le text.
As Win32::API suggests, you should use the N type (or Q on 64-bit builds) to get the pointer as a number, then read the pointed memory yourself. Win32::API's provides ReadMemory to read memory, but it requires knowing how much memory to read. That's not useful for NUL-terminated strings and wide NUL-terminated strings.
For wide NUL-terminated strings, Win32::API provides SafeReadWideCString. But SafeReadWideCString can return a string unrelated to the input on error, so I use my own decode_LPCWSTR instead.
use strict;
use warnings;
use feature qw( say state );
use open ':std', ':encoding('.do { require Win32; "cp".Win32::GetConsoleOutputCP() }.')';
use Config qw( %Config );
use Encode qw( decode encode );
use Win32::API qw( ReadMemory );
use constant PTR_SIZE => $Config{ptrsize};
use constant PTR_PACK_FORMAT =>
PTR_SIZE == 8 ? 'Q'
: PTR_SIZE == 4 ? 'L'
: die("Unrecognized ptrsize\n");
use constant PTR_WIN32API_TYPE =>
PTR_SIZE == 8 ? 'Q'
: PTR_SIZE == 4 ? 'N'
: die("Unrecognized ptrsize\n");
sub lstrlenW {
my ($ptr) = #_;
state $lstrlenW = Win32::API->new('kernel32', 'lstrlenW', PTR_WIN32API_TYPE, 'i')
or die($^E);
return $lstrlenW->Call($ptr);
}
sub decode_LPCWSTR {
my ($ptr) = #_;
return undef if !$ptr;
my $num_chars = lstrlenW($ptr)
or return '';
return decode('UTF-16le', ReadMemory($ptr, $num_chars * 2));
}
# Returns true on success. Returns false and sets $^E on error.
sub LocalFree {
my ($ptr) = #_;
state $LocalFree = Win32::API->new('kernel32', 'LocalFree', PTR_WIN32API_TYPE, PTR_WIN32API_TYPE)
or die($^E);
return $LocalFree->Call($ptr) == 0;
}
sub GetCommandLine {
state $GetCommandLine = Win32::API->new('kernel32', 'GetCommandLineW', '', PTR_WIN32API_TYPE)
or die($^E);
return decode_LPCWSTR($GetCommandLine->Call());
}
# Returns a reference to an array on success. Returns undef and sets $^E on error.
sub CommandLineToArgv {
my ($cmd_line) = #_;
state $CommandLineToArgv = Win32::API->new('shell32', 'CommandLineToArgvW', 'PP', PTR_WIN32API_TYPE)
or die($^E);
my $cmd_line_encoded = encode('UTF-16le', $cmd_line."\0");
my $num_args_buf = pack('i', 0); # Allocate space for an "int".
my $arg_ptrs_ptr = $CommandLineToArgv->Call($cmd_line_encoded, $num_args_buf)
or return undef;
my $num_args = unpack('i', $num_args_buf);
my #args =
map { decode_LPCWSTR($_) }
unpack PTR_PACK_FORMAT.'*',
ReadMemory($arg_ptrs_ptr, PTR_SIZE * $num_args);
LocalFree($arg_ptrs_ptr);
return \#args;
}
{
my $cmd_line = GetCommandLine();
say $cmd_line;
my $args = CommandLineToArgv($cmd_line)
or die("CommandLineToArgv: $^E\n");
for my $arg (#$args) {
say "<$arg>";
}
}
I have a problem in regards of extracting signed int from string in c++.
Assuming that i have a string of images1234, how can i extract the 1234 from the string without knowing the position of the last non numeric character in C++.
FYI, i have try stringstream as well as lexical_cast as suggested by others through the post but stringstream returns 0 while lexical_cast stopped working.
int main()
{
string virtuallive("Images1234");
//stringstream output(virtuallive.c_str());
//int i = stoi(virtuallive);
//stringstream output(virtuallive);
int i;
i = boost::lexical_cast<int>(virtuallive.c_str());
//output >> i;
cout << i << endl;
return 0;
}
How can i extract the 1234 from the string without knowing the position of the last non numeric character in C++?
You can't. But the position is not hard to find:
auto last_non_numeric = input.find_last_not_of("1234567890");
char* endp = &input[0];
if (last_non_numeric != std::string::npos)
endp += last_non_numeric + 1;
if (*endp) { /* FAILURE, no number on the end */ }
auto i = strtol(endp, &endp, 10);
if (*endp) {/* weird FAILURE, maybe the number was really HUGE and couldn't convert */}
Another possibility would be to put the string into a stringstream, then read the number from the stream (after imbuing the stream with a locale that classifies everything except digits as white space).
// First the desired facet:
struct digits_only: std::ctype<char> {
digits_only(): std::ctype<char>(get_table()) {}
static std::ctype_base::mask const* get_table() {
// everything is white-space:
static std::vector<std::ctype_base::mask>
rc(std::ctype<char>::table_size,std::ctype_base::space);
// except digits, which are digits
std::fill(&rc['0'], &rc['9'], std::ctype_base::digit);
// and '.', which we'll call punctuation:
rc['.'] = std::ctype_base::punct;
return &rc[0];
}
};
Then the code to read the data:
std::istringstream virtuallive("Images1234");
virtuallive.imbue(locale(locale(), new digits_only);
int number;
// Since we classify the letters as white space, the stream will ignore them.
// We can just read the number as if nothing else were there:
virtuallive >> number;
This technique is useful primarily when the stream contains a substantial amount of data, and you want all the data in that stream to be interpreted in the same way (e.g., only read numbers, regardless of what else it might contain).
This question already has answers here:
How to test whether stringstream operator>> has parsed a bad type and skip it
(5 answers)
Closed 8 years ago.
I am a little new to C++ and would really appreciate any input or suggestions! So with our intro course projects I have been looking for a way to ensure that when the prog. is asking for int values it correctly responds! That is it states its invalid in cases of both a double as well as string being entered! So if cin >> intVariable ... intVariable will not accept cin entry of "abdf" or 20.01.
So to achieve this I wrote the following function...It works but I am looking for your thoughts on how this process can be further improved!
void getIntegerOnly(int& intVariable, string coutStatement)
{
bool isInteger; // Check if value entered by user is int form or not
string tmpValue; // Variable to store temp value enetered by user
cout << coutStatement; // Output the msg for the cin statement
do
{
cin >> tmpValue; // Ask user to input their value
try // Use try to catch any exception caused by what user enetered
{
/* Ex. if user enters 20.01 then the if statement converts the
string to a form of int anf float to compare. that is int value
will be 20 and float will be 20.01. And if values do not match
then user input is not integer else it is. Keep looping untill
user enters a proper int value. Exception is 20 = 20.00 */
if (stoi(tmpValue) != stof(tmpValue))
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
else
{
isInteger = true; //Set to true!
clear_cin(); // Clear cin to ignore all text and space in cin!
}
}
catch (...) // If the exception is trigured!
{
isInteger = false; // Set to false!
clear_response(); // Clear response to state invalid
}
} while (!isInteger); //Request user to input untill int clause met
//Store the int value to the variable passed by reference
intVariable = stoi(tmpValue);
}
This is simply an example of getting users age and age is greater than zero when running a Win32 console based application! Thank you for the feedback :)
One way would be something like the following:
std::string str;
std::cin >> str;
bool are_digits = std::all_of(
str.begin(), str.end(),
[](char c) { return isdigit(static_cast<unsigned char>(c)); }
);
return are_digits ? std::stoi(str) : throw std::invalid_argument{"Invalid input"};
and catch the exceptions on the calling side (stoi can also throw std::out_of_range).
You can leverage the second parameter of stoi().
string tmpValue;
size_t readChars;
stoi(tmpValue, &readChars);
if(readChars == tmpValue.length())
{
// input was integer
}
EDIT: this will not work for strings containing "." (for example integers passed in scientific notation).
This is not my work, but the answer to this question is what you want. Pass the string to it as a reference. It will return true is your string is an integer.
How do I check if a C++ string is an int?
Here is my code
#include<iostream>
#include<Windows.h>
using namespace std;
#define BUFSIZE 4602
#define VARNAME TEXT("zzz")
int main()
{
TCHAR chNewEnv[BUFSIZE];
GetEnvironmentVariable(VARNAME, chNewEnv, BUFSIZE);
if(GetLastError()==ERROR_ENVVAR_NOT_FOUND)
{
cout<<"Hello";
}
else
{
cout<<"Bye";
}
return 0;
}
I am checking whether zzz environment variable is available or not. I need to do the same without using if(GetLastError()==ERROR_ENVVAR_NOT_FOUND). Is there any way?
I am doing the same program using C# in which I don't use GetLastError(). I need to make these two programs similar that is why I am asking without the use of GetLastError(). Here is my C# snippet
string abc =Environment.GetEnvironmentVariable("zzz");
if (abc == null || abc.ToUpper() == "NULL" || abc.ToUpper() == "NUL")
You have to use GetLastError, as you may encounter cases where a variable is defined with no value.
Such cases can be emulated with:
SetEnvironmentVariable( "foo", "" );
When GetEnvironmentVariable return 0, it may be that the variable doesn't exist, or that is exists with an empty content. In the later case, GetLastError returns 0.
If you don't care (that is: a nonexistent variable or an empty one is the same for you), then don't bother with GetLastError.
Side note. You should always make a first call with a NULL nSize argument, as the documentation states:
If lpBuffer is not large enough to hold the data, the return value is
the buffer size, in characters, required to hold the string and its
terminating null character and the contents of lpBuffer are undefined.
And, I just tested (Windows 7), in such case GetLastError returns 0 (awkward, if you ask me)
Edit: On Windows 7, when I set an user variable to "null", the value retrieved by GetEnvironmentVariable (MBCS) is a 5 bytes string 'n', 'u', 'l', 'l', '\0'
Code (UNICODE build):
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <Windows.h>
#define BUFSIZE 4602
#define VARNAME L"zzz"
const wchar_t * MyGetEnv( const wchar_t * pszVarName, wchar_t * pszVarValue,
size_t cbValue ) {
DWORD dwCopied = GetEnvironmentVariable( pszVarName, pszVarValue, cbValue );
// The line bellow MAY BE COMMENTED OUT IF YOU REALLY
// DON'T LIKE GETLASTERROR, AS cbCopied WILL BE ZERO FOR
// NON-EXISTENT VARIABLE
if ( GetLastError() != NO_ERROR ) return NULL; // doesn't exist, or error
if ( dwCopied == 0 ) return NULL; // var is empty
return pszVarValue;
}
int main() {
wchar_t szVarValue[ BUFSIZE ];
const wchar_t * pszVarValue = MyGetEnv( VARNAME, szVarValue,
_countof( szVarValue ) );
if ( pszVarValue == NULL ) {
printf( "No variable or empty value\n" );
} else if ( ( _wcsicmp( pszVarValue, L"null" ) == 0 ) ||
( _wcsicmp( pszVarValue, L"nul" ) == 0 ) ) {
printf( "Special 'null' or 'nul' value\n" );
} else {
wprintf( L"Value is %s\n", szVarValue );
}
return 0;
}
The most egregiously redundant code construct I often see involves using the code sequence
if (condition)
return true;
else
return false;
instead of simply writing
return (condition);
I've seen this beginner error in all sorts of languages: from Pascal and C to PHP and Java. What other such constructs would you flag in a code review?
if (foo == true)
{
do stuff
}
I keep telling the developer that does that that it should be
if ((foo == true) == true)
{
do stuff
}
but he hasn't gotten the hint yet.
if (condition == true)
{
...
}
instead of
if (condition)
{
...
}
Edit:
or even worse and turning around the conditional test:
if (condition == false)
{
...
}
which is easily read as
if (condition) then ...
Using comments instead of source control:
-Commenting out or renaming functions instead of deleting them and trusting that source control can get them back for you if needed.
-Adding comments like "RWF Change" instead of just making the change and letting source control assign the blame.
Somewhere I’ve spotted this thing, which I find to be the pinnacle of boolean redundancy:
return (test == 1)? ((test == 0) ? 0 : 1) : ((test == 0) ? 0 : 1);
:-)
Redundant code is not in itself an error. But if you're really trying to save every character
return (condition);
is redundant too. You can write:
return condition;
Declaring separately from assignment in languages other than C:
int foo;
foo = GetFoo();
Returning uselessly at the end:
// stuff
return;
}
I once had a guy who repeatedly did this:
bool a;
bool b;
...
if (a == true)
b = true;
else
b = false;
void myfunction() {
if(condition) {
// Do some stuff
if(othercond) {
// Do more stuff
}
}
}
instead of
void myfunction() {
if(!condition)
return;
// Do some stuff
if(!othercond)
return;
// Do more stuff
}
Using .tostring on a string
Putting an exit statement as first statement in a function to disable the execution of that function, instead of one of the following options:
Completely removing the function
Commenting the function body
Keeping the function but deleting all the code
Using the exit as first statement makes it very hard to spot, you can easily read over it.
Fear of null (this also can lead to serious problems):
if (name != null)
person.Name = name;
Redundant if's (not using else):
if (!IsPostback)
{
// do something
}
if (IsPostback)
{
// do something else
}
Redundant checks (Split never returns null):
string[] words = sentence.Split(' ');
if (words != null)
More on checks (the second check is redundant if you are going to loop)
if (myArray != null && myArray.Length > 0)
foreach (string s in myArray)
And my favorite for ASP.NET: Scattered DataBinds all over the code in order to make the page render.
Copy paste redundancy:
if (x > 0)
{
// a lot of code to calculate z
y = x + z;
}
else
{
// a lot of code to calculate z
y = x - z;
}
instead of
if (x > 0)
y = x + CalcZ(x);
else
y = x - CalcZ(x);
or even better (or more obfuscated)
y = x + (x > 0 ? 1 : -1) * CalcZ(x)
Allocating elements on the heap instead of the stack.
{
char buff = malloc(1024);
/* ... */
free(buff);
}
instead of
{
char buff[1024];
/* ... */
}
or
{
struct foo *x = (struct foo *)malloc(sizeof(struct foo));
x->a = ...;
bar(x);
free(x);
}
instead of
{
struct foo x;
x.a = ...;
bar(&x);
}
The most common redundant code construct I see is code that is never called from anywhere in the program.
The other is design patterns used where there is no point in using them. For example, writing "new BobFactory().createBob()" everywhere, instead of just writing "new Bob()".
Deleting unused and unnecessary code can massively improve the quality of the system and the team's ability to maintain it. The benefits are often startling to teams who have never considered deleting unnecessary code from their system. I once performed a code review by sitting with a team and deleting over half the code in their project without changing the functionality of their system. I thought they'd be offended but they frequently asked me back for design advice and feedback after that.
I often run into the following:
function foo() {
if ( something ) {
return;
} else {
do_something();
}
}
But it doesn't help telling them that the else is useless here. It has to be either
function foo() {
if ( something ) {
return;
}
do_something();
}
or - depending on the length of checks that are done before do_something():
function foo() {
if ( !something ) {
do_something();
}
}
From nightmarish code reviews.....
char s[100];
followed by
memset(s,0,100);
followed by
s[strlen(s)] = 0;
with lots of nasty
if (strcmp(s, "1") == 0)
littered about the code.
Using an array when you want set behavior. You need to check everything to make sure its not in the array before you insert it, which makes your code longer and slower.
Redundant .ToString() invocations:
const int foo = 5;
Console.WriteLine("Number of Items: " + foo.ToString());
Unnecessary string formatting:
const int foo = 5;
Console.WriteLine("Number of Items: {0}", foo);