Read multiple files by passing them in argv[1] - c++

This might be a basic question, but I am new to C++, so I would appreciate your understanding.
What I am trying to do is to read files from a folder and pass one of them at a time in argv[1], get some results from that file, write them in an output file specified in argv[2], then the same for the next file, and so on.
I guess it has something to do with pointers but I am not sure how to fix this.
Thank you for any input!
Here is what I have so far:
vector<string> getFilenames(string folder)
{
vector<string> names;
string search_path = folder + "/*.*";
WIN32_FIND_DATA fd;
HANDLE hFind = ::FindFirstFile(search_path.c_str(), &fd);
if (hFind != INVALID_HANDLE_VALUE) {
do {
// read all (real) files in current folder
// , delete '!' read other 2 default folder . and ..
if (!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
names.push_back(fd.cFileName);
}
} while (::FindNextFile(hFind, &fd));
::FindClose(hFind);
}
return names;
}
int main(int argc, char **argv) {
ofstream fileout(argv[2], ios::out | ios::app);
int a, b, c;
vector<string> filenames = getFilenames("folder path");
istringstream iss;
for (int i = 0; i < filenames.size(); i++) {
iss.str(filenames[i]);
iss >> argv[1];
if (readFile(a, b, c, argv[1]) == 0) {
/* do something */
}
}
fileout.close();
return 0;
}

I want to complete #Florian Klemme but I cannot comment.
There is a little example of how to iterate through command line parameters :
int main(int argc, char **argv)
{
for (auto i = int{0}; i < argc; ++i) {
// do something with argv[i];
}
}

I'm not exactly sure what your problem is but maybe this little example can help as a starting point. It shows how you can
Iterate though files in a directory (you need C++17 though)
Read some number from a file
Write to another file
Hopefully you can add the rest with no problem. :)
#include <filesystem>
#include <fstream>
#include <iostream>
#include <string>
namespace fs = std::filesystem;
int main(int argc, char **argv) {
std::string input_dir = argv[1];
std::string output_file = argv[2];
std::ofstream out(output_file);
// Iterate over files in directory
for(auto& file : fs::directory_iterator(input_dir)) {
std::ifstream in(file.path());
// In this example, read a integer number from the current file
if (int i; in >> i) {
std::cout << "Read " << i << " from " << file << std::endl;
// ... and write it to the output file.
out << i << std::endl;
}
}
}

Related

C++ vector change in text.txt file and add text

#include <iostream>
#include <string>
#include <stdio.h>
#include <cstring>
#include <fstream>
#include <vector>
#include <iterator>
using std::cout;
using std::cin;
using std::endl;
using std::string;
std::string FilesOpen(std::string command)
{
const int size_buffer = 2;
char buffer[size_buffer];
memset(buffer, 0, size_buffer * sizeof(char));
std::string result = "";
// Open pipe to file
FILE* pipe = popen(command.c_str(), "r");
if (!pipe)
{
return "popen failed!";
}
// read till end of process:
while (!feof(pipe))
{
// use buffer to read and add to result
if (fgets(buffer, 2, pipe) != NULL)
{
result += buffer;
memset(buffer, 0, size_buffer * sizeof(char));
}
}
pclose(pipe);
return result;
}
int main(int* agrc, char* agrv[])
{
std::vector<std::string> pole;
std::string text;
// get files names and use to ifstream files
FilesOpen("ls /root/workspace/src/server > /root/workspace/filestext.txt");
// get files info size and names
FilesOpen("ls -l /root/workspace/src/server > /root/workspace/filelist.txt");
// get files name and add vector
std::ifstream files;
files.open("/root/workspace/filestext.txt", std::ios_base::in);
if (!files)
{
std::cout << "Error not open files" << std::endl;
}
while (files >> text)
{
pole.push_back(text);
}
files.close();
for (std::vector<std::string>::iterator it = pole.begin(); it != pole.end(); ++it)
{
std::cout << *it << std::endl;
}
// replace text in shell
std::string filereplace = "/root/workspace/testovaci.sh";
std::ofstream r_file(filereplace.c_str());
char patch[] = "patch=";
if (r_file.is_open())
{
for (int i = 0; patch[i] != '\0'; i++)
r_file.put(patch[i]);
r_file.put('D');
}
r_file.close()
}
I need to get the contents of the file name from the filetext.txt file and ignore the folders and list them in the testovaci.sh script, which looks like this:
neco1
neco2
neco3
patch =
neco4
neco5
I need to put in the testovaci.sh file has been added to patch = "file". "file". "file"
and the folders were ignored, leaving only binary files.
Please help me, as I tried everything but nothing works.

Recieve 3 files by terminal and concatenate the content of file2 and file3 to file1 using fstream

