I have this function which uses the winscard.h function SCardGetReaderDeviceInstanceId.
WCHAR SCardInstanceId(SCARDCONTEXT phContext, LPTSTR szReaderName) {
WCHAR szDeviceInstanceId[256];
DWORD cchDeviceInstanceId = 256;
long lReturn = SCardGetReaderDeviceInstanceId(phContext, szReaderName, szDeviceInstanceId, &cchDeviceInstanceId);
if (lReturn != SCARD_S_SUCCESS) {
cout << "Failed SCardGetReaderDeviceInstanceId, errorcode: " << std::hex << std::setfill('0') << std::setw(8) << lReturn << endl;
exit(1);
}
return szDeviceInstanceId;
}
But it gives me a wierd error message on the return line.
E0120 return value type does not match the function type
and
Error C2440 'return': cannot convert from 'WCHAR [256]' to 'WCHAR'
What can be the issue here? and how do I solve it?
I can't change the function type to WCHAR [256], it that even a type?
The function return type is WCHAR. You are trying to return a C-style array of WCHARs. This isn't possible. You can instead return an std::wstring object, so your code would look like this:
#include <string>
std::wstring SCardInstanceId(SCARDCONTEXT phContext, LPTSTR szReaderName) {
std::wstring szDeviceInstanceId;
DWORD cchDeviceInstanceId = 255;
szDeviceInstanceId.resize(cchDeviceInstanceId);
// I think it is safer to resize to 255 chars as it is implementation defined if the internal array has the null-terminator.
// If it does and you resize to 256, you will end up with a 257-element array...
long lReturn = SCardGetReaderDeviceInstanceId(phContext, szReaderName, szDeviceInstanceId.data(), &cchDeviceInstanceId); // from c++17
// long lReturn = SCardGetReaderDeviceInstanceId(phContext, szReaderName, &szDeviceInstanceId[0], &cchDeviceInstanceId);
// before c++17 'data' returns const reference, so SCardGetReaderDeviceInstanceId couldn't modify the buffer (compilation error)
szDeviceInstanceId.resize(cchDeviceInstanceId-1); // shrink the string length to the length actually occupied by characters
// -1 because cchDeviceInstanceId is length including null-terminator (according to docs), and resize expects length excluding null
if (lReturn != SCARD_S_SUCCESS) {
cout << "Failed SCardGetReaderDeviceInstanceId, errorcode: " << std::hex << std::setfill('0') << std::setw(8) << lReturn << endl;
exit(1);
}
return szDeviceInstanceId;
}
If the 4th parameter of SCardGetReaderDeviceInstanceId didn't output any data, you could just pass szDeviceInstanceId.size()+1 (+1 for null).
Also note, that the buffer will be allocated on the heap, unless SSO occurs (which is implementation defined, yet I don't think it would occur in any implementation in case of this long string).
As you can see the code is somewhat complex because of the differences in the management of the null-terminator. To make it simpler (but less beautiful in the C++ context) you can use std::wstring only to return the string:
std::wstring SCardInstanceId(SCARDCONTEXT phContext, LPTSTR szReaderName) {
WCHAR szDeviceInstanceId[255];
DWORD cchDeviceInstanceId = 255;
long lReturn = SCardGetReaderDeviceInstanceId(phContext, szReaderName, szDeviceInstanceId, &cchDeviceInstanceId);
if (lReturn != SCARD_S_SUCCESS) {
cout << "Failed SCardGetReaderDeviceInstanceId, errorcode: " << std::hex << std::setfill('0') << std::setw(8) << lReturn << endl;
exit(1);
}
return std::wstring(szDeviceInstanceId);
}
Please note, that doing it like this might be a bit less performant as you have to allocate both WCHAR[255] array and std::wstring array. It isn't going to matter most of the time, but it might be worth using the first method in a very performance-sensitive context.
You can return the array in the C manner as well, however it isn't recommended to do that in C++.
i try to make code which is multithreaded and at certain step i have to retrieve array made on heap.
this is the code:
the following function will call another function called read_bi5_to_bin and it will pass to it unsigned char* initialized as nullptr data_bin_buffer
int HTTPRequest::read_bi5_main(boost::filesystem::path p, ptime epoch)
{
boost::unique_lock<boost::mutex> read_bi5_to_bin_lock(m_read_bi5_to_binMutex,boost::defer_lock);
unsigned char *buffer;
size_t buffer_size;
int counter;
size_t raw_size = 0;
std::string filename_string = p.generic_string();
path p2 = p;
p2.replace_extension(".bin");
std::string filename_string_2_bin =p2.generic_string() ;
path p3 = p;
p3.replace_extension(".csv");
std::string filename_string_2_csv = p3.generic_string();
const char *filename = filename_string.c_str();
const char *filename_2_bin = filename_string_2_bin.c_str();
const char *filename_2_csv = filename_string_2_csv.c_str();
if (fs::exists(p) && fs::is_regular(p))
{
buffer_size = fs::file_size(p);
buffer = new unsigned char[buffer_size];
}
else {
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Error: couldn't access the data file. |"
<< filename << "|" << std::endl;
read_bi5_to_bin_lock.unlock();
return 2;
}
std::ifstream fin(filename, std::ifstream::binary);
//fin.open(filename, std::ifstream::binary);
fin.read(reinterpret_cast<char*>(buffer), buffer_size);
fin.close();
//5-11-2020 the next line will be commented and put in HTTPCLIent constructor
//mHTTPRequest_Symbol_str= mHTTPRequest_HTTPClient_shared_pointer->Get_mHttpClient_HttpSymbolPrepareGet_shared_pointer()->mSymbol_strGet() ;
std::size_t pos = mHTTPRequest_Symbol_str.find("JPY");// position of "h_ticks.bi5" in str
double PV;
if (pos != std::string::npos)
{
PV = PV_YEN_PAIR;
}
else
{
PV = PV_DOLLAR_PAIR;
}
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
//5-20-2020
//boost::shared_ptr<unsigned char> data_bin_buffer = boost::make_shared<unsigned char>() ;
//n47::tick_data *data = n47::read_bi5_to_bin(
// buffer, buffer_size, epoch, PV, &raw_size, data_bin_buffer.get());
unsigned char* data_bin_buffer = nullptr;
n47::tick_data *data = n47::read_bi5_to_bin(
buffer, buffer_size, epoch, PV, &raw_size, data_bin_buffer);
//5-11-2020 here i will save binary file
//boost::unique_lock<boost::mutex> read_bi5_to_bin_lock(m_read_bi5_to_binMutex);
std::string file_name_path_string=output_compressed_file_2(data_bin_buffer, raw_size, filename_2_bin);
read_bi5_to_bin_lock.unlock();
path file_name_path_2{ file_name_path_string };
buffer_size = 0;
if (fs::exists(file_name_path_2) && fs::is_regular(file_name_path_2))
{
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << boost::this_thread::get_id() <<"\t we can access the data .bin file. |"
<< filename_2_bin << "| with size ="<< fs::file_size(file_name_path_2) << std::endl;
read_bi5_to_bin_lock.unlock();
}
else {
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Error: couldn't access the data .bin file. |"
<< filename_2_bin << "|" << std::endl;
read_bi5_to_bin_lock.unlock();
return 2;
}
n47::tick_data_iterator iter;
//5-11-2020 here i will save file.csv from data which is pointer to vector to pointers to ticks
if (data == 0) {
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Failure: Failed to load the data!" << std::endl;
read_bi5_to_bin_lock.unlock();
//5-14-2020 file is empty
//return 0;
}
//5-15-2020 take care that without else ,error happens with empty files because data is pointer to vector of pointers to ticks .so when data is made inside read_bi5 ,it is made as null pointer and later it is assigned to vector if file has ticks.if file does not have ticks ,then it is just returned as null pointer .so when dereferencing null pointer we got error
else if (data->size() != (raw_size / n47::ROW_SIZE)) {
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "Failure: Loaded " << data->size()
<< " ticks but file size indicates we should have loaded "
<< (raw_size / n47::ROW_SIZE) << std::endl;
read_bi5_to_bin_lock.unlock();
//5-14-2020 file is empty
//return 0;
}
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << "time, bid, bid_vol, ask, ask_vol" << std::endl;
read_bi5_to_bin_lock.unlock();
counter = 0;
std::ofstream out_csv(filename_string_2_csv);
if (data == 0)
{
}
else if (data != 0)
{
////read_bi5_to_bin_lock.lock();
for (iter = data->begin(); iter != data->end(); iter++) {
//5-11-2020 here i will save file.csv from data which is pointer to vector to pointers to ticks>>>>>>>here i should open file stream for output and save data to it
out_csv << ((*iter)->epoch + (*iter)->td) << ", "
<< (*iter)->bid << ", " << (*iter)->bidv << ", "
<< (*iter)->ask << ", " << (*iter)->askv << std::endl;
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) <<
boost::this_thread::get_id() << "\t"<<((*iter)->epoch + (*iter)->td) << ", "
<< (*iter)->bid << ", " << (*iter)->bidv << ", "
<< (*iter)->ask << ", " << (*iter)->askv << std::endl;
read_bi5_to_bin_lock.unlock();
counter++;
}
////read_bi5_to_bin_lock.unlock();
}
out_csv.close();
//5-13-2020
//??5-17-2020 isolate multithreaded error
read_bi5_to_bin_lock.lock();
BOOST_LOG((*mHTTPRequest_LoggingInstance_shared_pointer).mloggerCoutLog) << ".end." << std::endl << std::endl
<< "From " << raw_size << " bytes we read " << counter
<< " records." << std::endl
<< raw_size << " / " << n47::ROW_SIZE << " = "
<< (raw_size / n47::ROW_SIZE) << std::endl;
read_bi5_to_bin_lock.unlock();
delete data;
delete[] buffer;
delete [] data_bin_buffer;
return 0;
}
then inside read_bi5_to_bin function ,there will be a call to another function n47::lzma::decompress . this is the code of read_bi5_to_bin:
tick_data* read_bi5_to_bin(
unsigned char *lzma_buffer, size_t lzma_buffer_size, pt::ptime epoch,
float point_value, size_t *bytes_read, unsigned char* buffer_decompressed) {
tick_data *result = 0;
// decompress
int status;
buffer_decompressed = n47::lzma::decompress(lzma_buffer,
lzma_buffer_size, &status, bytes_read);
if (status != N47_E_OK)
{
bytes_read = 0;
}
else {
// convert to tick data (with read_bin).
result = read_bin(buffer_decompressed, *bytes_read, epoch, point_value);
//delete[] buffer;
}
return result;
}
then inside n47::lzma::decompress there will be making an array on heap called outBuffer .this buffer i need to retrieve at read_bi5_main in data_bin_buffer
this is code for n47::lzma::decompress
unsigned char *decompress(
unsigned char *inBuffer, size_t inSize, int *status, size_t *outSize) {
unsigned char *outBuffer = 0;
elzma_file_format format = ELZMA_lzma;
elzma_decompress_handle handle;
handle = elzma_decompress_alloc();
if (handle == 0) {
*status = -1;
} else {
// decompression...
datastream ds(inBuffer, inSize);
*status = elzma_decompress_run(
handle,
inputCallback, static_cast<void*>(&ds),
outputCallback, static_cast <void*>(&ds),
format);
if (*status == ELZMA_E_OK) {
*outSize = ds.outData.size();
outBuffer = new unsigned char[ ds.outData.size() ];
std::copy(ds.outData.begin(), ds.outData.end(), outBuffer);
}
elzma_decompress_free(&handle);
}
return outBuffer;
}
when i run this it gives error.a very helpful one here told me that it is the data_bin_buffer which is the problem because it is just one byte.and advised me to avoid shared pointer.when i convert it to normal pointer it gives another error if initialzed it to nullptr.should i not initialize the pointer???
Your read_bi5_to_bin code is broken.
tick_data* read_bi5_to_bin(
unsigned char *lzma_buffer, size_t lzma_buffer_size, pt::ptime epoch,
float point_value, size_t *bytes_read, unsigned char* buffer_decompressed) {
tick_data *result = 0;
The code receives a pointer called buffer_decompressed.
// decompress
int status;
buffer_decompressed = n47::lzma::decompress(lzma_buffer,
lzma_buffer_size, &status, bytes_read);
Then it throws away the value it received and gets some other value.
if (status != N47_E_OK)
{
bytes_read = 0;
}
else {
// convert to tick data (with read_bin).
result = read_bin(buffer_decompressed, *bytes_read, epoch, point_value);
//delete[] buffer;
}
return result;
}
And it never returns or frees the value it stored in buffer_decompressed.
Ooops.
I found the problem in my code.
it is the way i pass pointer to unsigned char to read_bi5_to_bin .
at first I thought passing the pointer variable is correct"as if i am passing lvalue reference" but i was so much wrong.reference is different than pointer.
pointer variable is lvalue variable of type pointer.so it is copied into function making new lvalue variable in function .the new variable has same value of pointer passed.this value is the address to first unsigned char in array.
but what i really need is to pass pointer to pointer to unsigned char.then pointer to pointer will be copied into function.the value of copied variable will be address of pointer to unsigned char.this is what i need retrieve from function.
I used & operator to get pointer to pointer .then I read very useful comment suggesting using ** so i changed the code to use **.voila,it works
this is the modified code:
read_bi5_to_bin_lock2.lock();
//5-20-2020
//boost::shared_ptr<unsigned char> data_bin_buffer = boost::make_shared<unsigned char>() ;
//n47::tick_data *data = n47::read_bi5_to_bin(
// buffer, buffer_size, epoch, PV, &raw_size, data_bin_buffer.get());
unsigned char *data_bin_buffer = 0 ;
n47::tick_data *data = n47::read_bi5_to_bin(
buffer, buffer_size, epoch, PV, &raw_size, &data_bin_buffer);
//5-11-2020 here i will save binary file
//boost::unique_lock<boost::mutex> read_bi5_to_bin_lock(m_read_bi5_to_binMutex);
std::string file_name_path_string=output_compressed_file_2(&data_bin_buffer, raw_size, filename_2_bin);
read_bi5_to_bin_lock2.unlock();
and this is the modified code in read_bi5_to_bin:
tick_data* read_bi5_to_bin(
unsigned char *lzma_buffer, size_t lzma_buffer_size, pt::ptime epoch,
float point_value, size_t *bytes_read, unsigned char** buffer_decompressed) {
tick_data *result = 0;
// decompress
int status;
*buffer_decompressed = n47::lzma::decompress(lzma_buffer,
lzma_buffer_size, &status, bytes_read);
thanks alot to DavidSchwartz for his very helpful comment.
void reverse(char * str){
char * end = str;
cout << "str" << str << endl;//ABCDE
cout << "end" << end << endl;//ABCDE
char tmp;
if(str){
while(*end){++end; cout << end << endl;}//ABCDE-->BCDE-->CDE-->DE-->E--> NULL
--end;//end=E
cout <<"--end" << end << endl;
while(str<end){// do swap
tmp = *str;//*str = str[0]
*str++ = *end;//*end = last ele in str[]
*end-- = tmp;
}
}
}
My input is
char test[] = "ABCDE";
cout << test << endl; //ABCDE
reverse(test);
cout << test << endl; //EDCBA
I am feeling not good about the pointer, since c++ primer book says char* pointer to the first element of an array, but when I output the pointer end, it is the content of an array not the address.
Also, reverse(test), I mean to give the address of the first element in an array to the pointer, but it turns out give the whole elements to the pointer.
A char* variable is a pointer to a char. A char[] is an array of char. Now, an array of char can be accessed through a pointer, and for char* it is commonly used for string processing (it's used although for other types, but for char it's much more common).
char test[6] = "ABCDE";
char *start = &test[0]; // will point on A
Accessing the array with the pointer can be done with pointer arithmetic:
char *end = start + 5; // equivalent to char *end = &test[5]
Now when you do:
cout << test;
or
cout << start;
It's actually calling an overload of operator<< that takes a const char*. What this operator does is that it print char starting from the pointer passed until it reaches a null char ('\0').
If you want to print the address contained in the pointer and not the string, you have to cast it to void*:
cout << static_cast<void*>(start);
std::cout is overloaded to print strings for char* .
Try:
char *test = "ABCDE";
std::cout << (void *) test << std::endl;
I have a test function as follow:
[TestMethod]
void RipMichaelJacksonTest()
{
string expected = "Hello";
BSTR actual = SysAllocString(L"Hello");
Assert::AreEqual(expected, actual);
}
The assert part will of course fail.
Is there any Assert function that i can use?
Im new to VC++.
The problem is that you are doing a AreEqual. Passing in two parameters will force AreEqual(Object^, Object^) which:
Verifies that two specified objects are equal. The assertion fails if the objects are not equal.
What you are actually looking for is the comparison of a wchar* and a char*. There is not a direct comparison function between the two so it will be necessary to convert from a string to a wstring. There are lots of examples of how to do that, such as: https://stackoverflow.com/a/7159944/2642059 and you'll need to do something similar, for example:
wstring get_wstring(const string& s) {
wstring buf;
const char* cs = s.c_str();
const size_t wn = mbsrtowcs(nullptr, &cs, 0, nullptr);
if (wn == string::npos) {
cout << "Error in mbsrtowcs(): " << errno << endl;
} else {
buf.resize(wn + 1);
if(mbsrtowcs(&*buf.begin(), &cs, wn + 1, nullptr) == string::npos) {
cout << "Error in mbsrtowcs(): " << errno << endl;
buf.resize(0);
}
}
return buf;
}
The return of get_wstring(expected) and actual will now both be wchars and can thereby be compared in the using AreEqual(String^, String^, bool)
I have the following program which is giving run time error:
*The instruction at "x" referenced memory at "y"
The memory could not be written.*
Code:
int main() {
char *str1 = "Rain";
char *&str2 = str1;
cout << str1 << str2 << endl;
*str1 = 'M';
cout << str1 << str2 << endl;
//Here the error happens
*str2 = 'P';
cout << str1 << str2 << endl;
return 0;
}
What is the cause of this error.
The problem is that a string literal is technically a 'char const pointer'. Reading right to left a pointer to unmodifiable characters. Because of backward comparability with 'C' this can be auto cast to 'char pointer' by the compiler. This does not mean that the underlying type has changed and thus modifying the underlying const object is undefined behavior.
char *str1 = "Rain"; // Lie this is not a char*
char const* str9 = "Rain"; // This is the real type.
// String lieterals => "XXXXX" are char const*
If you want to modify the string what you need to do is declare an array.
char str6[] = "Rain";
str6[0] = 'M';
*str6 = 'P';