Recursive function of tree with infinite childs. c++ - c++

I've created a virtual filesystem that i made to simulate a hard drive. The problem i am getting is that when i format this "drive" i need to go though every folder and sub-folders and delete "files" that I've created and then deleting the folders without getting memory leaks :)
I've been at this for a few hours now and I've tried to make recursive functions but it won't delete everything. It keeps getting stuck somewhere :(
Any ideas would make my week!! Thanks.
Here is code example of my folder.h and recursive function.
folder.h :
#ifndef FOLDER_H
#define FOLDER_H
#include <iostream>
#include <string>
#include "file.h"
using namespace std;
class folder
{
private:
int CAP = 10;
int nrOfChildFolders;
int nrOfFiles;
string folderName;
folder * parentFolder;
folder * childFolder[10];
file * fileArray[10];
public:
folder();
folder(string folderName, folder * parent);
~folder();
void addFolder(string folderName);
void addFile(string fileName, int nr);
string getFolderAndFiles()const;
string getFolderName()const;
int getFileNr(string fileName)const;
void reset();
folder * getFolder(string name)const;
folder * getParentFolder()const;
void deleteFile(string name, int nr);
folder * getChildFolder(int pos);
int getNrOfChildFolders()const;
/* data */
};
#endif
Recursive function :
void FileSystem::recursiveFolderSwitcher(folder * newCurrentFolder)
{
int folders = newCurrentFolder->getNrOfChildFolders();
if (newCurrentFolder->getNrOfChildFolders() != 0)
{
for (int i = 0; i < folders; i++)
{
newCurrentFolder = newCurrentFolder->getChildFolder(i);
recursiveFolderSwitcher(newCurrentFolder);
}
}
newCurrentFolder->reset();
}
Thanks <3

You are reassigning newCurrentFolder in your for-loop.
newCurrentFolder = newCurrentFolder->getChildFolder(i);
This makes the final
newCurrentFolder->reset()
reset the last child instead.
Use
folder* child = newCurrentFolder->getChildFolder(i);
recursiveFolderSwitcher(child);
instead.
Also
if (newCurrentFolder->getNrOfChildFolders() != 0)
is unnecessary, the for-statement will take care of this for you.

Related

How to make a vector of sf::sound

I use the SFML library and more specifically the audio part of SFML. I would like to store multiple sf::Sound, so it occurred to me to make a class that handles sounds and to make a vector of sf::Sound.
However, when I try to play a sound, only the last element of the list of my vector can be played, the rest does not play.
I really can't understand why.
audio.hpp
#ifndef AUDIO_HPP
#define AUDIO_HPP
#pragma once
#include <SFML/Audio.hpp>
#include <vector>
#include <string>
enum {SELECTION_SOUND, DEAD_SOUND};
enum {MAIN_THEME_MUSIC, GAME_MUSIC, GAME_OVER_MUSIC};
class Audio
{
public:
Audio();
void setVolumeMusic(const float v);
void setVolumeSound(const float v);
float getVolumeSound() const;
float getVolumeMusic() const;
void playSound(const unsigned int soundExecute);
void stopMusic();
void deleteMusicTheme();
~Audio();
private:
bool m_musicThemeUse;
float m_volumeMusic, m_volumeSound;
std::vector <sf::SoundBuffer> m_buffer;
std::vector <bool> accessMusic, accessSound;
std::vector <sf::Sound> m_sound;
std::vector <sf::Music*> m_music;
std::vector <std::string> m_nameFileMusic, m_nameFileSound;
/*
* m_musicThemeUse : If this variable is equal to "true" then, the main menu music is deleted from memory.
* m_volumeMusic, m_volumeSound : Music/sound volume, it is fixed between 0.f and 100.f.
* m_buffer: vector containing the audio files of the sounds.
* accessMusic, accessSound : bool vector determining whether a music is available for playback or not. Useful when a file is deleted.
* m_sound: vector containing the audio files of the sounds.
* m_music: vector containing the audio files of the musics.
* m_nameFileMusic, m_nameFileSound : vector of string containing the path of the audio files.
*/
};
#endif
The constructor of the Audio class.
Audio::Audio() : m_nameFileMusic{ "data/mainTheme.ogg", "data/game.ogg", "data/gameOver.ogg" }, m_nameFileSound{"data/selectionSound.ogg", "data/dead.ogg" },
m_musicThemeUse(true), m_volumeMusic(0.f), m_volumeSound(100.f)
{
//Fill the values of accessMusic and accessSound to "true"
accessMusic.assign(std::size(m_nameFileMusic), true);
accessSound.assign(std::size(m_nameFileSound), true);
//Loads music files.
for (unsigned int i = 0; i < std::size(m_nameFileMusic); i++)
{
m_music.push_back(new sf::Music);
if (!m_music[i]->openFromFile(m_nameFileMusic[i]))
accessMusic[i] = false;
}
//Set the music files by setting the volume to them and activating repeat when the music files are finished.
setVolumeMusic(m_volumeMusic);
for(unsigned int i = 0; i < std::size(m_music); i++)
if(m_nameFileMusic[i] != "data/gameOver.ogg")
m_music[i]->setLoop(true);
//Load sound files.
const sf::SoundBuffer a;
const sf::Sound b;
for (unsigned int i = 0; i < std::size(m_nameFileSound); i++)
{
m_buffer.push_back(a);
m_sound.push_back(b);
if (!m_buffer[i].loadFromFile(m_nameFileSound[i]))
accessSound[i] = false;
else
m_sound[i].setBuffer(m_buffer[i]);
}
//Fix the volume of the sound files.
setVolumeSound(m_volumeSound);
//If the main menu music file is available then play the music file.
if(accessMusic[0])
m_music[0]->play();
m_sound[0].play();
}
When you copy SFML sound objects they stop playing. That's what happens when you relocate objects in an std::vector. I would recommend storing them in pointers as with
using SoundPtr = std::shared_ptr<sf::Sound>;
std::vector< SoundPtr > m_sound;
Yes I am coming back to tell you that I have solved the problem, in reality I had to separate the initialization phase of std::vector<sf::SoundBuffer> and the initialization phase of std::vector std::shared_ptr<sf::Sound>
Thank you everyone !
//Loads Buffer file
for (unsigned int i = 0; i < std::size(m_nameFileSound); i++)
{
m_buffer.push_back(sf::SoundBuffer{});
if (!m_buffer[i].loadFromFile(m_nameFileSound[i]))
accessSound[i] = false;
}
//Loads Sound file
for (unsigned int i = 0; i < std::size(m_buffer); i++)
{
m_sound.push_back(std::make_shared<sf::Sound>(sf::Sound{}));
if (accessSound[i])
m_sound[i]->setBuffer(m_buffer[i]);
}

