Error checking for empty directory in C++ - c++

I'm trying to create a folder named by todays date (on Ubuntu) and then check if it's empty or not.
The empty-or-not check will be done several times daily.
#include <cstdlib>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <typeinfo>
#include <chrono>
#include <time.h>
#include <iomanip>
using namespace std;
int main() {
//Pull out system date and create a folder named by system date
auto const now = std::chrono::system_clock::now();
auto const in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&in_time_t), "%d_%m_%Y");
// Creating todays date folder with entry folder
string str_2=std::string("mkdir -p " + string(ss.str()) + "/entry");
const char *com2=str_2.c_str();
system(com2);
//check if directory is empty or not
int check;
char is_empty[100];
FILE * output;
output = popen("ls " + ss.str() + "/entry | wc -l","r") ;
fgets (is_empty, 100, output); //write to the char
pclose (output);
check = atoi(is_empty);
if (check == 0) {
cout << "The folder is empty" << endl;
}
}
I'm getting this error when compiling this code:
error: no match for ‘operator+’ (operand types are ‘const char [4]’
and ‘std::stringstream {aka std::__cxx11::basic_stringstream<char>}’)
output = popen("ls " +ss+ "/entry | wc -l","r") ;

This solved it for me
int check;
char is_empty[100];
FILE * output;
string cmd = std::string("ls " + string(ss.str())+ "/entry | wc -l") ;
const char *com4 = cmd.c_str();
output = popen(com4,"r");
fgets(is_empty, 100, output);
pclose (output);
check = atoi(is_empty);
//cout << check<<endl;
if (check == 0){
cout << "The folder is empty" << endl;
}

Related

C++ values from struct creating newlines in CSV file

I am very new to C++, and currently am attempting to create a simple user interface which will do the following:
Check if a CSV file already exists with the given name
Create that file if it does not exists, and write the headers
Ask user for information, store in struct
Write data to CSV file when done
The issue I am facing is that when the program ends, and writes the data to the CSV file it creates newlines for each struct variable I am writing. I would like the program to just write all data on one line with comma separated format.
Example code:
struct.h
#ifndef struct_h
#define struct_h
#include "string"
namespace RB
{
struct Values
{
std::string event;
std::string town;
std::string state;
std::string date;
};
}; // namespace
#endif /* struct_h */
create.h
#ifndef create_h
#define create_h
#include <cstdio>
#include <ctime>
#include <iostream>
#include <fstream>
namespace RB
{
int createFile()
{
time_t t = time(nullptr); // the current time
struct tm gmt = *gmtime(&t); // structured time in GMT
const int year = 1900 + gmt.tm_year;
static const char *filename = "results_";
if (std::ifstream((filename + std::to_string(year) + ".csv").c_str()))
{
std::cout << "File Found, appending to file " << (filename + std::to_string(year) + ".csv").c_str() << std::endl;
}
else
{
std::cout << "No file with name " << (filename + std::to_string(year) + ".csv").c_str() << "\ncreating file...\n" << std::endl;
std::ofstream ofile((filename + std::to_string(year) + ".csv").c_str());
ofile << "Event" << ","
<< "Town" << ","
<< "State" << ","
<< "Date" << "\n";
ofile.flush();
ofile.close();
};
return 0;
};
}
#endif /* create_h */
main.cpp
#include <cstdio>
#include <stdlib.h>
#include <iostream>
#include "struct.h"
#include "create.h"
int main()
{
// Run Create before continuing
int c = RB::createFile();
struct RB::Values revent;
// Get Event Name
std::cout << "Starting to enter data for race event...\n" << std::endl;
std::cout << "What was the name of the event: ";
std::cin >> revent.event;
// Get Event Town
std::cout << "What town was the race run in: ";
std::cin >> revent.town;
// Get Event City
std::cout << "What state was the race run in: ";
std::cin >> revent.state;
// Get Event Date
std::cout << "When was the race run: ";
std::cin >> revent.date;
time_t t = time(nullptr); // the current time
struct tm gmt = *gmtime(&t); // structured time in GMT
const int year = 1900 + gmt.tm_year;
static const char *filename = "results_";
if (std::ifstream((filename + std::to_string(year) + ".csv").c_str()))
{
std::ofstream ofile((filename + std::to_string(year) + ".csv").c_str(), std::ofstream::out | std::ofstream::app);
ofile << revent.event << ",";
ofile << revent.town << ",";
ofile << revent.state << ",";
ofile << revent.date;
ofile.close();
};
return 0;
}
Sample Output:
Event,Town,State,Date
CapRock
,Turkey
,Texas
,March 9
I assume this is something simple I am doing wrong, but cannot seem to figure it out on my own.

