How to do Bitwise AND(&) on CString values in MFC(VC++)? - visual-c++

HI,
How to do Bitwise AND(&) on CString values in MFC(VC++)?
Example :
CString NASServerIP = "172.24.15.25";
CString SystemIP = " 142.25.24.85";
CString strSubnetMask = "255.255.255.0";
int result1 = NASServerIP & strSubnetMask;
int result2 = SystemIP & strSubnetMask;
if(result1==result2)
{
cout << "Both in Same network";
}
else
{
cout << "not in same network";
}
How i can do bitwise AND on CString values ?
Its giving error as "'CString' does not define this operator or a conversion to a type acceptable to the predefined operator"

You don't. Peforming a bitwise-AND on two strings doesn't make a lot of sense. You need to obtain binary representations of the IP address strings, then you can perform whatever bitwise operations on them. This can be easily done by first obtaining a const char* from a CString then passing it to the inet_addr() function.
A (simple) example based on your code snippet.
CString NASServerIP = "172.24.15.25";
CString SystemIP = " 142.25.24.85";
CString strSubnetMask = "255.255.255.0";
// CStrings can be casted into LPCSTRs (assuming the CStrings are not Unicode)
unsigned long NASServerIPBin = inet_addr((LPCSTR)NASServerIP);
unsigned long SystemIPBin = inet_addr((LPCSTR)SystemIP);
unsigned long strSubnetMaskBin = inet_addr((LPCSTR)strSubnetMask);
// Now, do whatever is needed on the unsigned longs.
int result1 = NASServerIPBin & strSubnetMaskBin;
int result2 = SystemIPBin & strSubnetMaskBin;
if(result1==result2)
{
cout << "Both in Same network";
}
else
{
cout << "Not in same network";
}
The bytes in the unsigned longs are "reversed" from the string representation. For example, if your IP address string is 192.168.1.1, the resulting binary from inet_addr would be 0x0101a8c0, where:
0x01 = 1
0x01 = 1
0xa8 = 168
0xc0 = 192
This shouldn't affect your bitwise operations, however.
You of course need to include the WinSock header (#include <windows.h> is usually sufficient, since it includes winsock.h) and link against the WinSock library (wsock32.lib if you're including winsock.h).

Related

Can you combine the raw string modifier R"()" with a string variable?

Example
For example:
string MyString = "Normal\tString";
cout << MyString << endl;
produces the following: "Normal String"
Appending the raw string modifier to the string like so:
string MyString = R"(Normal\tString)";
cout << MyString << endl;
produces the following: "Normal\tString"
The Question
Is there a way to append the raw string modifier to a variable containing a string in order to print the raw form of the string contained within the variable?
string TestString = "Test\tString";
cout << R(TestString) << endl;
So you get: "Test\tString"
Is there a way to append the raw string modifier to a variable containing a string in order to print the raw form of the string contained within the variable?
No.
However, you can write a function that substitutes the characters that are defined by escape sequences by an appropriate string, i.e. replace the character '\t' by the string "\\t".
Sample program:
#include <iostream>
#include <string>
// Performs only one substitution of \t.
// Needs to be updated to do it for all occurrences of \t and
// all other escape sequences that can be found in raw strings.
std::string toRawString(std::string const& in)
{
std::string ret = in;
auto p = ret.find('\t');
if ( p != ret.npos )
{
ret.replace(p, 1, "\\t");
}
return ret;
}
int main()
{
std::string TestString = "Test\tString";
std::cout << toRawString(TestString) << std::endl;
}
Output:
Test\tString
This question is tagged as C++11, in which case rolling your own conversion function is probably the best call.
However, if you have a C++14 compiler, you can use the std::quoted stream manipulator:
#include <iostream>
#include <iomanip>
int main() {
string s = "Hello\tWorld!";
std::cout << std::quoted(s) << std::endl; // Prints "Hello\tWorld!"
}
Kind of. This works but it's not a pretty solution:
std::string strToInsert = " insert this "
std::string myRawString = R"(
raw string raw string raw string
raw string raw string raw string
)"; myRawString += strToInsert; myRawString += R"(raw string
raw string raw string raw string
)";

C++ converting an int to a string