Blueprint loop/for/while node with custom c++ blueprint function library in unreal engine 4 (ue4)

I need to create a custom blueprint node. I am using the blueprint function library.
The node will look like this:
Input:
int timedelayforeachloop
int numberofloops
output:
exc loop
exc completed
loop1.h
// Fill out your copyright notice in the Description page of Project Settings.
#pragma once
#include "CoreMinimal.h"
#include "Kismet/BlueprintFunctionLibrary.h"
#include "loop1.generated.h"
/**
*
*/
UENUM(BlueprintType)
enum class EMultiBranchEnum1 : uint8
{
BranchA,
BranchB
};
UCLASS()
class MYPROJECT2_API Uloop1 : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
UFUNCTION(BlueprintCallable, meta = (DisplayName = "loop", CompactNodeTitle = "2as2", ExpandEnumAsExecs = "Branches"), Category = "1")
//UFUNCTION(BlueprintCallable, Meta = (DisplayName = "Multi Branch1", ExpandEnumAsExecs = "Branches"), Category = 1)
static void multiBranch(EMultiBranchEnum1& Branches, int loopqty);
//EMultiBranchEnum1::BranchB;
};
loop1.cpp
// Fill out your copyright notice in the Description page of Project Settings.
#include "loop1.h"
void Uloop1::multiBranch(EMultiBranchEnum1& Branches, int loopqty)
{
int currloop1 = 0;
int temp = 2;
int i;
for (i = 0; i < 10; i++){
currloop1 = currloop1 + 1;
Branches = EMultiBranchEnum1::BranchA;
}
if (temp > currloop1) {
Branches = EMultiBranchEnum1::BranchB;
}
if(temp == 0) {
Branches = EMultiBranchEnum1::BranchB;
}
}
-- THE PROBLEM --
The for loop only runs the once (evident by the print node i have on branchA(It only prints a single time))
-- What should happen with the code below --
the loop should run the 10 times (my print node should print 10 times)
Instead of using UBlueprintFunctionLibrary, you should use UBlueprintAsyncActionBase. It will allow you to store state in the node and call things connected to the execution pins asynchronously.
DelayLoop.h file:
#include "CoreMinimal.h"
#include "Kismet/BlueprintAsyncActionBase.h"
#include "DelayLoop.generated.h"
DECLARE_DYNAMIC_MULTICAST_DELEGATE(FDelayOutputPin);
/**
*
*/
UCLASS()
class TEST_API UDelayLoop : public UBlueprintAsyncActionBase
{
GENERATED_UCLASS_BODY()
public:
UPROPERTY(BlueprintAssignable)
FDelayOutputPin Loop;
UPROPERTY(BlueprintAssignable)
FDelayOutputPin Complete;
UFUNCTION(BlueprintCallable,
meta = (BlueprintInternalUseOnly = "true", WorldContext = "WorldContextObject"),
Category = "Flow Control")
static UDelayLoop* DelayLoop(const UObject* WorldContextObject,
const float DelayInSeconds, const int Iterations);
virtual void Activate() override;
private:
const UObject* WorldContextObject;
float MyDelay;
int MyIterations;
bool Active;
UFUNCTION()
void ExecuteLoop();
UFUNCTION()
void ExecuteComplete();
};
DelayLoop.cpp file:
#include "DelayLoop.h"
#include "Engine/World.h"
#include "TimerManager.h"
UDelayLoop::UDelayLoop(const FObjectInitializer& ObjectInitializer) :
Super(ObjectInitializer), WorldContextObject(nullptr), MyDelay(0.0f),
MyIterations(0), Active(false)
{
}
UDelayLoop* UDelayLoop::DelayLoop(const UObject* WorldContextObject,
const float DelayInSeconds, const int Iterations)
{
UDelayLoop* Node = NewObject<UDelayLoop>();
Node->WorldContextObject = WorldContextObject;
Node->MyDelay = DelayInSeconds;
Node->MyIterations = Iterations;
return Node;
}
void UDelayLoop::Activate()
{
if (nullptr == WorldContextObject)
{
FFrame::KismetExecutionMessage(TEXT("Invalid WorldContextObject."),
ELogVerbosity::Error);
return;
}
if (Active)
{
FFrame::KismetExecutionMessage(TEXT("DelayLoop is already running."),
ELogVerbosity::Warning);
}
if (MyDelay <= 0.0f)
{
FFrame::KismetExecutionMessage(
TEXT("DelayLoop delay can't be less or equal to 0."),
ELogVerbosity::Warning);
}
if (MyIterations <= 0)
{
FFrame::KismetExecutionMessage(
TEXT("DelayLoop iterations can't be less or equal to 0."),
ELogVerbosity::Warning);
}
Active = true;
for (int i = 0; i <= MyIterations; i++)
{
FTimerHandle IterationTimer;
WorldContextObject->GetWorld()->GetTimerManager().SetTimer(
IterationTimer, this, &UDelayLoop::ExecuteLoop, MyDelay * i);
}
FTimerHandle CompleteTimer;
WorldContextObject->GetWorld()->GetTimerManager().SetTimer(
CompleteTimer, this, &UDelayLoop::ExecuteComplete,
MyDelay * (MyIterations+1));
// If the Complete pin should happen at the same time as the last iteration
// use `MyDelay * MyIterations` here instead
}
void UDelayLoop::ExecuteLoop()
{
Loop.Broadcast();
}
void UDelayLoop::ExecuteComplete()
{
Complete.Broadcast();
Active = false;
}
This will get you a blueprint that looks like this:
Note: This code is heavily based on This Creating Asynchronous Blueprint Nodes guide by Daniel ~b617 Janowski, now hosted in the legacy wiki here

