Why my fread stops when reading some file? - qt

//#include <QtCore/QCoreApplication>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include "shift.h"
using namespace::std;
int main(int argc, char *argv[])
{
unsigned char tmpBuf;
FILE* fp;
FILE* fp2;
char fname[50];
static unsigned int lSize, count, num;
cout << "Input the filename:" << endl;
cin >> fname;
fp = fopen(fname,"r");
if(fp == NULL) {
cout << "The file does not exist!" << endl;
exit(1);
}
// obtain file size:
fseek(fp , 0 , SEEK_END);
lSize = ftell(fp);
rewind(fp);
cout << "The intput file's size is: " << lSize << endl;
fp2 = fopen("myfile", "w");
while(1){
num = fread(&tmpBuf, 1, 1, fp);
count += num;
// putchar(tmpBuf);
// tmpBuf = cror(tmpBuf, 4);
// tmpBuf = crol(tmpBuf, 4);
fwrite(&tmpBuf, 1, num, fp2);
cout << tmpBuf << " " << num << " " << count << endl;
if (count == lSize){
printf("over\n");
break;
}
}
fclose(fp);
fclose(fp2);
while(1){}
return 0;
//return a.exec();
}
I made a Qt console program and disable QtCore, like above code. When read some file, e.g. 1.txt (which contains only 1234567890) it succeeds. But when reading some other file, e.g. 1.rar, it failed like below: Why?

Check the value of num coming back from
num = fread(&tmpBuf, 1, 1, fp);
If it comes back as 0, that would explain why
if (count == lSize){
never comes back as true to break you out of the loop.
As to why that could happen, you're opening fname in "r" mode but a rar file would be binary. For that, I'd suggest opening in "rb" mode. If fread expects txt format but hits the EOF indicator, it'll stop advancing so num = 0 and count won't increase.
I don't have windows available to test this, but other questions have come up on stackoverflow for this reason:
fread/ftell apparently broken under Windows, works fine under Linux

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;
}

SIGTSTP in codechef ide

I've written a code to solve Buying new tablet problem from codechef. Although everything goes well in CLION and Visual Studio, even outputs are correct, codechef compiler says runtime error SIGTSTP. I'm new to this site, can not understand what it says. I've done a little research on Google, but nothing.
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main(){
int T,N,B,W,H,P;
bool isGr = false;
cin >> T;
while (T--){
cin >> N;
cin >> B;
vector <int> tablets;
while (N--){
cin >> W;
cin >> H;
cin >> P;
if (P <= B) {
tablets.push_back(W*H);
isGr = true;
}
else isGr = false;
}
if (isGr){
sort(tablets.begin(),tablets.end());
cout << tablets.back() << endl;
tablets = {};
} else cout << "no tablet" << endl;
isGr = false;
}
}
The condition
'''else isGr=false;'''
in second while loop, is not required....

Reading from character device with Qt

I'm not very good at character devices, so I need your help. A have a char device(let's call it /dev/my_light) which is a light sensor. I have to read the data from this file and transform it to the brightness value and then pass it to the brightness manager that changes the brightness of my screen. The problem is that when I read the value for some period of time I get old values from the file.I assume there is a buffer(again not sure how character devices exactly work). Whereas when I use cat /dev/my_light I see new data! Is it possible to get rid off the buffer and read new values that were written to the file just right now. Here is my code in Qt:
void MySensor::updateMySensor()
{
Packet packet;
packet.startByte = 0;
packet.mantissa = 0;
packet.exp = 0;
d->device = ::open(d->path.toStdString().c_str(), O_RDONLY);
if (d->device == -1)
{
qDebug() << Q_FUNC_INFO << "can't open the sensor";
return;
}
ssize_t size = ::read(d->device, &packet, sizeof(packet));
close(d->device);
if (size == -1)
{
qDebug() << errno;
return;
}
packet.exp &= 0x0F;
float illumination = pow(2, packet.exp) * packet.mantissa * 0.045;
if(d->singleShot) emit lightSensorIsRunning(true);
emit illuminationRead(illumination);
}
The mySensor function is called every second. I tried to call it each 200 msec but it didn't help. The value of illumination stays old for about 7 seconds(!) whereas the value that I get from cat is new just immediately.
Thank you in advance!
I can't test with your specific device, however, I'm using the keyboard as a read only device.
The program attempts to connect to keyboard and read all keys pressed inside and outside the window. It's a broad solution you'll have to adapt to meet your demands.
Note that I'm opening the file with O_RDONLY | O_NONBLOCK which means open in read only mode and no wait for the event be triggered(some notifier needed to know when data is ready!) respectively.
You'll need super user privilege to run this example!
#include <QtCore>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
const char *device_name = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
int descriptor = open(device_name, O_RDONLY | O_NONBLOCK);
if (descriptor < 0)
{
qDebug() << "Error" << strerror(errno);
return a.exec();
}
QFile device;
if (!device.open(descriptor, QFile::ReadOnly))
{
qDebug() << "Error" << qPrintable(device.errorString());
return a.exec();
}
QSocketNotifier notifier(device.handle(), QSocketNotifier::Read);
QObject::connect(&notifier, &QSocketNotifier::activated, &notifier, [&](int socket){
Q_UNUSED(socket)
struct input_event ev;
QByteArray data = device.readAll();
qDebug() << "Event caught:"
<< "\n\nDATA SIZE" << data.size()
<< "\nSTRUCT COUNT" << data.size() / int(sizeof(input_event))
<< "\nSTRUCT SIZE" << sizeof(input_event);
qDebug() << ""; //New line
while (data.size() >= int(sizeof(input_event)))
{
memcpy(&ev, data.data(), sizeof(input_event));
data.remove(0, int(sizeof(input_event)));
qDebug() << "TYPE" << ev.type << "CODE" << ev.code << "VALUE" << ev.value << "TIME" << ev.time.tv_sec;
}
qDebug() << ""; //New line
});
return a.exec();
}

