two dimensional array with undefined second dimension - c++

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

Related

(SOLVED) Why is a 'vector subscript out of range' message appearing on this counting sort algorithm? (SOLVED)

EDIT: I've solved the issue! It had nothing to do with the function itself. I initially used a vector for this function, and the cout statement I used to check the function in main() still called the vector, not the array. A simple mistake, but I appreciate the help!
Hey! I'm currently in college learning data structures, and for our final project, we're tasked with creating multiple sorting algorithms to sort 500,000 randomly generated numbers between 1 - 9,999,999 that have been defined in a text file. I'm currently trying to work on a counting sort, and I keep getting the #include vector line 1553 error 'vector subscript out of range'. I've debugged this function all the way to the last for-loop. Everything seems to work perfectly fine, so I'm assuming it has to do with somewhere in this final piece, but I'd prefer to not have to manually go through 500,000 cycles, so if anyone can see what I've done wrong, I'd like to know.
I also allocated this data on the heap because stack allocation creates a memory overload.
I apologize if this is a low-level question, but I'd love some help, as this project means a lot to me and to my grade. Thank you!
void countingSort(int numberArray[], int SIZE)
{
// Initializer for dynamically-allocated array used to hold the sorted data in the array
int* sortedArray = new int[SIZE];
// Initializes all values in sortedArray to 0
for (int i = 0; i < SIZE; i++)
sortedArray[i] = 0;
// Initializer for variable used to hold the maximum value in the original data
int max = 0;
// Finds the max in numberArray
for (int i = 0; i < SIZE; i++)
{
if (numberArray[i] > max)
max = numberArray[i];
}
// Create an array to store the amount of times each number in numberArray is used
int* countArray = new int[max + 1];
// Initialize all indexes of countArray to 0
for (int i = 0; i <= max; i++)
{
countArray[i] = 0;
}
// When a number is present in numberArray, increase its number of appearances in countArray by one
for (int i = 1; i < SIZE; i++)
countArray[numberArray[i]]++;
// Find the total frequency in the count array
for (int i = 1; i <= max; i++)
countArray[i] += countArray[i - 1];
// Store the sorted values into a sorted array
// Decrease the total count number
for (int i = SIZE - 1; i > 0; i--)
{
sortedArray[countArray[numberArray[i]] - 1] = numberArray[i];
countArray[numberArray[i]]--;
}
// Store the sorted array in the original numberArray
for (int i = 0; i < SIZE; i++)
{
numberArray[i] = sortedArray[i];
}
}
int main()
{
int* SIZE = new int;
*SIZE = 500000;
.
(*code for other functions*)
.
countingSort(numberArray, *SIZE);
cout << "\n" << numberList[0] << "\t" << numberList[499999] << endl;
}

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

Program killed: using vector of set of vector

In my Algorithm, I need to keep all the combinations of (3 bytes of) extended ASCII characters. Following is my code But when i run this code, the program gets killed on terminal when the last step occurs(BigVector.pushback).Why is this so and what can be the alternative in my case?
vector<set<vector<int> > > BigVector;
set<vector<int> > SmallSet;
for(int k=0; k <256; k++)
{
for(int j=0; j <256; j++)
{
for(int m=0; m <256; m++)
{
vector<int> temp;
temp.push_back(k);
temp.push_back(j);
temp.push_back(m);
SmallSet.insert(temp);
}
}
}
BigVector.push_back(SmallSet);
P.S: I have to keep the ascii characters like this:
{ {(a,b,c) ,(a,b,d),...... (z,z,z)} }
Please note that 256^3 = 16,777,216. This is huge, especially when you use vector and set!
Because you only need to record 256 = 2^8 information, you can store this in a char ( one byte). You can store each combination in one tuple of three chars. The memory is now 16,777,216 / 1024 / 1024 = 16 MB. On my computer, it finishes in 1 second.
If you accept C++11, I would suggest using std::array, instead of writing a helper struct like Info in my old code.
C++11 code using std::array.
vector<array<char,3>> bs;
.... for loop
array<char,3> temp;
temp[0]=k; temp[1]=j; temp[2]=m;
bs.push_back(temp);
C++98 code using home-made struct.
struct Info{
char chrs[3];
Info ( char c1, char c2, char c3):chrs({c1,c2,c3}){}
};
int main() {
vector<Info> bs;
for (int k = 0; k < 256; k++) {
for (int j = 0; j < 256; j++) {
for (int m = 0; m < 256; m++) {
bs.push_back(Info(k,j,m));
}
}
}
return 0;
}
Ways to use the combinations. (You can write wrapper method for Info).
// Suppose s[256] contains the 256 extended chars.
for( auto b : bs){
cout<< s[b.chrs[0]] << " " << s[b.chrs[1]] << " "<< s[b.chrs[2]] << endl;
}
First: your example doesn't correspond with the actual code.
You are creating ( { (a,a,a), ..., (z,z,z) } )
As already mentioned you will have 16'777'216 different vectors. Every vector will hold the 3 characters and typically ~20 bytes[1] overhead because of the vector object.
In addition a typical vector implementation will reserve memory for future push_backs.
You can avoid this by specifying the correct size during initialization or using reserve():
vector<int> temp(3);
(capacity() tells you the "real" size of the vector)
push_back makes a copy of the object you are pushing [2], which might be too much memory and therefore crashing your program.
16'777'216 * (3 characters + 20 overhead) * 2 copy = ~736MiB.
(This assumes that the vectors are already initialized with the correct size!)
See [2] for a possible solution to the copying problem.
I do agree with Potatoswatter: your data structure is very inefficient.
[1] What is the overhead cost of an empty vector?
[2] Is std::vector copying the objects with a push_back?