Unable to create a folder with todays date in c++

Im trying to create a folder with todays date in c++. WHile in python its very easy , in c++ im finding it challenging.
I tried this code where first I tried to print the date and then use the date values to create a folder. I even tried inserting unix commands but even those didnt work.
I simply want to create a directory like : DD_MM_YYYY or DD_MM_YY
#include <bits/stdc++.h>
#include <iostream>
#include <sys/stat.h>
#include <sys/types.h>
#include "time.h"
//#include "date/tz.h"
using namespace std;
using namespace std::chrono;
int main()
{ //option 1
time_t my_time =time(NULL);
cout << ctime(&my_time)<<endl;
///option 2
time_t t = time(NULL);
struct tm tm = *localtime(&t);
printf("now: %d-%d-%d %d:%d:%d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec);
printf("Date: %d_%d_%d\n", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday);
// EXPERIMENT SECTION : ALL OF THESE THROWING ERRORS
//sub_fol=(tm.tm_year+1900).ToString()+"."+tm.tm_mon.ToString();
//sub_fol=tm.tm_mon;
string str="date +'%d_%m_%y'";
//str="mkdir "+ str;
const char *command=str.c_str();
//string dr=system(command);
//printf(string(tm.tm_mon));
// THIS ONES WORKING
if (mkdir("test_", 0777) == -1)
cerr << "Error : " << strerror(errno) << endl;
else
cout << "Directory created";
// THIS ONE ISNT WORKING
if (mkdir(system(command), 0777) == -1)
cerr << "Error : " << strerror(errno) << endl;
else
cout << "Directory created";
}
You can make use of std::localtime and std::puttime to get a formatted date.
For example:
#include <iostream>
#include <chrono>
#include <sstream>
#include <iomanip>
int main()
{
auto const now = std::chrono::system_clock::now();
auto const in_time_t = std::chrono::system_clock::to_time_t(now);
std::stringstream ss;
ss << std::put_time(std::localtime(&in_time_t), "%d_%m_%Y");
std::cout << ss.str() << std::endl;
}
Will get you:
14_01_2021
You can see https://en.cppreference.com/w/cpp/io/manip/put_time for more formatting options.
Then you can use mkdir or make use of std::filesystem if you are using C++17 or above.
#include <filesystem>
...
std::filesystem::create_directory("abc");
See https://en.cppreference.com/w/cpp/filesystem/create_directory
For mkdir it expects a const char *path rather than a std::string but you can get a char pointer via c_str() e.g.:
mkdir(ss.str().c_str(), 0700);

Variable inside for loop

I am frustrated. I am trying to find a way to get the variable called 'line' to be accessed inside of the for loop that is at the bottom of the code.
#include <ctime>
#include <iostream>
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>
#include <Lmcons.h>
#include <fstream>
#include <windows.h>
using namespace std;
string currentmonth;
string earlydays;
//**************************************
string a3;
string a1;
int getdir (string dir, vector<string> &files)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(dir.c_str())) == NULL)
{
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}
while ((dirp = readdir(dp)) != NULL) {
std::string fname = dirp->d_name;
if(fname.find("FIN804") != std::string::npos)
files.push_back(fname);
}
}
//***************************************
int main() {
//Copy New date to be used from date database
ifstream dailyfiledate;
dailyfiledate.open("Databasedate.txt");
string line;
if (!dailyfiledate) //checks to see if file opens properly
{
cerr << "Error: Failed to copy the first string from Date Database.";
}
else
{
if (getline(dailyfiledate, line)) // Get line
cout << line; // print the line.
dailyfiledate.close(); // Remember to close the file.
}
string dir = string(a1);
vector<string> files = vector<string>();
getdir(dir,files);
for (unsigned int i = 0; i < files.size();)
{
//cout << files[i] << endl;
a3 = files[i];
cout << a3 << endl;
string b1 = a3 + line;
cout << b1 << endl;
remove(b1.c_str());
i++;
}
}
Actually, the variable was successfully being reached inside the for loop. I guess it was an oversight on my path.
And there is absolutely no error in the code above when it's compiled.
You mo'effers really need to be more humble. Give the answer, give guidance, or don't comment at all.

fixed amount of digits on creating .txt file