CERN ROOT: saving into file tree with branch of vector of custom class

How can I save into a TFile a TTree with a branch of vectors of custom class?
Also, why I am I not able to load the shared library (gSystem->Load returns 1) generated by the gInterpreter->GenerateDictionary call?
Below is what I tried to do:
// file: test.C
//
#include "TInterpreter.h"
#include "TRandom3.h"
#include "TFile.h"
#include "TTree.h"
#include <vector>
#include <iostream>
/***************************************************************/
class MyStruct : public TObject
{
public:
Int_t a;
Float_t b;
MyStruct() {a=0; b=0.0;}
ClassDef(MyStruct,1)
};
/***************************************************************/
void test(void)
{
gInterpreter->GenerateDictionary("std::vector<MyStruct>", "vector");
std::vector<MyStruct> test(3);
// fill 'test' with random numbers
TRandom3 rnd;
for (int i = 0; i < 3; i++)
{
test[i].a = int( rnd.Gaus(3.0, 10.0) );
test[i].b = rnd.Gaus(300.0, 10.0);
std::cout<<"test["<<i<<"]="<<test[i].a<<' '<<test[i].b<<std::endl;
}// end of for
// create a TTree and (attempt to) save it into a file
TFile outputTreeFile("test.root", "recreate");
TTree tree("tree", "ROOT tree");
tree.Branch("test", &test);
tree.Fill();
tree.Write();
}// end of function
/***************************************************************/
Running the code gives:
$ root.exe -t -l test.C+
root [0]
Processing test.C+...
test[0] = 12 295.652
test[1] = 10 299.699
test[2] = 11 299.433
Error in <TTree::Branch>: The class requested (vector<MyStruct>)
for the branch "test" is an instance of an stl collection and does
not have a compiled CollectionProxy. Please generate the
dictionary for this collection (vector<MyStruct>) to avoid to
write corrupted data.
What am I doing wrong?
Thank you very much for your help!

