Pass struct to function through pthread - unix

How do I pass a struct through the pthread_create to my function? The errors I keep getting are that lower and upper has not been defined which would lead me to believe that the struct was not passed properly. I have tried referencing lower as arg1.lower and my error back is saying im trying to request for the member of a non class type void*
void * mergeSortThread(void *arg1){
std::ostringstream ostr;
ostr << "begin: " << lower << " " << upper << endl;
string message = ostr.str();
write(2, message.data(), message.length());
}
int main(int argc, char** argv)
{
struct MergeSortThreadArg
{
int * array;
int * temp;
int lower, upper;
};
pthread_attr_t attr;
pthread_attr_init(&attr);
int arr[20];
int temp[20];
MergeSortThreadArg arg;
arg.array = arr;
arg.temp = temp;
arg.lower = 0;
arg.upper = 19;
pthread_create(th, &attr, mergeSortThread, &arg);
pthread_join(th[z], NULL);
return 0;
}

Define struct before mergeSortThread() and add casting of arg1 to struct MergeSortThreadArg * it in mergeSortThread():
void * mergeSortThread(void *arg1){
struct MergeSortThreadArg *p_MST = (struct MergeSortThreadArg *)arg1;
std::ostringstream ostr;
ostr << "begin: " << p_MST->lower << " " << p_MST->upper << endl;
...
Moreover, it's more correct/safe to allocate the struct and its fields (array and tmp) to avoid passing to new thread data located on stack of another thread.

Related

Converting std::vector from BYTE to int

Code:
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
void CCreateReportDlg::GetColumnIndexesToExclude()
{
const CString strSection = theApp.GetActiveScheduleSection(_T("Options"));
ByteVector vData = theApp.GetProfileVector(strSection, _T("AssignStatesEx"));
ColumnIndexVector vTemp(vData.begin(), vData.end()); // This converts BYTE to int
m_vColumnIndexesToExclude = vTemp;
}
Is there any way to avoid the requirement for vTemp without manually iterating vData and casting from BYTE to int?
Yes, just use assign(). IDK if you need to use clear() as well, but probably not. Just step through the runtime code the first time to know.
m_vColumnIndexesToExclude.assign(vData.begin(), vData.end());
Here's a test program:
#include <windows.h>
#include <iostream>
#include <vector>
using namespace std;
using ColumnIndexVector = std::vector<int>;
using ByteVector = std::vector<BYTE>;
int main(int argc, char* argv[])
{
cout << "Test" << endl;
ByteVector bytes = {'A', 'B', 'C', 'D'};
ColumnIndexVector colVector;
for ( auto _val: bytes)
{
cout << _val << endl;
}
colVector.assign(bytes.begin(), bytes.end());
for ( auto _val : colVector)
{
cout << _val << endl;
}
return 0;
}

How to change this pass by reference into pointer as function parameter

wanting to ask how to change this pass by reference into pass by pointer, cause some of my school works need pass by pointer and i doesn't really understand how to modified this code using pass by pointer
void convert(string &s){
for (int i =0; i<s.length(); i++){
s[i] = toupper(s[i]);
}
}
int main(){
string name;
cout<<"Enter your name"<<endl;
getline(cin,name);
convert(name);
cout<<name<<endl;
return 0;
}
First of all, there are some minor errors in the code.
Inlcude necessary headers.
Use std:: namespace prefix.
#include <iostream>
#include <string>
#include <cctype>
void convert(std::string &s){
for (int i =0; i < s.length(); i++){
s[i] = std::toupper(s[i]);
}
}
int main(){
std::string name;
std::cout << "Enter your name: ";
std::getline(std::cin, name);
convert(name);
std::cout << name << std::endl;
return 0;
}
Using pointer version?
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#define SIZE 100
void convert(char *s, size_t size){
for (int i =0; i < size; i++){
s[i] = std::toupper(s[i]);
}
}
int main(){
char name[SIZE];
std::cout << "Enter your name: ";
std::fgets(name, SIZE, stdin);
convert(name, strlen(name));
std::cout << name << std::endl;
return 0;
}
Another version using pointers
#include <iostream>
#include <string>
#include <cctype>
void convert(std::string *s){
for (int i =0; i < s -> length(); i++){
(*s)[i] = std::toupper((*s)[i]);
}
}
int main(){
std::string *name = new std::string();
std::cout << "Enter your name: ";
std::getline(std::cin, *name);
convert(name);
std::cout << *name << std::endl;
delete name;
return 0;
}

Equality operator for QFlags with scoped enum

I have some flags defined as follows, using a scoped enum:
enum class Capability : int
{
NoCapabilities = 0,
SomethingCool = 1,
UberCool = 1 << 1,
EvenCooler = 1 << 2,
};
Q_DECLARE_FLAGS( Capabilities, Capability )
Now, I am trying to use the equality operator:
Capabilities(DataCapability::NoCapabilities) == Capability::NoCapabilities
I cannot use testFlag in the current example, since NoCapabilities = 0. This works if the enum is not scoped (removing class keyword).
Apparently, casting to int (static_cast<int>(NoCapabilities)) works, but it's really ugly.
What is the approach to solve this?
Is it a bad practice to have a 0 zero value and test it?
You can overload equality operator for your combination of data types. However cast ist still necessary but hidden by operator.
#include <QCoreApplication>
#include <QFlags>
#include <iostream>
enum class Capability : int
{
NoCapabilities = 0,
SomethingCool = 1,
UberCool = (1 << 1),
EvenCooler = (1 << 2),
};
Q_DECLARE_FLAGS(Capabilities, Capability)
template <typename T>
bool operator==(const QFlags<T> lhs, const Capability rhs)
{
return (QFlags<T>::Int(lhs) == static_cast<int>(rhs));
}
int main(int argc, char *argv[])
{
Q_UNUSED(argc);
Q_UNUSED(argv);
if (Capabilities(Capability::NoCapabilities) == Capability::NoCapabilities)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
if (Capabilities(Capability::EvenCooler) == Capability::NoCapabilities)
{
std::cout << "true" << std::endl;
}
else
{
std::cout << "false" << std::endl;
}
return 0;
}

Is it possible to have a const reference to a nonconst char pointer?

Is it possible to have a const reference to *argv and iterate through the array of pointers argv?
For the code below, I get the following warning:
a reference of type "const char *& (not const-qualified) cannot be initialized with a value of type "char *"
After building, I get this error message:
cannot convert from 'char *' to 'const char *&'.
#import <iostream>
using std::cout;
using std::endl;
int main (int argc, char * argv []) {
for (const char *& c = *argv; *c != '\0'; ++c) {
cout << *c << endl;
}
return 0;
}
I am confused because I know it is possible to have a const reference to a non-const variable like so:
int i = 42;
int &r1 = i;

How to create a Queue of unsigned char array in Qt?

I am new in Queue (FIFO) and Qt. I want to create a Queue of unsigned char array in Qt. How to do it? Please help
unsigned char buffer[1024];
If you want to use the Qt API, then you can use the QQueue class -
QQueue<unsigned char> queue;
queue.enqueue(65);
queue.enqueue(66);
queue.enqueue(67);
while (!queue.isEmpty())
cout << queue.dequeue() << endl;
If you want to build the queue on your own, then I guess you can declare a Queue class like this -
class Queue
{
private:
enum{SIZE=1024, EMPTY=0};
unsigned char buffer[SIZE];
int readHead, writeHead;
public:
Queue()
{
readHead = writeHead = EMPTY;
}
void push(unsigned char data);
unsigned char pop();
unsigned char peek();
bool isEmpty();
};
void Queue::push(unsigned char data)
{
if((readHead - writeHead) >= SIZE)
{
// You should handle Queue overflow the way you want here.
return;
}
buffer[writeHead++ % SIZE] = data;
}
unsigned char Queue::pop()
{
unsigned char item = peek();
readHead++;
return item;
}
unsigned char Queue::peek()
{
if(isEmpty())
{
// You should handle Queue underflow the way you want here.
return;
}
return buffer[readHead % SIZE];
}
bool Queue::isEmpty()
{
return (readHead == writeHead);
}
If you want to maintain a Queue of unsigned char array, then you will have to maintain a queue of unsigned char pointers -
QQueue<unsigned char *> queue;
unsigned char *array1 = new unsigned char[10]; // array of 10 items
array1[0] = 65;
array1[1] = 66;
queue.enqueue(array1);
unsigned char *array2 = new unsigned char[20]; // an array of 20 items
queue.enqueue(array2);
unsigned char *arr = queue.dequeue();
qDebug() << arr[0] << ", " << arr[1];
Note: You should take care of the memory cleanup after you are done with this queue. IMHO, you better avoid this type of design though.

Resources