I need to create file with specific file name format (on windows). the format is:
Name_nodeNum_frequency.txt
nodeNum is int and frequency is float.
those two variables should be written with fixed digits:
if nodeNum is 8 --> 008
if frequency is 4.88421 --> 4.884
this is the function:
create_file(int nodeNum, double frequency)
{
char buffer [50];
//convert int to string
itoa(nodeNum, buffer, 10);
string sNodeNum = string(buffer);
//not sure about the double
//tried to_string but I got:
// more than instance of overloaded function matches the argument list
string fileName = ("Name_" + sNodeNum + "_" + sfreq + "MHZ");
FILE* pFile = OpenFile(fileName);
}
I tried to use %d, but it seems like I should not do that:
string fileName = ("Delay_" + "%3d" + "_" + sfreq + "MHZ" , sNodeNum);
I will be happy for some guidance.
thanks!
You seem to be mixing C and C++ here. A simple way to do this in C would be:
#include <stdio.h>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
char filename[50];
sprintf(filename, "Delay_%03d_%.3fMHZ.txt", sNodeNum, sfreq);
FILE* pFile = fopen(filename, "w");
return 0;
}
If on the other hand, if you want to use C++, you should make a few changes:
#include <iomanip>
#include <fstream>
#include <sstream>
#include <iostream>
int main()
{
int sNodeNum = 8;
double sfreq = 4.88421;
std::ostringstream ss;
ss << "Delay_" << std::setfill('0') << std::setw(3) << sNodeNum
<< "_" << std::setprecision(4) << sfreq << "MHZ.txt";
std::string filename(ss.str());
std::ofstream fout(filename.c_str());
return 0;
}
Each of these two approaches opens a file for writing, with the name Delay_008_4.884MHZ.txt.
Live demo link
#include <string>
#include <iomanip>
#include <iostream>
int nodeNum = 8;
float frequency = 4.88421f;
std::ostream& out = std::cout; // put your std::ofstream file or std::ostringstream
std::ios::fmtflags flags = out.flags();
out.width(3);
out.fill('0');
out.setf(std::ios::right, std::ios::adjustfield);
out << nodeNum << std::endl;
flags = out.flags(flags);
out.precision(3);
out.setf(std::ios::fixed, std::ios::floatfield);
out << frequency;
out.flags(flags);
Or even simpler:
out << std::setw(3) << std::setfill('0') << std::right << nodeNum << std::endl;
out << std::setprecision(3) << std::fixed << frequency;
Output:
008
4.884

creating files, checking if another one with the same name exists

Code(main.cpp) (C++):
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath);
if(ifs.good()){
finalPath += "dupe.txt";
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath);
}
}
ofs.open(finalPath);
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}
My problem is following.
Whenever I run this and enter, lets say 53 as for the amount, in the end it'll never create the full amount of files. It's always scaled.
Here's an example.
Defined Amont: 300 -> What I Get: 240
Defined Amount: 20 -> What I get: 15
Defined Amount: 600 -> What I get: 450
Thanks in advance.
Based on the logic of your code, you are creating a file if your ifstream object is not 'good()'. If some files aren't being created, then the error lies here.
With some digging, you'll find that the constructor for an ifstream object does not take a string, but instead a char *.
Adding a c_str() to your 'finalPath' variable should take care of this issue.
Some things to note:
You've forgotten to include fstream and iostream.
When digging into problems like this, don't use random numbers as your first test case. It was easier for me to replicate your issue by just trying to create files in numerical order.
Also don't forget 'close()' your ifstreams!
My adaptation of the code:
#include <string>
#include <sstream>
#include <stdio.h>
#include <stdlib.h>
#include <ctime>
#include <fstream>
#include <iostream>
//general vars
std::ofstream ofs;
std::ifstream ifs;
std::stringstream ss;
//spamFiles vars
std::string defPath;
int defAmt;
void spamFiles(std::string paramPath);
int main(int argc, const char * argv[])
{
srand(time_t(NULL));
std::cout << "Enter the amount of files: ";
std::cin >> ::defAmt;
std::cout << "Now enter the target path: ";
std::cin >> ::defPath;
::spamFiles(::defPath);
std::cout << defAmt << " files were created." << std::endl;
return 0;
}
void spamFiles (std::string paramPath){
//system("open -a Terminal .");
for(int i = 0; i < ::defAmt; i++){
std::string tempS;
int ranNum = rand() % 501;
ss << ranNum;
std::string ssResult = ss.str();
std::string finalPath = ::defPath + ssResult + ".txt";
ifs.open(finalPath.c_str());
while(ifs.good()){
finalPath += "dupe.txt";
ifs.open(finalPath.c_str());
}
ifs.close();
std::cout << finalPath << std::endl;
ofs.open(finalPath.c_str());
ofs << "";
ofs.close();
ss.str(std::string());
}
return;
}