Qt5: compile error while QSharedPointer<const T>::create()

Is it "expected" for QSharedPointer::create() not to work or is it a bug? I get an error:
/usr/include/qt5/QtCore/qsharedpointer_impl.h:439:9: error:
invalid conversion from ‘const void*’ to ‘void*’ [-fpermissive]
new (result.data()) T(std::forward<Args>(arguments)...);
casting from nonconst shared pointer and constructor from raw const pointer work.
I got this for Qt5.7.0 and Qt5.10.0.
Here is a minimal example:
#include <QSharedPointer>
struct A {};
int main(int argc, char *argv[])
{
auto ca = QSharedPointer<const A>::create();
return 0;
}
Here is one file (not minimal) example but with few working cases, 2 not working and a debug. Commented defines are for "not compiling" parts.
#include <QSharedPointer>
#include <QDebug>
#define FROM_PTR
//#define CONST_CREATE
#define FROM_RAW_PTR
#define PERFECT_FORWARD_CREATE
//#define PERFECT_FORWARD_CREATE_CONST
#define BUILTIN_CAST
class A
{
public:
A() = default;
A(int i) : _i{i} {}
void foo() const { qDebug() << "const foo" << _i; }
void foo() { qDebug() << "foo" << ++_i; }
private:
int _i{0};
};
using ASPtr = QSharedPointer<A>;
using ASCPtr = QSharedPointer<const A>;
int main(int argc, char *argv[])
{
Q_UNUSED(argc)
Q_UNUSED(argv)
#ifdef FROM_PTR
qDebug() << "FROM_PTR";
auto a1 = ASPtr::create();
a1->foo();
auto ca1 = static_cast<ASCPtr>(a1);
ca1->foo();
qDebug() << "\n";
#endif // FROM_PTR
#ifdef CONST_CREATE
qDebug() << "CONST_CREATE";
auto ca2 = ASCPtr::create();
ca2->foo();
qDebug() << "\n";
#endif // CONST_CREATE
#ifdef FROM_RAW_PTR
qDebug() << "FROM_RAW_PTR";
auto ca3 = ASCPtr(new const A);
ca3->foo();
qDebug() << "\n";
#endif // FROM_RAW_PTR
#ifdef PERFECT_FORWARD_CREATE
qDebug() << "PERFECT_FORWARD_CREATE";
auto a2 = ASPtr::create(10);
a2->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef PERFECT_FORWARD_CREATE_CONST
qDebug() << "PERFECT_FORWARD_CREATE_CONST";
auto ca4 = ASCPtr::create(20);
ca4->foo();
qDebug() << "\n";
#endif // PERFECT_FORWARD_CREATE
#ifdef BUILTIN_CAST
qDebug() << "BUILTIN_CAST";
QSharedPointer<A> a3 = ASPtr::create();
a3->foo();
auto ca4 = a3.constCast<const A>();
ca4->foo();
qDebug() << "\n";
#endif // BUILTIN_CAST
return 0;
}
That is a known Qt bug (QTBUG-49748). Although it is marked as resolved in Qt 5.6.0, the bug is still present as pointed out in the comments.
Why is this happening?
Look at the implmentation of the class QSharedPointer qsharedpointer_impl.h.
In particular the line:
new (result.data()) T(std::forward<Args>(arguments)...);
uses the result.data() as the new expression placement params. Unfortunately, one can not use a const pointer as a placement param (have a look at this question here on SO for more details).
Hence, there's not much you can do except reporting this to Qt developers via the official bug tracker.
You may have a look at the smart pointers provided by the standard library (e.g. std::shared_ptr) if you are not forced to use Qt ones.
UPDATE
As reported in Qt bug tracker, this bug was fixed in version 5.11 (here is the related commit). Basically, they used std::remove_cv to remove the topmost const from the type specified.

