fwrite, fread - problems with fread - c++

I have following code:
int main()
{
char* pedal[20];
char* pedal2[20];
for (int i = 0; i < 20; i++)
{
pedal[i] = "Pedal";
}
FILE* plik;
plik = fopen("teraz.txt","wb");
for (int i = 0; i < 20; i++)
{
fwrite(pedal[i],strlen(pedal[i]),1,plik);
}
system("pause");
fclose(plik);
plik = fopen("teraz.txt","rb");
for (int i = 0; i < 20; i++)
{
fread(pedal2[i],5,1,plik); //I know for now that every element has 5 bytes
}
for (int i = 0; i < 20; i++)
{
std::cout << pedal2[i] << std::endl;
}
fclose(plik);
system("pause");
return 0;
}
It's crashing at reading and second question let's assume that I have structure where I keep like integers, floats and also char* array and how can I easly write whole structure to the file? Normal fwrite with sizeof structure is not working

Your problem that you didn't allocate buffer for reading. In fact line
fread(pedal2[i],5,1,plik)
reads to unknown place. You need allocate memory (in your case it is 5 + 1 bytes for zero terminated string).
pedal2[i] = malloc(5+1);
fread(pedal2[i],5,1,plik)
Don't forget to release it after usage.

You can't read into pedal2 without first having allocated space for it.
You need something like this:
for (int i = 0; i < 20; ++i) {
pedal[i] = malloc(100); //allocate some space
}

Your first question seem to have already been answered by Simone & Dewfy.
For your second question about how to write structure values into the file, you will have to write member by member.
Please check fprintf. You can probably use it for writing different data types.

Related

Allocating pointer to a pointer

I have 5 buffers and 20 frames to write in them. Being one frame per buffer, at a certain moment i will have to overwrite buffers with the newest frame.
At random moments i need to read the oldest frame(its id and data) from all the buffers.
I am obliged to use a pointer to a pointer for my buffers, but since i suck at pointers, not even the allocation works, giving me a SEGMENTATION FAULT and not sure why.
What i have until now:
void fakeFrame(uint16_t *data)
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
int main()
{
uint16_t **p_frameBuffers;
uint32_t *p_frameIdxs;
uint16_t wrIdx = 0;
uint16_t reIdx = 0;
uint16_t currentFrameCounter = 0;
uint16_t nbBuffers = 5;
for(auto i =0; i< nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}
while(currentFrameCounter <= 20)
{
wrIdx++;
wrIdx %= nbBuffers;
if(wrIdx == reIdx)
{
std::cout<<"i passed the limit";
}
currentFrameCounter++;
p_frameIdxs[wrIdx] = currentFrameCounter;
fakeFrame(p_frameBuffers[wrIdx]);
}
std::cout<<"\n";
return 0;
}
I can see a few different problems with this code here.
You declare the long-form of the function for fakeFrame() in the beginning of the program, when the standard is usually to declare the function header first.
This is like a warning to the program that a function is about to be used, and that it's not part of a class or anything. Just standalone.
Example:
#include <iostream>
void fakeFrame();
int main()
{
return 0;
}
void fakeFrame()
{
for (auto i = 0; i < 1440; i++)
for (auto j = 0; j < 1440; j++)
data[(i * 1440) + j] = std::rand()%2;
}
You're also using some of these 16 and 32 bit unsigned ints as if they were arrays, so I was deeply confused about that. Did you mean to set them as arrays?
You also have some variables being declared in a non-array context but being used as arrays. I'm not deeply familiar with the uint variable/object types but I know they aren't usually meant to function as standalone arrays.
Also, no variable called m_pFrameBuffers is actually declared in the code you provided. Plus this is also used as an array, so it should really be declared as one.
I hope this provides at least some insight into what's not working. I'm actually kind of surprised that the void function ran before, it's improperly formatted.
In the end this is what did it: the pointer to a pointer is actually an array of pointers (which i did not know, of course)
p_frameBuffers = (uint16_t**)malloc((sizeof(uint16_t*)*nbBuffers));
for(auto i = 0; i < nbBuffers; i++)
{
p_frameBuffers[i] = (uint16_t*)malloc(1440*1440*2);
}

How can I convert vector<string> to char* arr[]?

Recently I want to convert vector to char* array[].
So I had found the solution. But It was not safety way..
Here is my code
char** arr = new char* [4];
vector<string> vv;
// setting strings
for (int i = 0 ;i < 4; i++)
{
vv.emplace_back("hello world");
}
// convert
for (int i = 0; i < 4; i++)
{
arr[i] = new char[vv[i].size()];
memcpy(arr[i], vv[i].c_str(), vv[i].size());
}
// prints
for (int i = 0; i < 4; i++)
{
cout << arr[i] << endl;
}
// output
// hello world羲羲?솎솨
// hello world羲羲拂솽솨
// hello world羲羲
// hello world羲羲?펺솨
// delete memorys
for (unsigned index = 0; index < 4; ++index) {
delete[] arr[index];
}
delete []arr;
Why does it happen string crash??
Is there no safe way anymore?
When you use memcpy, arr[i] is not guaranteed to be a null-terminated string. To treat arr[i] as null terminated string, as in
cout << arr[i] << endl;
causes undefined behavior.
You need couple of minor changes.
Allocate one more byte of memory.
Use strcpy instead of memcpy.
arr[i] = new char[vv[i].size() + 1];
strcpy(arr[i], vv[i].c_str());
There's an easier way of doing this if you can maintain the lifetime of your initial vector.
for (int i = 0; i < 4; i++)
{
arr[i] = vv[i].c_str();
}
This way you won't allocate no additional memory, however, you'd have to keep in mind that once your initial vector gets destroyed, that array will be corrupted as well. But if you need such conversion for some simple synchronous api call within the same thread, that would do the trick.
In such cases I usually use this ugly construct.
arr[i] = new char[vv[i].size() + 1];
arr[i][vv[i].copy(arr[i], vv[i].size())] = 0;