I know this is extremely basic but I'm very new to C++ and can't seem to find an answer. I'm simply trying to convert a few integers to strings. This method works:
int a = 10;
stringstream ss;
ss << a;
string str = ss.str();
but when I need to convert the second and third ones like this:
int b = 13;
stringstream ss;
ss << a;
string str2 = ss.str();
int c = 15;
stringstream ss;
ss << b;
string str3 = ss.str();
I get this error:
'std::stringstream ss' previously declared here
Do I need to somehow close stringstream? I've noticed that if I put them far away from each other in my code the compiler doesn't mind but that doesn't seem like something I should do. Does anyone have suggestions?
You're trying to redeclare the same stringstream with the same name. You can modify your code like this in order to work :
int b = 13;
stringstream ss2;
ss2 << a;
string str2 = ss2.str();
Or like this if you don't want to redeclare it :
int b = 13;
ss.str(""); // empty the stringstream
ss.clear();
ss << a;
string str2 = ss.str();
You can also use , which is much quicker :
int c = 42;
std::string s = std::to_string(c);
The stringstream is a variable just like any other. To make the idiom work twice without change, put it in braces:
int a = 13;
string str2;
{
stringstream ss;
ss << a;
str2 = ss.str();
} // ss ceases to exist at the closing brace
int b = 15;
string str3;
{
stringstream ss; // now we can make a new ss
ss << b;
str3 = ss.str();
}
Since C++11, you can do
std::string str4 = std::to_string( b );
or (with c of arbitrary type)
std::string str5 = ( std::stringstream() << c ).str();
There are other solutions, of course.
The particular error you are getting is telling you that you can't declare two variables with the same name (ss in your case) within the same scope.
If you wanted to create a new stringstream you could call it something else.
But there are other ways to convert an int to a string.. you could use std::to_string().
try
#include <string>
int a = 10;
std::string s = std::to_string(a);
Make sure you declare:
using namespace std;
Then insert the code:
int a = 10;
ostringstream ssa;
ssa << a;
string str = ssa.str();
int b = 13;
ostringstream ssb;
ssb << b;
string str2 = ssb.str();
int c = 15;
ostringstream ssc;
ssc << c;
string str3 = ssc.str();
One of the simplest way i can think of doing it is:
string str = string(itoa(num));

C++/cli: How to convert String containing Bytes as characters to double

I have problem converting String^ containing 8 bytes as characters (as ascii) to double.
I want to take those 8 characters and convert them binary to double.
What would you recommend to do this conversion in C++/cli?
I was trying to use Marshal::Copy, Double::TryParse, etc.
Maybe I use wrong specifications of parameters, but I really lost my last hopes.
There must be something easy to do this conversion.
Thanks.
Well, the bad news is that the System.String class uses only Unicode encoding internally.
So if you give it bytes it will map them to its internal encoding hiding the original value.
The good news is that you can play with the System.Text.Encoding class to retrieve 8bits values corresponding to the unicode characters.
Here is a sample :
#include <iostream>
using namespace System;
using namespace System::Text;
int main()
{
int n = 123456;
double d = 123.456;
std::cout << n << std::endl;
std::cout << d << std::endl;
char* n_as_bytes = (char*)&n;
char* d_as_bytes = (char*)&d;
String^ n_as_string = gcnew String(n_as_bytes, 0, sizeof(n));
String^ d_as_string = gcnew String(d_as_bytes, 0, sizeof(d));
Encoding^ ascii = Encoding::GetEncoding("iso-8859-1");
array<Byte>^ n_as_array = ascii->GetBytes(n_as_string);
array<Byte>^ d_as_array = ascii->GetBytes(d_as_string);
cli::pin_ptr<unsigned char> pin_ptr_n = &n_as_array[0];
cli::pin_ptr<unsigned char> pin_ptr_d = &d_as_array[0];
unsigned char* ptr_n = pin_ptr_n;
unsigned char* ptr_d = pin_ptr_d;
int n_out = *(int*)ptr_n;
double d_out = *(double*)ptr_d;
std::cout << n_out << std::endl;
std::cout << d_out << std::endl;
return 0;
}
This should give you :
123456
123.456
123456
123.456
Not sure it is completely safe, but trying it in your context should be a good start to ensure it is viable. :)

Audio data (unsigned char) that have been manipulated cannot be played