GNU Radio no output from other blocks parallel with my own OOT block

I would like to code my own general block with 1 input and 1 output for GNU Radio in C++. I followed the steps in gnuradio.org using gr_modtool. It can works well. But when I connect other block(scope sink2) with the same source there is no output in it.
I connect the flow graph as:
/-> Scope Sink2
Signal Source -> Throttle -|
\-> my own block -> Scope Sink1
I'm using GNU Radio Companion v3.7.6.1-65-g500517ac
I created the block 'energy_de'. This create among other four files:
energy_de.h
#ifndef INCLUDED_CPP_ENERGY_DE_H
#define INCLUDED_CPP_ENERGY_DE_H
#include <cpp/api.h>
#include <gnuradio/block.h>
namespace gr {
namespace cpp {
/*!
* \brief <+description of block+>
* \ingroup cpp
*
*/
class CPP_API energy_de : virtual public gr::block
{
public:
typedef boost::shared_ptr<energy_de> sptr;
/*!
* \brief Return a shared_ptr to a new instance of cpp::energy_de.
*
* To avoid accidental use of raw pointers, cpp::energy_de's
* constructor is in a private implementation
* class. cpp::energy_de::make is the public interface for
* creating new instances.
*/
static sptr make(float makenoise);
virtual float noise () const = 0;
virtual void set_noise (float noise) = 0;
};
} // namespace cpp
} // namespace gr
energy_de_impl.h
#ifndef INCLUDED_CPP_ENERGY_DE_IMPL_H
#define INCLUDED_CPP_ENERGY_DE_IMPL_H
#include <cpp/energy_de.h>
namespace gr {
namespace cpp {
class energy_de_impl : public energy_de
{
private:
float d_noise;
public:
energy_de_impl(float noise);
~energy_de_impl();
// Where all the action really happens
void forecast (int noutput_items, gr_vector_int &ninput_items_required);
float noise() const { return d_noise; }
void set_noise(float noise) { d_noise = noise; }
int general_work(int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items);
};
} // namespace cpp
} // namespace gr
energy_de_impl.cc
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <gnuradio/io_signature.h>
#include "energy_de_impl.h"
namespace gr {
namespace cpp {
energy_de::sptr
energy_de::make(float noise)
{
return gnuradio::get_initial_sptr
(new energy_de_impl(noise));
}
/*
* The private constructor
*/
energy_de_impl::energy_de_impl(float noise)
: gr::block("energy_de",
gr::io_signature::make(1, 1, sizeof(float)),
gr::io_signature::make(1, 1, sizeof(float))),
d_noise(noise)
{
}
/*
* Our virtual destructor.
*/
energy_de_impl::~energy_de_impl()
{
}
void
energy_de_impl::forecast (int noutput_items, gr_vector_int &ninput_items_required)
{
ninput_items_required[0] = noutput_items;
}
int
energy_de_impl::general_work (int noutput_items,
gr_vector_int &ninput_items,
gr_vector_const_void_star &input_items,
gr_vector_void_star &output_items)
{
const float *in = (const float *) input_items[0];
float *out = (float *) output_items[0];
for(int i = 0; i < noutput_items; i++){
if (in[i]*in[i] > d_noise){
out[i] = 1.0;
}
else{
out[i] = 0.0;
}
}
return noutput_items;
}
} /* namespace cpp */
} /* namespace gr */
cpp_energy_de.xml
<?xml version="1.0"?>
<block>
<name>energy_de</name>
<key>cpp_energy_de</key>
<category>cpp</category>
<import>import cpp</import>
<make>cpp.energy_de($noise)</make>
<callback>set_niose($noise)</callback>
<param>
<name>noise</name>
<key>noise</key>
<type>float</type>
</param>
<sink>
<name>in</name>
<type>float</type>
</sink>
<source>
<name>out</name>
<type>float</type>
</source>
</block>
Why I cannot get an out put from Scope Sink2? What have I forgotten to write inside the four files? Is this the problem about input_items buffer of my block?
When using a general block rather than a sync_block, your general_work must call consume, indicating how many items you've read, otherwise your own block's input buffer (== throttle's output buffer) quickly fills up, throttle can't put new samples into it and your flow graph halts. At that point, your scope sink might simply not have enough input to show anything.
I think for your use case, just using a sync_block would be much easier, and hence, the correct way to do this.
I'd like to point you to a mail I've written today to the discuss GNU Radio mailing list. It explains the buffer space concepts behind this.
/->A->Null Sink
File Source -|
\->B->File Sink
[...]
So the mechanism below is: the output buffer of File Source is the
input buffer of A and the input buffer of B. No memory duplication
here.
File Source has a buffer writer with a write pointer, and A and B have
their own read pointers pointing into that buffer.
When File Source produces N items, the write pointer advances by N.
Similarly, when A consumes M items, A's read pointer advances by M.
When calling (general_)work, the input_items buffer(s) is (are) really
just a pointer (start_of_buffer + read pointer). Equivalently, the
output_items buffer(s) is (are) really just pointing to the write
pointer.
File Source is only allowed to produce so many items that the write pointer doesn't advance beyond the minimum read pointer, because in that case, it would overwrite samples that a downstream block hasn't consumed.

Why can't one clone a `Space` in Gecode before solving the original one?

I'm looking for a way to copy Space instances in Gecode and then analyze the difference between the spaces later.
However it goes already wrong after the first copy. When one copies the code in the book Modelling and Programming in Gecode, as shown here below, and simply modifies it such that a copy is made first (SendMoreMoney* smm = m->copy(true);), one gets a Segmentation fault, regardless whether the shared option is true or false.
#include <gecode/int.hh>
#include <gecode/search.hh>
using namespace Gecode;
class SendMoreMoney : public Space {
protected:
IntVarArray l;
public:
SendMoreMoney(void) : l(*this, 8, 0, 9) {
IntVar s(l[0]), e(l[1]), n(l[2]), d(l[3]),
m(l[4]), o(l[5]), r(l[6]), y(l[7]);
// no leading zeros
rel(*this, s, IRT_NQ, 0);
rel(*this, m, IRT_NQ, 0);
// all letters distinct
distinct(*this, l);
// linear equation
IntArgs c(4+4+5); IntVarArgs x(4+4+5);
c[0]=1000; c[1]=100; c[2]=10; c[3]=1;
x[0]=s; x[1]=e; x[2]=n; x[3]=d;
c[4]=1000; c[5]=100; c[6]=10; c[7]=1;
x[4]=m; x[5]=o; x[6]=r; x[7]=e;
c[8]=-10000; c[9]=-1000; c[10]=-100; c[11]=-10; c[12]=-1;
x[8]=m; x[9]=o; x[10]=n; x[11]=e; x[12]=y;
linear(*this, c, x, IRT_EQ, 0);
// post branching
branch(*this, l, INT_VAR_SIZE_MIN(), INT_VAL_MIN());
}
// search support
SendMoreMoney(bool share, SendMoreMoney& s) : Space(share, s) {
l.update(*this, share, s.l);
}
virtual SendMoreMoney* copy(bool share) {
return new SendMoreMoney(share,*this);
}
// print solution
void print(void) const {
std::cout << l << std::endl;
}
};
// main function
int main(int argc, char* argv[]) {
// create model and search engine
SendMoreMoney* m = new SendMoreMoney;
SendMoreMoney* mc = m->copy(true);
DFS<SendMoreMoney> e(m);
delete m;
// search and print all solutions
while (SendMoreMoney* s = e.next()) {
s->print(); delete s;
}
return 0;
}
How can one make a real copy?
You have to call status() on the Space first.
I found this exchange in the Gecode mailing list archives: https://www.gecode.org/users-archive/2006-March/000439.html
It would seem that internally, Gecode uses the copy function and constructor for its own internal purposes, so to make a "copy-by-value" copy of a space, you need to use the clone() function defined in the Space interface. However, as noted in #Anonymous answer, you need to call status() before calling clone or it will throw an exception of type SpaceNotStable
I augmented my space with the function below to automatically call status, make the clone, and return a pointer of my derived type:
struct Example : public Space {
...
Example * cast_clone() {
status();
return static_cast<Example *>(this->clone());
}
...
}
As a workaround, one can create a totally independent space and then use equality constraints
on the variable level to reduce the domains of these variables.
Example:
void cloneHalfValues(SendMoreMoney* origin) {
int n = l.size();
for(int i = 0x00; i < n/2; i++) {
if(origin->l[i].assigned()) {
rel(*this, l[i], IRT_EQ, origin->l[i].val());
}
}
}
The reason why one can't clone a Space is however still a mystery.