I have a directory with 15 folders and each folder has 100 of text files. In each text files contains a column of numbers.
I need those numbers to do some calculations, but I cannot figure out how to obtain it. I was thinking about a 2D vector, but I need different type of data structure (string for the name of the folder and interger for the numbers).
What is my best solution?d
What I got so far is a code that will search all the files by given a path.
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <algorithm>
#include <tuple>
#include <boost/filesystem.hpp>
#include<dirent.h>
using namespace std;
namespace fs = boost::filesyst
// prototype to search all the files by given it a path
vector<double> getFilesFromDirectory(const fs::path& startDirectory);
int main()
{ // the directory
string dir = "/home/...";
// testing to call my methode
vector<double> myDataStructure = getFilesFromDirectory(dir);
// print out the value of myDataStructure
for (auto it = myDataStructure.begin(); it != myDataStructure.end(); it++)
{
cout << *it << " " << endl;
}
return 0;
}
// methode to search all the files by given it a path
vector<double> getFilesFromDirectory(const fs::path& startDirectory)
{
vector<double> di;
// First check if the start path exists
if (!fs::exists(startDirectory) || !fs::is_directory(startDirectory))
{
cout << "Given path not a directory or does not exist" << endl;
exit(1);
}
// Create iterators for iterating all entries in the directory
fs::recursive_directory_iterator it(startDirectory); // Directory iterator at the start of the directory
fs::recursive_directory_iterator end; // Directory iterator by default at the end
// Iterate all entries in the directory and sub directories
while (it != end)
{
// Print leading spaces
for (int i = 0; i < it.level(); i++)
cout << "";
// Check if the directory entry is an directory
// When directory, print directory name.
// Else print just the file name.
if (fs::is_directory(it->status()))
{
// print out the path file
cout << it->path() << endl;
}
else
{
cout << it->path().filename() << endl;
// test
di = getValueFromFile(it->path().c_str());
// test, here I want to group the numbers of the file
// and each name of the folder
for(int i = 0; i < 15; i++)
{
di.push_back(mi(fs::basename(it->path()), it->path().c_str());
}
}
// When a symbolic link, don't iterate it. Can cause infinite loop.
if (fs::is_symlink(it->status()))
it.no_push();
// Next directory entry
it++;
}
return di;
}
If I understand the problem correctly, I'd write a class (or struct) to hold the contents of each file:
A string containing the path:
A vector containing every value represented in the column for that file
In your main program, a vector containing each object you create.
Definition:
#ifndef __COLVALS_HPP__
#define __COLVALS_HPP__
#include <vector>
#include <string>
class ColVals {
private:
std::vector<double> _colValues;
std::string _pathName;
public:
ColVals(const std::string& pathName);
~ColVals() {}
void appendValue(const double colValue);
std::vector<double> getValues();
std::string getPath();
};
#endif // __COLVALS_HPP__
Implementation:
#include "colvals.hpp"
using namespace std;
ColVals::ColVals(const string& pathName) {
_pathName = pathName;
}
void ColVals::appendValue(const double colValue) {
_colValues.push_back(colValue);
}
vector<double> ColVals::getValues() {
return _colValues;
}
string ColVals::getPath() {
return _pathName;
}
Related
Hello so basically what i want is to loop through all folders in a given directory and find a folder which contains 4p in it´s name
for (const auto& folderIter : filesystem::directory_iterator(roaming))
{
if (folderIter.path() == folderIter.path().string().contains("4p") != std::string::npos)
{
filesystem::remove(folderIter.path());
}
}
But this code does not work
Since you told:
im trying to find a folder which starts with the name 4p. Nothing more
Does this meet your demands?:
#include <iostream>
#include <vector>
using namespace std;
int
main ()
{
std::vector < std::string > _strings;
// adding some elements to iterate over the vector
_strings.emplace_back ("4p_path");
_strings.emplace_back ("4p_path1");
_strings.emplace_back ("3p_path");
_strings.emplace_back ("4p_path2");
_strings.emplace_back ("2p_path");
_strings.emplace_back ("4p_path3");
for (const auto & p:_strings)
{
std::string first_two = p.substr (0, 2);// 0 = begin, 2 = end
if (first_two == std::string ("4p")) // I assume 4p as suffix
{
std::cout << "4p\n";
}
else
{
std::cout << "not 4p\n";
}
}
return 0;
}
Since you said that I have to find exact folders that have 4p suffixes, I should add this one:
#include <string>
#include <iostream>
#include <filesystem>
namespace fs = std::filesystem;
int main()
{
std::vector < std::string > _Folders;
std::string path = "F:\\MyMusicProjects";// your directory
// get the name of all folders and add it into folders vector
for (const auto& entry : fs::directory_iterator(path)) {
_Folders.emplace_back(std::string(entry.path().filename().string()));
}
// iterate over folders
for (const auto& p : _Folders)
{
// p variable is the folder name and we compare it to check wheter it starts with 4p or not
if (p.substr(0, 2) == "4p")
std::cout << "found\t" << path << "\\" << p << "\n";
else
std::cout << "was not 4p\t" << path<< "\\" << p << "\n";
// don't forget, p is the folder name, to get full path as string:
// std::string fullPath = path+"\\"+p;
}
return 0;
}
Hello guys I'am trying to insert numbers form text file into a vector of int
the text file called "graphe.txt" its content like :
enter image description here
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sstream>
#include <cstdlib>
using namespace std;
void load(ifstream & inputFile, vector < int > G) {
string currentLine;
if (inputFile.is_open()) //Always test the file open.
{
while (getline(inputFile, currentLine)) {
if (currentLine.length() == 0) {
break;
} else {
int s = stoi(currentLine);
G.push_back(s);
}
}
inputFile.close();
} else
cout << "file is not open" << '\n';
}
void shwTab(vector < int > G) {
vector < int > ::iterator it;
for (it = G.begin(); it != G.end(); ++it)
cout << * it << " \n";
cout << endl;
}
int main() {
ifstream inputFile("graphe.txt");
vector < int > G;
load(inputFile, G);
shwTab(G);
return 0;
}
and the output is like :
https://i.stack.imgur.com/1Wx03.png
I dont know exactly where the problem is ? the numbers doesnt appear !
Pass vector<int> G as reference, in your example a copy of G is passed to load.
void load(ifstream& inputFile,vector<int> &G)
Notice the & before G.
Not that relevant, but you could do the same for the shwTab function:
void shwTab (vector<int> &G)
to avoid copying the entire vector. It's not necessary, but you do save some memory.
So let's say i have this code that looks for documents of mine and prints the path to them.
#include <iostream>
#include <experimental/filesystem>
#include <string>
#include <stdio.h>
#include <Shlwapi.h>
using namespace std;
string extensions[3] = { ".doc", ".docx", ".txt" }; // things to look for
string ignoredirs[2] = { "Windows", "Program Files", } // and other ones that i was too
// lazy to write in there
using namespace std::experimental::filesystem;
path yee;
void main()
{
for (recursive_directory_iterator i("c:\\"), end; i != end; ++i)
if (!is_directory(i->path()) && i->path().has_extension()) // checks if the file
// even has an extension
{
for (int x = 0; x <= 3; ++x)
if (i->path().extension().string() == extensions[x])// checks if the
// extension is equal
// to current
// extension in loop
cout << "found document at :" ;
cout << i->path().string() << endl; // print out the path
}
}
And I would like to not iterate to directories in ignoredir[] because it takes ages to find my docs on the filesystem.
I saw this code from cppreference.com.
Could someone explain me the the code and/or how to use it in my use case?
Pr could you submit a better solution than that?
Ps. I don't want to use boost in this program, just to see how it works in experimental::filesystem
Proposed solution:
#include <iostream>
#include <experimental/filesystem>
#include <string>
#include <stdio.h>
#include <Shlwapi.h>
#include <set>
using namespace std;
set<string> extensions = { ".doc", ".docx", ".txt" }; //things to look for
set<string> ignoredirs = { "Windows", "Program Files" }; //and other ones that i was too lazy to write in there
using namespace std::experimental::filesystem;
int main()
{
for (recursive_directory_iterator i("c:\\"), end; i != end; ++i)
{
if (!is_directory(i->path()) && i->path().has_extension()) // checks ifthe file even has an extension
{
if (extensions.find(i->path().extension().string()) != extensions.end())
cout << "found document at :";
cout << i->path().string() << endl; //print out the path
}
if (ignoredirs.find(i->path().filename().string()) != ignoredirs.end())
i.disable_recursion_pending();
}
}
Explanation:
i->path().filename() actually return directory name, when the same directory name is in set<> then i.disable_recursion_pending(); is called. When this one is called recursive_directory_iterator i omit directory with i->path().filename() name.
set<string> was used to get rid internal for loop that requires size of table, which is error prone. Also performance gain and code simplification
Notice:
On windows directory names should be compared case insensitive. Also Windows 64bit have "Program Files" and "Program Files (x86)" and both need to be listed in ignore list (or string comparison need to be improved)
I'm getting a strange error when trying to iterate a Map of Vectors. I'm using the Stanford CS106B class libraries for this project and when I try to compile the code I get an error telling me that "itr has no member named 'first' "
I have tried searching for solutions to this problem and I have found many similar entries but the answers seem to mimic what I'm doing. I'm sure I'm missing something simple...
#include <iostream>
#include <fstream>
#include <string>
#include "console.h"
#include "simpio.h" // for getLine
#include "strlib.h"
#include "vector.h"
#include "queue.h"
#include "map.h"
#include <iterator>
using namespace std;
void CountLetters(ifstream &filename) {
int index=0;
Vector<int> counts;
for (int i=0; i<=26; i++) {
counts.add(0);
}
char c;
while (!filename.eof()) {
c=filename.get();
index=c-'a';
if (index>=0 && index<26) {
c=stringToChar(toLowerCase(charToString(c)));
counts[index]++;
}
}
for (int y=0; y<=26; y++) {
cout << char('a'+y) << ": " << counts[y] << endl;
}
filename.close();
}
Map <string, Vector<char> > assembleSets (ifstream &in, int seed) {
Map <string, Vector<char> > letterSets;
char c;
Vector<char> workingText;
string letterSet;
while(!in.eof()) {
if (workingText.size()<seed) { // Build the intial set of "seed" letters.
c=in.get();
workingText.add(c);
}
else {
c=in.get();
letterSet.clear();
for (int i=0; i<workingText.size()-1; i++) {
letterSet+=workingText[i]; // add the letter to the letter set.
workingText[i]=workingText[i+1]; // move the letter down one in the vector (simulate queue).
}
letterSet+=workingText[seed-1];
workingText[seed-1]=c; // add the newwest letter to the workingText but do not add it to the letter set.
// Check to see if the letter set exists already, if not, add it.
if (!letterSets.containsKey(letterSet)) {
Vector<char> blank;
letterSets.add(letterSet,blank);
letterSets[letterSet].add(c);
}
else {
// Add the next character to the vector of characters for that letter set.
letterSets[letterSet].add(c);
}
}
}
return letterSets;
}
int main() {
ifstream in;
int mSeed =0;
while (true) {
string fileName = getLine("Please enter a file name");
in.open(fileName);
if(in.fail()) cout << "Couldn't open file!" << endl;
else break;
}
// CountLetters(in);
while (true) {
mSeed=getInteger("Enter a seed value: ");
if (mSeed>0&&mSeed<=10) {
break;
} else {
cout << "Please choose a value from 1 to 10." << endl;
}
}
Map<string, Vector<char> > letterSets = assembleSets(in, mSeed);
Map<string, Vector<char> > :: iterator itr;
for (auto& it: letterSets) {
string keys = (it.first);
Vector<char> values = it.second;
}
return 0;
}
Any help would be fantastic! I'm really scratching my head.
It simply means that Map<string, Vector<char> > :: iterator.
Using std::map instead of Map and std::vector instead of Vector compiles correctly.
Check the implementation of your custom iterator.
Anyway i suggest you using the range-based syntax for this (if you use the C++ standard library):
for (auto& it : letterSets)
{
string key = it.first;
vector<char> values = it.second;
}
so the write elm and getfileID functions require the cursor pos in the file
(write elm appends to the end, getFileID prints lines first to last)
#ifndef file_operations_header
#define file_operations_header
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include "First_classes_header.h"
class fileOPerations
{
private:
string line;
fstream f_myFileOut;
public:
fileOPerations();
void closeFile()
{
f_myFileOut.close();
}
int getFileID()
{
int counter = 0;
if (f_myFileOut.is_open())
{
while(f_myFileOut.good()){
getline(f_myFileOut,line);
++counter;
cout << line << endl;
}
}f_myFileOut.close();
return counter;
}
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
if (f_myFileOut.is_open())
{
f_myFileOut << mV.str_vector[i].counter << "\t";
f_myFileOut << mV.str_vector[i].name << endl;
}
else{
cout << "can't open file." << endl;
}
return 0;
}
friend class makeVector;
};
fileOPerations::fileOPerations():f_myFileOut("file.txt",ios::out|ios::app|ios::in){}
#endif // file_operations_header
and the call to getFileID in my main doesn't print anything because writeElm()
set the cursor pos to the end of the file.
#include <iostream>
#include <string.h>
#include <vector>
#include "First_classes_header.h"
#include "file_operations.h"
using namespace std;
int main()
{
fileOPerations fpObject;
makeVector vecObject;
int fileID = fpObject.getFileID();
while(true){
IDgenerator();
int genID = IDgenerator::GetID();
int currentID = fileID + genID;
string workingName = nameGetter::setName();
vecObject.vecSetter(currentID,workingName);
fpObject.writeElm(vecObject, currentID); // error within this function
fpObject.getFileID();
}fpObject.closeFile();
return 0;
}
Is it safe/effecient/effective to call f_myFileOut.open() with different parameters
in each separate function?
int getFileID()
{
f_myFileOut.open(("file.txt",ios::out|ios::app|ios::in)
int counter = 0;
...
...
int writeElm(makeVector& mV,int i)
{
f_myFileOut.open("file.txt",ios::out|ios::app|ios::ate);
Or should I set the cursor pos manually?
While it is certainly not efficient, to open/close the same file over and over again, it would be safe, and I'd even call it better coding style, because currently you are opening a file in one method and closing it in another, and in both cases it is not obvious from the function name that this is one of their side effects (contratry to e.g. closeFile()). Also you are already opening/closing the file in every iteration, so this would "only" double the open/close operations.
In general however, I'd definitively recommend to open the file once at the beginning of your program, close it at the end and e.g. use f_myFileOut.seekg (0,f_myFileOut.beg) and f_myFileOut.seekg (0,f_myFileOut.end) in between, to move your iterator around.