I have trouble with playing audio data after they have been manipulated.
The only API I use is the alsa lib API on Linux (Ubuntu) in C.
I get the data from a 16 bits integer wave file in a unsigned char array (called buffer1) using read() and buffer1 can be played properly. I want the data to be passed to another unsigned char array (called buffer2) of the same size. If I just make a loop with buffer2[i] = buffer1[i], it works : buffer2 can be played properly. But in order to manipulate the data, I convert it to a float array then back to unsigned char (Until now I do not manipulate the audio data; I just convert them to float then back to unsigned char to test how it works). But now buffer2 does not make sound although all of its values are strictly identical to the values of buffer1 (I made a printf of many values of buffer1 and buffer2; they are all identical) ... All I did is casting from unsigned to float and vice versa...
Please any idea of what's wrong?
Victor
The values in buffer1 and buffer2 cannot be identical or it would work. Perhaps the formatting that you use in your printf command is masking the differences (%i, %f etc.). Rather than use printf, try setting a breakpoint and looking at the values using your debugger. This might help reveal what is actually going wrong.
EDIT:
Given your comments about how you perform the cast, I think that I can now help. The raw data coming in is of type unsigned char. On most platforms, this will be an integer value between 0 and 255. You want to convert this value to a float to do your manipulation. To make the data meaningful as a floating point type for any manipulation, you want to scale this range between +/- 1.0. This is what the "scale" variable is for in the following code.
#include <iostream>
#include <math.h>
int main()
{
const int BUFFER_LEN = 6;
const unsigned char channelDataIN[] = {0,255, 1, 254, 2, 253};
unsigned char channelDataOUT[BUFFER_LEN];
float channelDataF[BUFFER_LEN];
std::cout.precision(5);
float scale = powf(2.f, 8.f*sizeof(unsigned char) ) - 1.f;
for (int mm = 0; mm < BUFFER_LEN; ++mm)
{
std::cout << "Original = " << (int)channelDataIN[mm] << std::endl;
channelDataF[mm] = (float)(channelDataIN[mm]) * 2.f/scale - 1.f; //Float cast
std::cout << "Float conversion = " << channelDataF[mm] << std::endl;
channelDataOUT[mm] = (unsigned char) ceil( ( 1.f+channelDataF[mm] ) * scale/2.f );
std::cout << "Recovered = " << (int)channelDataOUT[mm] << std::endl;
if (channelDataIN[mm] == channelDataOUT[mm])
std::cout << "The output precisely equals the input" << std::endl << std::endl;
else
std::cout << "The output != input" << std::endl << std::endl;
}
return 0;
}
The output array of unsigned chars after converting the values back is identical to the input array. This is the output from the code . . .
Original = 0
Float conversion = -1
Recovered = 0
The output precisely equals the input
Original = 255
Float conversion = 1
Recovered = 255
The output precisely equals the input
Original = 1
Float conversion = -0.99216
Recovered = 1
The output precisely equals the input
Original = 254
Float conversion = 0.99216
Recovered = 254
The output precisely equals the input
Original = 2
Float conversion = -0.98431
Recovered = 2
The output precisely equals the input
Original = 253
Float conversion = 0.98431
Recovered = 253
The output precisely equals the input

stick integer to string and char*

How can I add an integer variable to a string and char* variable? for example:
int a = 5;
string St1 = "Book", St2;
char *Ch1 = "Note", Ch2;
St2 = St1 + a --> Book5
Ch2 = Ch1 + a --> Note5
Thanks
The C++ way of doing this is:
std::stringstream temp;
temp << St1 << a;
std::string St2 = temp.str();
You can also do the same thing with Ch1:
std::stringstream temp;
temp << Ch1 << a;
char* Ch2 = new char[temp.str().length() + 1];
strcpy(Ch2, temp.str().c_str());
for char* you need to create another variable that is long enough for both, for instance. You can 'fix' the length of the output string to remove the chance of overrunning the end of the string. If you do that, be careful to make this large enough to hold the whole number, otherwise you might find that book+50 and book+502 both come out as book+50 (truncation).
Here's how to manually calculate the amount of memory required. This is most efficient but error-prone.
int a = 5;
char* ch1 = "Book";
int intVarSize = 11; // assumes 32-bit integer, in decimal, with possible leading -
int newStringLen = strlen(ch1) + intVarSize + 1; // 1 for the null terminator
char* ch2 = malloc(newStringLen);
if (ch2 == 0) { exit 1; }
snprintf(ch2, intVarSize, "%s%i", ch1, a);
ch2 now contains the combined text.
Alternatively, and slightly less tricky and also prettier (but less efficient) you can also do a 'trial run' of printf to get the required length:
int a = 5;
char* ch1 = "Book";
// do a trial run of snprintf with max length set to zero - this returns the number of bytes printed, but does not include the one byte null terminator (so add 1)
int newStringLen = 1 + snprintf(0, 0, "%s%i", ch1, a);
char* ch2 = malloc(newStringLen);
if (ch2 == 0) { exit 1; }
// do the actual printf with real parameters.
snprintf(ch2, newStringLen, "%s%i", ch1, a);
if your platform includes asprintf, then this is a lot easier, since asprintf automatically allocates the correct amount of memory for your new string.
int a = 5;
char* ch1 = "Book";
char* ch2;
asprintf(ch2, "%s%i", ch1, a);
ch2 now contains the combined text.
c++ is much less fiddly, but I'll leave that to others to describe.
You need to create another string large enough to hold the original string followed by the number (i.e. append the character corresponding to each digit of the number to this new string).
Try this out:
char *tmp = new char [ stelen(original) ];
itoa(integer,intString,10);
output = strcat(tmp,intString);
//use output string
delete [] tmp;

Resources