Pointer related question. I'm going through some example code that currently reads in data from a file called dataFile into a buffer. The reading is done inside a loop as follows:
unsigned char* buffer = (unsigned char*)malloc(1024*768*);
fread(buffer,1,1024*768,dataFile);
redPointer = buffer;
bluePointer = buffer+1024;
greenPointer = buffer+768;
Now, I want to try and write the entire contents of the array buffer to a file, so that I can save just those discrete images (and not have a large file). However, I am not entirely sure how to go about doing this.
I was trying to cout statements, however I get a print-out of garbage characters on the console and also a beep from the PC. So then I end my program.
Is there an alternative method other than this:
for (int i=0; i < (1024*768); i++) {
fprintf(myFile, "%6.4f , ", buffer[i]);
}
By declaring your buffer as a char*, any pointer arithmatic or array indexes will use sizeof(char) to calculate the offset. A char is 1 byte (8 bits).
I'm not sure what you are trying to do with the data in your buffer. Here are some ideas:
Print the value of each byte in decimal, encoded as ASCII text:
for (int i=0; i < (1024*768); i++) {
fprintf(myFile, "%d , ", buffer[i]);
}
Print the value of each byte in hexadecimal, encoded in ASCII text:
for (int i=0; i < (1024*768); i++) {
fprintf(myFile, "%x , ", buffer[i]);
}
Print the value of each floating point number, in decimal, encoded in ASCII text (I think my calculation of the array index is correct to process adjacent non-overlapping memory locations for each float):
for (int i=0; i < (1024*768); i += sizeof(float)) {
fprintf(myFile, "%6.4f , ", buffer[i]);
}
Split the buffer into three files, each one from a non-overlapping section of the buffer:
fwrite(redPointer, sizeof(char), 768, file1);
fwrite(greenPointer, sizeof(char), 1024-768, file2);
fwrite(bluePointer, sizeof(char), (1024*768)-1024, file3);
Reference for fwrite. Note that for the count parameter I simply hard-coded the offsets that you had hard-coded in your question. One could also subtract certain of the pointers to calculate the number of bytes in each region. Note also that the contents of these three files will only be sensible if those are sensibly independent sections of the original data.
Maybe this gives you some ideas.
Updated: so I created a complete program to compile and test the formatting behavior. This only prints the first 20 items from the buffer. It compiles (with gcc -std=c99) and runs. I created the file /tmp/data using ghex and simply filled in some random data.
#include <stdlib.h>
#include <stdio.h>
int main()
{
FILE* dataFile = fopen("/tmp/data", "rb");
if (dataFile == NULL)
{
printf("fopen() failed");
return -2;
}
unsigned char* buffer = (unsigned char*)malloc(1024*768);
if (buffer == NULL)
{
printf("malloc failed");
return -1;
}
const int bytesRead = fread(buffer,1,1024*768,dataFile);
printf("fread() read %d bytes\n", bytesRead);
// release file handle
fclose(dataFile); dataFile = NULL;
printf("\nDecimal:\n");
for (int i=0; i < (1024*768); i++) {
printf("%hd , ", buffer[i]);
if (i > 20) { break; }
}
printf("\n");
printf("\nHexadecimal:\n");
for (int i=0; i < (1024*768); i++) {
printf("%#0hx , ", buffer[i]);
if (i > 20) { break; }
}
printf("\n");
printf("\nFloat:\n");
for (int i=0; i < (1024*768); i += sizeof(float)) {
printf("%6.4f , ", (float)buffer[i]);
if (i > 20) { break; }
}
printf("\n");
return 0;
}
Related
I have recently started programming in UNIX environment. I need to write a program which creates an empty file with name and size given in the terminal using this commands
gcc foo.c -o foo.o
./foo.o result.txt 1000
Here result.txt means the name of the newly created file, and 1000 means the size of the file in bytes.
I know for sure that lseek function moves the file offset, but the trouble is that whenever I run the program it creates a file with a given name, however the size of the file is 0.
Here is the code of my small program.
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/stat.h>
int main(int argc, char **argv)
{
int fd;
char *file_name;
off_t bytes;
mode_t mode;
if (argc < 3)
{
perror("There is not enough command-line arguments.");
//return 1;
}
file_name = argv[1];
bytes = atoi(argv[2]);
mode = S_IWUSR | S_IWGRP | S_IWOTH;
if ((fd = creat(file_name, mode)) < 0)
{
perror("File creation error.");
//return 1;
}
if (lseek(fd, bytes, SEEK_SET) == -1)
{
perror("Lseek function error.");
//return 1;
}
close(fd);
return 0;
}
If you aren't allowed to use any other functions to assist in creating a "blank" text file, why not change your file mode on creat() then loop-and-write:
int fd = creat(file_name, 0666);
for (int i=0; i < bytes; i++) {
int wbytes = write(fd, " ", 1);
if (wbytes < 0) {
perror("write error")
return 1;
}
}
You'll want to have some additional checks here but, that would be the general idea.
I don't know whats acceptable in your situation but, possibly adding just the write() call after lseek() even:
// XXX edit to include write
if ((fd = creat(file_name, 0666)) < 0) {
perror("File creation error");
//return 1;
}
// XXX seek to bytes - 1
if (lseek(fd, bytes - 1, SEEK_SET) == -1) {
perror("lseek() error");
//return 1;
}
// add this call to write a single byte # position set by lseek
if (write(fd, " ", 1) == -1) {
perror("write() error");
//return 1;
}
close(fd);
return 0;
I am trying to reconstruct an image from a file which is in Intel hex 386 format. After parsing the file all the data I am copying to a QByteArray and same array is used to create a QImage Object. But whatever image is which I got after reconstructing is not perfect. I am getting blue color instead of black, edges are not clear etc. The text file which I am parsing is a ram memory dump from STM32F4 controller (arm).The image is stored in RGB565 format.
Code to create the image:
{
QString strFilename;
Hex386Parser oFileParser;
strFilename = QFileDialog::getOpenFileName(this,"Select a file", QDir::homePath());
oFileParser.parseFile(strFilename, oByteArray);
QImage image(320, 240, QImage::Format_RGB16);
for (int y = 0; y < image.height(); y++)
{
memcpy(image.scanLine(y), oByteArray.constData() + y * image.bytesPerLine(),
image.bytesPerLine());
}
qDebug() <<"Size of the byte array is " <<oByteArray.size();
QLabel *label = new QLabel();
label->setPixmap(QPixmap::fromImage(image));
label->show();
}
Code to used to parse the file:
#define QT_NO_CAST_TO_ASCII
void Hex386Parser::parseFile(QString strFilename,QByteArray& ref_ByteArray)
{
QFile oFile(strFilename);
std::stringstream sstr;
QString strLength;
int unLength = 0, unAddress = 0,unDescriptor =0xFFFF,nIndex =0,nlineno=0;
if (oFile.open((QIODevice::ReadOnly | QIODevice::Text)))
{
QTextStream in(&oFile);
while (!in.atEnd())
{
QString line = in.readLine();
nIndex = 0;
nlineno++;
//unsigned char *pCharFrame = (unsigned char *)line.toStdString().c_str();
if (':' != line.at(nIndex))
{
// file corrupted
return;
}
nIndex++;
{
strLength = line.mid(nIndex, 2);
sstr << strLength.toStdString();
sstr << std::hex;
sstr >> unLength; // get length of the record
strLength.clear();
sstr.clear();
}
nIndex += 2;
unAddress = line.mid(nIndex,4).toInt(); // get address bytes
nIndex +=4;
unDescriptor = line.mid(nIndex, 2).toInt(); // get data descriptor
nIndex += 2;
switch(unDescriptor)
{
case data_record:
ref_ByteArray.append((line.mid(nIndex, unLength )));
// add data to bytearray
break;
case end_of_file_record:
break;
case extended_segment_address_record:
break;
case extended_linear_address_record:
break;
case start_linear_address_record:
break;
}
}
oFile.close();
}
}
What am I doing wrong??
The line contains hex string data representations where each byte is coded as two characters.
You want binary bytes. So, 2 * unLength symbols should be read from line. Then, that data string should converted to binary, for example:
{
case data_record:
QByteArray hex = line.mid(nIndex, 2 * unLength ).toLatin1();
QByteArray binary = QByteArray::fromHex(hex);
ref_ByteArray.append(binary);
...
}
I am learning to use Boost.MPI to parallelize the large amount of computation, here below is just my simple test see if I can get MPI logic correctly. However, I did not get it to work. I used world.size()=10, there are total 50 elements in data array, each process will do 5 iteration. I would hope to update data array by having each process sending the updated data array to root process, and then the root process receives the updated data array then print out. But I only get a few elements updated.
Thanks for helping me.
#include <boost/mpi.hpp>
#include <iostream>
#include <cstdlib>
namespace mpi = boost::mpi;
using namespace std;
#define max_rows 100
int data[max_rows];
int modifyArr(const int index, const int arr[]) {
return arr[index]*2+1;
}
int main(int argc, char* argv[])
{
mpi::environment env(argc, argv);
mpi::communicator world;
int num_rows = 50;
int my_number;
if (world.rank() == 0) {
for ( int i = 0; i < num_rows; i++)
data[i] = i + 1;
}
broadcast(world, data, 0);
for (int i = world.rank(); i < num_rows; i += world.size()) {
my_number = modifyArr(i, data);
data[i] = my_number;
world.send(0, 1, data);
//cout << "i=" << i << " my_number=" << my_number << endl;
if (world.rank() == 0)
for (int j = 1; j < world.size(); j++)
mpi::status s = world.recv(boost::mpi::any_source, 1, data);
}
if (world.rank() == 0) {
for ( int i = 0; i < num_rows; i++)
cout << "i=" << i << " results = " << data[i] << endl;
}
return 0;
}
Your problem is probably here:
mpi::status s = world.recv(boost::mpi::any_source, 1, data);
This is the only way data can get back to the master node.
However, you do not tell the master node where in data to store the answers it is getting. Since data is the address of the array, everything should get stored in the zeroth element.
Interleaving which elements of the array you are processing on each node is a pretty bad idea. You should assign blocks of the array to each node so that you can send entire chunks of the array at once. That will reduce communication overhead significantly.
Also, if your issue is simply speeding up for loops, you should consider OpenMP, which can do things like this:
#pragma omp parallel for
for(int i=0;i<100;i++)
data[i]*=4;
Bam! I just split that for loop up between all of my processes with no further work needed.
I need to perform some regexp operations on binary data. I wrote a function to convert QByteArray data in a hexa string representation. Each byte is prepended by 'x' for parsing purpose.
How could this code be optimized?
QByteArray data;
QByteArray newData;
for (int i = 0; i < data.size(); i++) {
QString hex;
hex.setNum(data[i], 16);
if (data[i] < 10) {
hex.prepend("x0");
} else {
hex.prepend("x");
}
newData.append(hex.toLatin1());
}
The code you posted has two bugs in it that I corrected.
1) Assuming you always want two hex digits you want to check if the value is less than 16, not 10.
2) QString::setNum has no overload for char, so the value is promoted to a larger type. For a value like 128, which is negative in a signed char, you would get x0ffffffffffffff80 due to sign extension.
The function foo1 is your original code with the bugs fixed, and foo2 is a more optimal version that avoids creating a temporary QString since the conversion to unicode and back isn't free, and prepending values to a string requires additional copying.
I used QElapsedTimer because on Windows where I am testing it uses the high resolution PerformanceCounter clock. If you are on another platform it might be less accurate. You can see the different types of clocks it may use in the documentation.
Set display_converted_string to true if you want the converted string printed to verify they are identical.
#include <QString>
#include <QByteArray>
#include <QElapsedTimer>
#include <iostream>
QByteArray foo1(QByteArray data)
{
QByteArray newData;
for (int i = 0; i < data.size(); i++) {
unsigned char c = data[i];
QString hex;
hex.setNum(c, 16);
if (c < 16) {
hex.prepend("x0");
} else {
hex.prepend("x");
}
newData.append(hex.toLatin1());
}
return newData;
}
QByteArray foo2(QByteArray data)
{
static const char digits[] = {'0','1','2','3','4','5','6','7',
'8','9','a','b','c','d','e','f'};
QByteArray newData;
newData.reserve(data.size() * 3);
for (int i = 0; i < data.size(); i++)
{
unsigned char c = data[i];
newData.append('x');
newData.append(digits[(c >> 4) & 0x0f]);
newData.append(digits[c & 0x0f]);
}
return newData;
}
int main()
{
const int iterations = 10000;
const bool display_converted_string = false;
QElapsedTimer t;
std::cout << "Using clock type " << t.clockType() << ".\n";
QByteArray data(256, 0);
QByteArray newData;
qint64 elapsed1 = 0, elapsed2 = 0;
//Set the values in data to 0-255 to make sure all values are converted properly.
for(int i = 0; i < data.size(); ++i)
{
data[i] = i;
}
t.start();
for(int i = 0; i < iterations; ++i)
{
newData = foo1(data);
}
elapsed1 = t.nsecsElapsed();
std::cout << "foo1 elapsed time = " << elapsed1 << "\n";
if(display_converted_string)
{
std::cout << "newData = " << newData.data() << "\n";
}
t.restart();
for(int i = 0; i < iterations; ++i)
{
newData = foo2(data);
}
elapsed2 = t.nsecsElapsed();
std::cout << "foo2 elapsed time = " << elapsed2 << "\n";
if(display_converted_string)
{
std::cout << "newData = " << newData.data() << "\n";
}
return 0;
}
Im trying to print the first line from each file, then the second line from each file and so on.
When getline = EOF, then that file is closed and filesAreOpen is decremented, though the program loops forever
void PrintLines(ifstream files[], size_t count)
{
string s;
ifstream *end, *start;
int filesAreOpen = count;
//continue while filesAreOpen > 0
while(filesAreOpen)
{
}
}
Actually you don't have to close files if EOF is reached. That will make your code much slower and painful to manage. Because you have to check if it is open, which involves file names. In this case, files are already open and you will read first line from each file than second line from each file and so on. But if a file reaches EOF, then of course you will miss that file and continue to read lines from other files. Until all files are reached EOF. Then close them all.
void PrintLines(ifstream files[], size_t count)
{
int filesAreOpen = count;
char line[250];
//continue while filesAreOpen > 0
while(filesAreOpen)
{
for(int i=0; i<count; i++)
{
if (!infile[i].eof())
{
infile[i].getline(line,250);
cout << line;
}
else
filesAreOpen--;
}
}
for(int i=0; i<count; i++)
files[i].close();
}