I want to crop just only jpg files in a directory.
Tried if statement, but don't know what should inside if().
void Cutimage::load_images(string img_prefix)
{
for (const auto& entry : fs::directory_iterator(img_prefix)) {
cout << entry.path() << endl; //output all directory's filenames
if () { //I applied some statements but doesn't work
string path_string = entry.path().string();
crop_images(path_string);
}
}
No, the filesystem utilities of the standard library do not have such feature. However, it is fairly simple to iterate all directory entries, and conditionally perform an operation if the file name ends in ".jpg", which appears to be what you've attempted.
Tried if statement, but don't know what should inside if().
The directory entry has an member function that returns the full path of the directory. The path class has an member function that returns a string. The string class has a member function that returns true if the string ends with the sub string given as an operand. This appears to be what you're looking for.
Related
I'm trying to open a directory, the name of which (path) is currently in a std::string read in originally from a .csv file (although I don't think that changes anything about the string itself). Calling opendir(path.c_str()) returns NULL. I tried the following code, doing the conversion outside of opendir():
DIR *dir;
bool first = True;
string level = "";
struct dirent *ent;
const char * c = path.c_str();
// A
if ((dir = opendir(c)) != NULL){
// do stuff
// should open the directory and go here
}else{
// always ends up here
}
While this failed with path="LeanDataBase", a directory in the project folder, substituting opendir("LeanDataBase") for opendir(c) does seem to open the directory. However, this function is recursive, so I can't hard code this value or it doesn't work and falls into an infinite loop.
I also tried printing the types, with the following two lines inserted right after "A" in the previous code:
cout << typeid(c).name() << endl;
cout << typeid("LeanDataBase").name() << endl;
Which yielded the following output:
PKc
A13_c
Does this mean that I'm passing the wrong type to opendir()? It seems like it can handle PKc, but not A13_c. Is there a way to convert the path string to the proper type?
Looking at my crystall ball, I see the following issue: path is modified (or even leaves the scope) after path.c_str() is called, but before opendir() is called. It is usually a bad practice to remember result of c_str() in any variable, as it leads to issues like this. c_str() is intended for in-place usage, like following
opendir(path.c_str());
Is there a way in c++ to pass to a method a variable where that variable could be one of several different variables (of same type) depending on where the method is called.
For example:
A method to check if a file exists with the correct name.
At one point in the program, I might want to check a users file exists, so the user enters their username into string variable username, and that is passed to CheckFile:
bool LotterySystem::CheckFile(const std::string &USERNAME)
{
//if file exists, return false, else return true
FILE *fin = fopen((USERNAME + ".txt").c_str(), "r");
if (fin)
{
fclose(fin);
return false;
}
return true;
}
At another point I might want to check a file with stock information exists, so the user enters the stock they wish to check into string variable stockType:
bool LotterySystem::CheckFile(const std::string &STOCKTYPE)
{
//if file exists, return false, else return true
FILE *fin = fopen((STOCKTYPE + ".txt").c_str(), "r");
if (fin)
{
fclose(fin);
return false;
}
return true;
}
Is there a way to pass a generic string variable with any name, to CheckFile, without having to have different CheckFile methods for every file name to be checked?
You don't need differnt CheckFile methods. In fact, having more than one would result in a multiple definition error, because you are defining two methods with the same signature.
Just call it with different arguments:
LotterySystem ls;
ls.CheckFile("MyNameIsFred");
ls.CheckFile("MyPreferredPreferredStockName");
It seems like you want to pass different values of type const std::string, which in C++ can be passed simply using a single function. You will have to change the value which you are calling the function, not create different instances of the bool LotterySystem::CheckFile method.
And also, no compiler would compile the two instances of the same function, with same parameters.
bool LotterySystem::CheckFile(const std::string &USERNAME)
{
//if file exists, return false, else return true
FILE *fin = fopen((USERNAME + ".txt").c_str(), "r");
if (fin)
{
fclose(fin);
return false;
}
return true;
}
Then call:
LotterySystem mySystem;
std::string sName = "John Doe", sStockName = "ZXY";
bool nameFileExists = mySystem.CheckFile(sName);
bool stockFileExists = mySystem.CheckFile(sStockName);
It seems like you want to alter the semantics of the function by changing the name in the signature. That's not how it works. As chris states in the comments, the function's semantics stay the same, no matter what string you pass - only the return value will change, depending on what functions used in CheckFile return. Giving the string a different name does not create another overload of CheckFile and will not, in any way, alter the semantics or code flow within the function.
What you want is a dedicated function per purpose. CheckFile should just do what the name suggests(well, sort of): check whether the txt file denoted by the string you pass exists.
Layered on CheckFile you might want to implement additional functionality for the purpose of checking different types of files. That being said, if you're dealing with text-files, you need to parse and validate the contents anyway to be sure you actually have a valid user file or a stock-info file. In essence, you want something like this:
bool IsUserFile(const std::string&); // validates text-file contents
bool processUserFile(const std::string& path) // path omitting the extension '.txt'
{
if(!(CheckFile(path) && IsUserFile(path)))
return false;
// open file process contents
// return true if successful, false otherwise
}
Similarly for stock-info files.
On another note, there is no need to make such a function a member function of LotterySystem and if you insist on making it a member function, consider making it a static member function - it doesn't depend on an instance of LotterySystem.
Also, if I understand your intentions correctly, you want to check if a file exists. So, your CheckFile function needs to return true if it can open the file. Currently, it does exactly the opposite. Leave a comment if I'm mistaken.
Please note: checking for the existence of a file only by seeing if your application can open it is a very restricted case. It might exist and fopen() might still not be able to open it, be it due to insufficient privileges or other conditions.
This is a follow up question from here: C++ - Developing own version of std::count_if?
I have the following function:
// vector for storing the file names that contains sound
std::vector<std::string> FilesContainingSound;
void ContainsSound(const std::unique_ptr<Signal>& s)
{
// Open the Wav file
Wav waveFile = Wav("Samples/" + s->filename_);
// Copy the signal that contains the sufficient energy
std::copy_if(waveFile.Signal().begin(), waveFile.Signal().end(),
FilesContainingSound.begin(), [] (const Signal& s) {
// If the energy bin > threshold then store the
// file name inside FilesContaining
}
}
But to me, I only need to capture the string "filename" inside of the lambda expression, because I'll only be working with this. I just need access to the waveFile.Signal() in order to do the analysis.
Anyone have any suggestions?
EDIT:
std::vector<std::string> FilesContainingSound;
std::copy_if(w.Signal().begin(), w.Signal().end(),
FilesContainingSound.begin(), [&] (const std::unique_ptr<Signal>& file) {
// If the energy bin > threshold then store the
// file name inside FilesContaining
});
You seem to be getting different levels of abstraction confused here. If you're going to work with file names, then you basically want something on this order:
std::vector<std::string> input_files;
std::vector<std::string> files_that_contain_sound;
bool file_contains_sound(std::string const &filename) {
Wav waveFile = Wav("Samples/" + filename);
return binned_energy_greater(waveFile, threshold);
}
std::copy_if(input_files.begin(), input_files.end(),
std::back_inserter(files_that_contain_sound),
file_contains_sound);
For the moment I've put the file_contains_sound in a separate function simply to make its type clear -- since you're dealing with file names, it must take a file name as a string, and return a bool indicating whether that file name is one of the group you want in your result set.
In reality, you almost never really want to implement that as an actual function though--you usually want it to be an object of some class that overloads operator() (and a lambda is an easy way to generate a class like that). The type involved must remain the same though: it still needs to take a file name (string) as a parameter, and return a bool to indicate whether that file name is one you want in your result set. Everything dealing with what's inside the file will happen inside of that function (or something it calls).
Given the path you are search under, and the file name contains regular expression, is there any way to check whether there is any file satisfy the file name pattern exists under this path? In C++?? for example:
under path
/path
I want to search the file "foo.*"
foo.*
the result could be foo.1 or foo.2 or whatever. I would like to get the result(I mean I want to know whether the file exist and the exact file name), Thanks
Look into boost::filesystem, otherwise you will need to look at the api for your os.
Here is an example (untested):
boost::filesystem::path dir("/path");
boost::filesystem::directory_iterator it(dir), end;
BOOST_FOREACH(const boost::filesystem::path& p, std::make_pair(it, end))
{
if(boost::filesystem::is_regular_file(p))
{
if(p.stem().string() == "foo")
{
std::cout << p.extension() << '\n';
}
}
}
I have inherited a fairly large codebase, 90% C++, and I need to get up to speed on it quickly. There are hundreds of .cc files in a wide directory tree structure.
It's fairly complex, and has no logging. In order to figure out how some major subsystems work, I want to insert a function call into every function.
E.g., given a .cc file full of stuff like this:
void A::foo(int a, int b) {
// ...
}
void A::bar() {
// ...
}
void B::bleh(const string& in) {
// ...
}
I'd like to get this:
void A::foo(int a, int b) {
LOG(debug) << "A::foo() called.";
// ...
}
void A::bar() {
LOG(debug) << "A::bar() called.";
// ...
}
void B::bleh(const string& in) {
LOG(debug) << "B::bleh() called.";
// ...
}
This can be done via python script, CMD script, power shell script, etc. If there is a way to make VS do it, great. Whatever works. Doesn't have to be pretty, I'm not checking any of this in.
Also, it doesn't necessarily need to get everything. E.g. nested classes, implementations in header files, etc.
Had something similar for adding profiling code using Macros in VS, here's the code
(this also groups everything under a single "undo" command and lists all of the changes in its own output window)
Imports System
Imports EnvDTE
Imports EnvDTE80
Imports System.Diagnostics
Public Module Module1
Function GetOutputWindowPane(ByVal Name As String, Optional ByVal show As Boolean = True) As OutputWindowPane
Dim window As Window
Dim outputWindow As OutputWindow
Dim outputWindowPane As OutputWindowPane
window = DTE.Windows.Item(EnvDTE.Constants.vsWindowKindOutput)
If show Then window.Visible = True
outputWindow = window.Object
Try
outputWindowPane = outputWindow.OutputWindowPanes.Item(Name)
Catch e As System.Exception
outputWindowPane = outputWindow.OutputWindowPanes.Add(Name)
End Try
outputWindowPane.Activate()
Return outputWindowPane
End Function
Const ToInsert As String = "/* Inserted text :D */"
Sub AddProfilingToFunction(ByVal func As CodeFunction2)
Dim editPoint As EditPoint2 = func.StartPoint.CreateEditPoint()
While editPoint.GetText(1) <> "{"
editPoint.CharRight()
End While
editPoint.CharRight()
editPoint.InsertNewLine(1)
Dim insertStartLine As Integer = editPoint.Line
Dim insertStartChar As Integer = editPoint.LineCharOffset
editPoint.Insert(ToInsert)
GetOutputWindowPane("Macro Inserted Code").OutputString( _
editPoint.Parent.Parent.FullName & _
"(" & insertStartLine & "," & insertStartChar & _
") : Inserted Code """ & ToInsert & """" & vbCrLf)
End Sub
Sub AddProfilingToProject(ByVal proj As Project)
If Not proj.CodeModel() Is Nothing Then
Dim EventTitle As String = "Add Profiling to project '" & proj.Name & "'"
GetOutputWindowPane("Macro Inserted Code").OutputString("Add Profiling to project '" & proj.Name & "'" & vbCrLf)
DTE.UndoContext.Open(EventTitle)
Try
Dim allNames As String = ""
For i As Integer = 1 To proj.CodeModel().CodeElements.Count()
If proj.CodeModel().CodeElements.Item(i).Kind = vsCMElement.vsCMElementFunction Then
AddProfilingToFunction(proj.CodeModel().CodeElements.Item(i))
End If
Next
Finally
DTE.UndoContext.Close()
End Try
GetOutputWindowPane("Macro Inserted Code").OutputString(vbCrLf)
End If
End Sub
Sub AddProfilingToSolution()
GetOutputWindowPane("Macro Inserted Code").Clear()
If Not DTE.Solution Is Nothing And DTE.Solution.IsOpen() Then
For i As Integer = 1 To DTE.Solution.Projects.Count()
AddProfilingToProject(DTE.Solution.Projects.Item(i))
Next
End If
End Sub
End Module
P.S
Remember to change the "Const ToInsert As String = ..." to the code you actually want to be inserted
Since you're using Visual C++, and it seems you only need the name of the function called, it might be possible to automate this further using the following command-line switches to cl.exe:
/Gh: Enable _penter function call
/GH: Enable _pexit function call
Basically, providing these switches means that the compiler will automatically inject calls to functions named _penter() and _pexit() whenever any function begins or ends. You can then provide a separately-compiled module that implements these two functions, which either (a) calls some helper library such as DbgHelp to determine the name of the called function, or (b) just grabs the return address from the stack and prints it verbatim -- afterwards, write a script to transform these addresses into function names by looking at e.g. the linker map file produced if you pass /link /MAP:mymapfile.txt to cl.exe.
Of course, you'll need to put your _penter() and _pexit() in a separate module with /Gh and /GH turned off to avoid infinite recursion! :)
I did it some years ago in VS.
Regex will help you.
BTW, it not nesasary to insert different string. You can add the same string like:
LOG(debug) << __FUNCTION__ << " called.";
EDIT
something like this regexp (valid for VS only):
(void|char|int):b+:i\:\::i\([^(]*\):b*\{
You should extend the regexp depending of your needs.
A run-time profiler will kind of give you that information: it will tell what subroutines were called from each routine, and how many times (but not, in what sequence).
Have you considered running the code within a debugger, and simply stepping through the entire application (or otherwise setting a breakpoint on the code you're interested in and just stepping through that)? I find that to sometimes be a useful technique when faced with a large legacy code base that I didn't write.
Alternatively, if you're compiling in the VS world, consider taking a look at the /Gh and
/GH switches to cl.exe. They seem to allow you to hook function entry/exit and call some other routine. I've never used them before, but they seem to directly address your need.