get all values triple pointer C++

I have an externel C-DLL, which I use in my C++ project.
The function which I stuck up with is
Get_ALLFiles(char*** listOfFiles, int* nbrOfFiles). This function applies some criteria on a folder and returns the files, that matches the criteria.
int nbrOfFiles= 0;
//just get the number of files
Get_ALLFiles((char***)malloc(1 * sizeof(char***)), &ElementNbr);
// pointer allocation
char ***MyFilesList = (char***)malloc(nbrOfFiles* sizeof(char**));
for (int i = 0; i < ElementNbr; i++) {
MyFilesList [i] = (char**)malloc(ElementNbr * 32 * sizeof(char*));
for (int j = 0; j < 32; j++)
MyFilesList [i][j] = (char*)malloc(ElementNbr * sizeof(char));
}
//Now i will use the function in order to get all the files (in my exemple
//I have 10 which respond the criteria
Get_ALLFiles(MyFilesList , &nbrOfFiles);
In my "MyFilesList" I have only the first element, how can I get all the elements in "MyFilesList"?
My guess is that the function allocates its memory itself, and you should pass pointers to variables that receives the values. Emulating pass-by-reference in C.
Something like
char** MyFilesList;
int NumberFiles;
// Get a list of all files
Get_ALLFiles(&MyFilesList, &NumberFiles);
// Print all files
for (int i = 0; i < NumberFiles; ++i)
{
std::cout << "File #" i + 1 << " is " << MyFilesList[i] << '\n';
}
// Free the memory
for (int i = 0; i < NumberFiles; ++i)
{
free(MyFilesList[i]);
}
free(MyFilesList);
You should pass the address of a variable to the function, not a pointer to dynamic memory.
That is, just like you do with the number.
The function will then allocate all the memory and update your variable through the pointer it received.
Like this:
char** MyFilesList = nullptr;
int nbrOfFiles = 0;
Get_ALLFiles(&MyFilesList , &nbrOfFiles);

two dimensional array with undefined second dimension

I have a problem that I'm not sure how to solve. I have a C++ function that opens a .wav file, reads the samples into an array of doubles that has as many indexes as the number of samples in the .wav file, and return a pointer to that array. This works perfectly.
What I'm wanting to do is read more than one .wav file and store them in a two dimensional array. Although I know how many arrays there will be, the size of each array will be different, because all .wav files have a different nubmer of samples. I don't know how to properly store this data for multiple files.
Here is the call to wav2sig, the function that opens the .wav and returns a pointer:
double* wav2sig(std::string filepath, int & num_samples)
And here is the code that I'm working off, roughly.
std::string paths[3] = {"man1.wav",
"man2.wav",
"man3.wav"};
double **data = new double[3][]; //this would work in java, but not here
int num_samples[3];
for(int i = 0; i < 3; i++) {
data[i] = wav2sig(paths[i], num_samples[i]);
for(int j = 50; j < 100; j++)
std::cout << data[i][j] << " ";
std::cout << std::endl;
}
I know that the returned pointer has all correct data. I just don't know how to store several of them correctly. Thanks for any help!
I strongly suggest the use of std::vector for the arrays instead of pointers that point to dynamically allocated memory. They are just as easy to use and they take away the headache of managing memory.
Change the return value of wav2sig
std::vector<double> wav2sig(std::string filepath);
I am guessing num_samples was used to return the number of elements in the returned array. When you use std::vector<double> as the return type, the size of the returned value will capture that. Hence, there is no need for the additional output argument.
Use std::vector<std::vector<double>> for the 2D array.
std::vector<std::vector<double>> data;
Update the loops accordingly
// Separate reading of the data from files from outputting the data
// Read the data
for(int i = 0; i < 3; i++) {
data.push_back(wav2sig(paths[i]);
}
// Output the data
for(int i = 0; i < 3; i++) {
for(size_t j = 0; j < data[i].size(); j++)
std::cout << data[i][j] << " ";
std::cout << std::endl;
}

Wrong use of memset?

Can someone please explain what is wrong here:
class test
{
public:
char char_arr[100];
};
int main()
{
test **tq = (test**)calloc(10, sizeof(test*));
for(unsigned int i = 0; i < 10; i++)
tq[i] = (test*)calloc(10, sizeof(test));
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
return 0;
}
The code above produces random crashes. The errors are: "memory could not be written", "memory could not be read", "stack is corrupted"
test **tq = (test**)calloc(10, sizeof(test*));
...
for(unsigned int i = 0; i < 10; i++)
memset(tq, 0, sizeof(tq[0][0])*100);
When you allocate tq, you ask for 10 * sizeof(test*) bytes. But when you call memset, you ask it to set sizeof(tq[0][0]*100) bytes. You are definitely writing to more bytes then you allocated. Perhaps you meant:
for(unsigned int i = 0; i < 10; i++)
memset(tq[i], 0, 10 * sizeof(test));
This makes sense because:
tq[i] = (test*)calloc(10, sizeof(test));
When you allocated tq[i], you allocated 10 * sizeof(test) bytes.
You are confusing this for a 2D array:
char x[10][10];
This is a 2D array, which holds 100 contiguous chars.
But you have allocated a bunch of pointers, then pointed them to separate arrays of 10 chars each. The result is not contiguous; you cannot access it in the way you have.