OpenCL Vector add program

I'm absolutely new to OpenCL programming. I have a working installation of OpenCL library and drivers. But the program I'm trying to run is not producing expected output (Output is all zeros). It is just a simple vector_add program.
Thanks in advance for suggestions.
int main(int argc, char** argv)
{
cout << "Hello OpenCL" << endl;
vector<Platform> all_platforms;
int err = Platform::get(&all_platforms);
cout << "Getting Platform ... Error code " << err << endl;
if (all_platforms.size()==0)
(cout << "No platforms" << endl, exit(0));
cout << "Platform info : " << all_platforms[0].getInfo<CL_PLATFORM_NAME>() << endl;
Platform default_platform = all_platforms[0];
cout << "Defaulting to it ..." << endl;
vector<Device> all_devices;
err = default_platform.getDevices(CL_DEVICE_TYPE_GPU, &all_devices);
cout << "Getting devices ... Error code : " << err << endl;
if (all_devices.size()==0)
(cout << "No devices" << endl, exit(0));
Device default_device = all_devices[0];
cout << all_devices.size() << " devices & " << "Device info : " << all_devices[0].getInfo<CL_DEVICE_NAME>() << endl;
cout << "Defaulting to it ..." << endl;
Context context(default_device);
Program::Sources sources;
std::string kernel_code=
" void kernel simple_add(global const int* A, global const int* B, global int* C){"
" unsigned int i = get_global_id(0); "
" C[i]=A[i]+B[i]; "
" } ";
sources.push_back(make_pair(kernel_code.c_str(), kernel_code.length()+1));
Program program(context, sources);
if (program.build(all_devices)==CL_SUCCESS)
cout << "Built Successfully" << endl;
Buffer buffer_A(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_B(context,CL_MEM_READ_WRITE,sizeof(int)*10);
Buffer buffer_C(context,CL_MEM_READ_WRITE,sizeof(int)*10);
int A[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
int B[] = {0, 1, 2, 0, 1, 2, 0, 1, 2, 0};
CommandQueue queue(context,default_device);
queue.enqueueWriteBuffer(buffer_A,CL_TRUE,0,sizeof(int)*10,A); // load data from host to device
queue.enqueueWriteBuffer(buffer_B,CL_TRUE,0,sizeof(int)*10,B);
Kernel kernel(program, "vector_add");
kernel.setArg(0, buffer_A);
kernel.setArg(1, buffer_B);
kernel.setArg(2, buffer_C);
queue.enqueueNDRangeKernel(kernel,cl::NullRange,cl::NDRange(10),cl::NullRange);
queue.finish();
int *C = new int[10];
queue.enqueueReadBuffer(buffer_C, CL_TRUE, 0, 10 * sizeof(int), C);
for (int i=0;i<10;i++)
std::cout << A[i] << " + " << B[i] << " = " << C[i] << std::endl;
return 0;
}
As pointed out in the comments, you should always check the error codes when using OpenCL API functions. This can be achieved by enabling exception handling in the C++ wrapper:
#define __CL_ENABLE_EXCEPTIONS // with cl.hpp
//#define CL_HPP_ENABLE_EXCEPTIONS // with cl2.hpp
#include <CL/cl.hpp>
int main(int argc, char *argv[])
{
try
{
// OpenCL code here
}
catch (cl::Error& err)
{
cout << err.what() << " failed with error code " << err.err() << endl;
}
}
If you do this, you will receive useful information about a couple of issues with your code.
The clCreateKernel function returns CL_INVALID_NAME. In your kernel, you define the kernel function with the name simple_add, but then you try and create a kernel object using the name vector_add.
If you have an OpenCL platform with multiple devices, you may also receive an error when building your kernel program. This is because you are creating an OpenCL context with a single device, but then trying to build the program for a list of devices:
Context context(default_device);
// ...
if (program.build(all_devices)==CL_SUCCESS)
cout << "Built Successfully" << endl;
The simplest fix is just to remove the argument from the build function, since by default it will build the program for all devices in the context (which is almost always what you actually want):
if (program.build()==CL_SUCCESS)
cout << "Built Successfully" << endl;

Resources