I'm begginer in C++, so may be parts of my code doesn't have sense, sorry.
What I have to do is (C++, Linux, by fstream):
· Receive 3 or more files passed by terminal by:
./executable file1.txt file2.txt file3.txt
· programm a function that read the files file2.txt and file3.txt and copy it to file1.txt (concatenate, don't overwrite)
I don't know how to do it, I don't know anything about fstream, I'm just learning now by myself, so I really need help. Maybe there are similar questions solved in SO, but I don't know how to solve my problem by them.
I attach the code I have. I don't know how to code the function, so it's empty.
Thank you so much.
I try doing:
void concat(char *argv[], int numberoffilesreceived){
char c;
towritethefiles.open(argv[0], ios::app);
for(int i=1; i<numberoffilesreceived; i++){
toreadthefiles.open(argv[i], ios::in);
while(!toreadthefiles.eof()){
toreadthefiles >> c;
towritethefiles<< c;
}
}
}
It compiles but doesn't work, the program freezes when you run it.
and I also try using std::copy by I don't understand how it works.
ifstream toreadthefiles;
ofstream towritethefiles;
void concat(char *argv[], int numberoffilesreceived);
int main(int argc, char *argv[]){
/* 1/2 The code from below to 2/2 it's only to prevent path errors when receiving the files (it works fine) */
const char directory[SIZE]="./";
int count_files=0;
char files[SIZE][SIZE];
for(int i=1; i<argc; i++){
strcpy(files[i], directory);
strcat(files[i], argv[i]);
count_files++;
}
/*2/2 to add ./ to the name files when passed by terminal: ./executable ./file1.txt ./file2.txt ./file3.txt */
/*check if received almost 3 files like required */
if(argc<3){
cout<< "Error, to few files entered" << endl;
getchar();
exit(1);
}
/*pass the files to the concat function*/
for(int i=1; i<argc; i++){
concat(&argv[i], count_files);
}
toreadthefiles.close();
towritethefiles.close();
return 0;
}
void concat(char *argv[], int count_files){
}
I think I see an issue with your concat() function. You are calling concat() for each of the files passed in. Then in the function, you are using count_files to run that loop again for the number of files passed in.
I would consider rewriting concat() function so that it looks like this:
void concat(std::ofstream& outputStream, char* fileToAppend)
{
std::ifstream in(fileToAppend);
if (!in) {
cout << "Error, cannot open file: " << fileToAppend;
return;
}
// Use std::getline to read each line in the input stream,
// then write it to the output stream!
string line;
while (std::getline(in, line)) {
outputStream << line;
}
}
The benefit being that you can reuse the function for appending a single input file to an existing output stream, and you wrap up the check to ensure the file exists (you may want something more sophisticated like returning true/false on the file being appended, or throwing an error, etc.).
In main(), you would replace the code after the check for at least three files with something like:
// Create an output stream with the first file
// ios::out- output flag
// ios::app- append flag
std::ofstream out(argv[1], ios::out | ios::app);
// Make sure the file exists!
if (!out) {
cout << "Error, cannot open file: " << argv[1];
exit(1);
}
// For all other arguments, concat with the first.
for (int i = 2; i < argc; i++) {
concat(out, argv[i]);
}
You can use std::copy with stream iterators, and I've revised my previous suspicion that it would be slow, so here's one way using doing just that with comments in the code.
#include <iostream>
#include <fstream>
#include <vector>
#include <ios>
#include <stdexcept>
void concat(const std::string& destination, const std::vector<std::string>& sources) {
// open the destination file and keep it open until all is done
std::ofstream dest_fs(destination, std::ios_base::binary);
if(!dest_fs)
throw std::runtime_error("Could not write to \"" + destination + "\".");
// loop over the source files
for(const auto& source_file : sources) {
// open the current source file
std::ifstream source_fs(source_file, std::ios_base::binary);
if(!source_fs)
throw std::runtime_error("Could not read from \"" + source_file + "\".");
// copy from source to destination
std::copy(std::istreambuf_iterator<char>(source_fs),
std::istreambuf_iterator<char>(),
std::ostreambuf_iterator<char>(dest_fs));
}
}
int cppmain(std::string program, std::vector<std::string> args) {
if(args.size() < 2) {
std::cout << "USAGE: " << program << " destination_file input_file(s)\n";
return 1;
}
// extract the first argument which is the destination file
std::string destination_file = std::move(args.front());
args.erase(args.begin()); // erase first argument from the vector
try {
// do the concatenation
concat(destination_file, args);
return 0;
} catch(const std::exception& ex) {
std::cerr << program << ": ERROR: " << ex.what() << "\n";
return 1;
}
}
int main(int argc, char* argv[]) {
return cppmain(argv[0], {argv + 1, argv + argc});
}

issue while creating binary files

I've written this code, which it get the repository and look for the files within. it aims to create binary files for each file found so as to write some data inside it later. However, the code is not running as expected. and the binary file are not created this the issue.
the directory has two images, and the output I get is as follows :
Creating bin files
C:\repo\1.bin
Error: failed to create file
Press <RETURN> to close this window...
I really do not know where I miss it. Any advice I'd be glad.
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}
First I have to say, if you directory you are looking for doesn't exists or is empty, the program gets locked, it would be nice to have that fixed if making a bigger program.
Then, for your case, I don't see whars the point of that stringstream, so I tried removing that, and changing it by a normal string, removing the last \n character you get from reading the filenames:
cout << fileName << '\n';
string ss = fileName.substr(0, fileName.size() - 1);
myOfstream.open(ss.c_str(), fstream::binary);
if (!myOfstream)
{
hope it helps
I found the issue bro, after debugging ;D
the problem is in the "newline", the string fileName has a "\n" at the end that's whats rise your error. Thus you have to erase it, I ve used this statement fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
and I included algorithm lib.
the working code is as follows :
#include <vector>
#include <string>
#include <iostream> // for standard I/O
#include <string> // for strings
#include <iomanip> // for controlling float print precision
#include <sstream> // string to number conversion
#include <fstream>
#include <algorithm>
using namespace std;
void getDir(string d, vector<string> & f)
{
FILE* pipe = NULL;
string pCmd = "dir /B /S " + string(d);
char buf[256];
if( NULL == (pipe = _popen(pCmd.c_str(),"rt")))
{
cout<<"Error"<<endl;
return;
}
while (!feof(pipe))
{
if(fgets(buf,256,pipe) != NULL)
{
f.push_back(string(buf));
}
}
_pclose(pipe);
}
void replaceExt(string& s, const string& newExt) {
string::size_type i = s.rfind('.', s.length());
if (i != string::npos) {
s.replace(i+1, newExt.length(), newExt);
}
}
using namespace std;
int main(int argc, char* argv[])
{
vector<string> files;
string path = "C:\\repo";
getDir(path, files);
vector<string>::const_iterator it = files.begin();
cout<<"Creating bin files "<<endl;
ofstream myOfstream;
while( it != files.end())
{
string fileName = (string) *it;
replaceExt(fileName, "bin");
cout << fileName << '\n';
fileName.erase(std::remove(fileName.begin(), fileName.end(), '\n'), fileName.end());
std::stringstream ss;
ss << fileName << "" ;
myOfstream.open(ss.str(), fstream::binary);
if ( !myOfstream )
{
std::cerr << "Error: failed to create file " << '\n';
break;
}
myOfstream.close();
it++;
}
return 0;
}

Passing a file into a function

I'm trying to create a program that passes a file to a function. The function is supposed to detect how many lines are in my file. I don't think I'm passing the file correctly into my function, I've tried several different ways. Any help will be greatly appreciated.
#include <iostream>
#include <fstream>
#define die(errmsg) {cerr << errmsg << endl; exit(1);}
using namespace std;
int num_of_lines(ifstream file)
{
int cnt3;
string str;
while(getline(file, str))cnt3++;
return(cnt3);
}
int main(int argc, char **argv)
{
int num_of_lines(ifstream file);
string file;
file = argv[1];
if(argc == 1)die("usage: mywc your_file"); //for some reason not working
ifstream ifs;
ifs.open(file);
if(ifs.is_open())
{
int a;
cout << "File was opened\n";
a = num_of_lines(file);
cout <<"Lines: " << a << endl;
}
else
{
cerr <<"Could not open: " << file << endl;
exit(1);
}
ifs.close();
return(0);
}
Two problems with the function. First, you should pass the stream by reference. Second, you just forgot to initialise your counter.
int num_of_lines( ifstream &file )
{
int cnt3 = 0;
string str;
while( getline(file, str) ) cnt3++;
return cnt3;
}
The other thing is you're passing file to it (which is a string) instead of ifs. Change the call to:
a = num_of_lines( ifs );

How do I print the content of a file?

How can I print the contents of a file, the name of which is specified via my program's command line?
I do not know how to give the name of file by command line and how to work with it.
For ex this is does not work:
int main(int argc, char *argv[])
{
FILE *f;
char s[20];
cin >> s;
f=fopen_s(s,"rt");
std::cout << f;
_getch();
return 0;
}
error C2660
#include <iostream>
#include <fstream>
int main(int argc , char *argv[])
{
if(argc < 2)
{
std::cout << " Wrong usage " << std::endl;
exit(0);
}
std::string file_name = argv[1];
std::ifstream fs;
fs.open(file_name.c_str());
std::cout << file_name << std::endl;
std::string line ;
while(fs >> line)
{
std::cout << line << std::endl;
}
return 0;
}
You cannot use << operator with char[]
Solution : You can use std::string
std::string s;
Use the string's c_str() value as name in fopen_s(name, "rt")
Solution : You need to put the file in the same directory as the executable
f = fopen_s(s.c_str(), "rt");
You cannot cout << FILE *f
Solution : read file content line by line as you print each line
char* line; //used to receive data for each line
int length; //used to represent how many characters have received
while ((getline(&line, &length, f) != -1) {
print("%s", line);
}