Storing array's of integers on the heap and accessing them via pointers

I'm hoping someone can shed some light on where I am going wrong with pointers.. I've read countless web pages and tried various things but for some reason my code is returning jibberish (which I'm guessing may be the memory addresses instead of the data within my array). The purpose of the program is to create an array of 100 elements on the heap, pass this array by a pointer to a function (along with two integer variables start and end); a new array will be created on the heap (this comprises of a chunk of the original array using the start and end variables) and the pointer to this array is passed back to the main method so that the new array can be outputted. My problem is not only is the output seeming to be the location not the value, but also it seems 100 values are outputted not 20 as should be expected. I've spent hours trying to figure out where I have gone wrong and just when I think I understand the concept of pointers my faith is destroyed by red squigglies and incorrect outputs. Please HELP! My code is as follows:
#include "stdafx.h"
#include <iostream>
#include <time.h>
using namespace std;
double* getSubArray(double*, int, int);// Declare a function that will get the sub array
int _tmain(int argc, _TCHAR* argv[])
{
const int size = 100;// Declare the size of the array
double* pA;// Declare the variable to hold the pointers to the data in array
double* pB;
int start = 15;
int end = 35;
pA = new double[size];// Create space for the array
srand(clock());// Seed the program to the computers current time so that random gets a different set of random numbers everytime it is run
// Use a for loop to traverse through each element of the array (starting at index 0) placing a number defined by the random function that is no higher than 250
for (int i = 0; i < size; i++)
{
pA[i] = rand()%250;
}
cout << "An Array of 100 numbers is created and stored in the heap, these values are:" << endl;
// Output the Array for the user to see
for (int j = 0; j < size; j++)
{
// Place 10 numbers on each line
if (j % 10 == 0)
{
cout << endl;
}
cout << *(pA + j) << " ";
}
cout << endl << "The program will build a second array using the data between the indexes " << start << " & " << end << endl;
pB = getSubArray(pA, start, end);// Pass the data to the method
// Output second array for user to compare
for (int k = 0; k < size; k++)
{
// Place 10 numbers on each line
if (k % 10 == 0)
{
cout << endl;
}
cout << *(pB + k) << " ";
}
system("pause");
return 0;
}
double* getSubArray(double* pA, int start, int end)
{
double* pB = new double[end-start];// Declare space in the heap for the new array whoes size is the size of the criteria given
for (int i = 0; i < (end - start); i++)
{
for (int j = start; j < end; j++)
{
*(pB + 0) = pA[j];
}
}
return pB;
}
*(pB + 0) = pA[j];
That keeps writing to the first element of the array. Surely you want to write to each element in turn:
for (int i = start; i < end; ++i) {
pB[i-start] = pA[i];
}
or if you don't want to write your own loop
std::copy(pA+start, pA+end, pB);
Don't forget to delete[] everything you new[] or, to save mucking around with low-level memory management, use std::vector to manage the dynamic arrays for you.

vector.push_back

I am writing an application that reads from data files of a given format. In the file, I've dynamically created a 2D array of pointers to vector objects. Basically, it reads through the file, and when it finds a given string pattern, it stops and reads
while(getline(inputFile,tempTestString)){
// first for ACCEL
if(string::npos != tempTestString.find(ACCEL)){
sstream.str(tempTestString);
sstream >> pushBack;
cout << "position 1" << endl;
array[tempDim1][tempDim2].vectorName->push_back(pushBack);
cout << "position 2" << endl;
break;
}
}
now, pushBack is a large number, could be up to 20000, but it varies between files.
The problem with this code is that I'm not getting any run-time errors, or even any exceptions thrown, I tried catching them. The program simply finishes! To be sure, I added the cout << "position1" << endl; and cout << "position2" << endl; lines and the latter prints.
In case you haven't guessed:
tempTestString and ACCEL - string objects
sstream - stringstream object
array - 2D struct array in dynamic memory
vectorName - pointer to vector object, member of struct pointed to by array
ADDENDUM:
So, in response to some comments, here is the other portion of the code, where all the variables were created:
array
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
structName
struct structName{
vector<double>* vectorName;
vector<double>* vectorName1;
vector<double>* vectorName2;
};
tempDim1 and tempDim2 are both const ints, of values 2 and 3, respectively. pushBack can have a value of up to 20000
Try to correct this:
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
=>
array = new structName* [tempDim1];
for(int i = 0; i < tempDim1; i++){
array[i] = new structName [tempDim2];
}
You're using the wrong number of elements in your initialization.
array = new structName* [tempDim1];
for(int i = 0; i < tempDim2; i++){
array[i] = new structName [tempDim2];
}
i < tempDim2 is wrong; the array has tempDim1 elements.
I don't know if this is the problem, but it is a problem. If tempDim1 > tempDim2 then some elements of array[] are going to be uninitialized. (And if it's the other way around, you're corrupting memory.) The only way this would work is if tempDim1 and tempDim2 are the same by coincidence.