C++ how to make a root of .cfg file - c++

I have this .cfg file and my problem is that I am trying to read and extract info using the libconfig library in the .cfg file but I can't create a root up to the AboCombi element. I would like to know how to create a root of more than 2 elements of a hierarchy.
myConfig.cfg
clients =
{
name = "Robert";
client_infos = (
{
town = "Koeln";
Start_abo = "09.12.2020";
AboCombi = (
{
Courses = "All";
Materials = "ADTF_For_Free";
Matric = "A0003";
},
);
},
};
int main(int argc, char** argv) {
(void)argc;
(void)argv;
Config cfg;
// Read the file. If there is an error, report it and exit.
try
{
cfg.readFile("myConfig.cfg");
}
catch (const FileIOException &fioex)
{
cerr << "I/O error while reading file." << endl;
return(EXIT_FAILURE);
}
catch (const ParseException& pex)
{
cerr << "Parse error at " << pex.getFile() << ":" << pex.getLine()
<< " - " << pex.getError() << endl;
return(EXIT_FAILURE);
}
const Setting& root = cfg.getRoot();
// Output a list of the main config file.
try
{
const Setting &croot = root["clients"]["client_infos"]; // but I would like to go further down the hierarchy to AboCombi and its elements
int count = croot.getLength();
cout << count << endl;
}
catch (const SettingNotFoundException &nfex)
{
// Ignore.
}
return(EXIT_SUCCESS);
}

Related

C++ something gone wrong when reading the file

I'm trying to write and read serialized data to file, but it always breaks when reading specific "PNG" struct, with stored "bed_feet_top.png" from minecraft 1.8.9 textures folder in it, and I can't find a way to get the error. Already tried errno and try and catch, but it always says sucess. It seems that it breaks after and not when reading the buggy "PNG" struct, because the read data is uncorrupted and I can recreate the stored image. I'm using "stb_image" library to read the image data and "zpp_bits" library for serializing the data.
the code i would use:
PNG srcImage; //The "PNG" struct it will break at
unsigned char* buffer = stbi_load("bed_feet_top.png", &image.imageWidth, &image.imageHeight, &image.colorChannels, STBI_rgb_alpha);
if (!buffer)
{
std::cout << "Failed to read image: " + path << std::endl;
return 1;
}
image.pixels = (char*)buffer;
DataBuffer srcBuffer;
srcBuffer.serialize("somePath", "someName", srcImage);
DataManager::writeToFile("someFile.dat", srcBuffer);
DataBuffer dstBuffer;
DataManager::readFromFile("someFile.dat", &dstbuffer);
PNG dstImage = dstBuffer.deserialize<PNG>("somePath", "someName"); //The buggy "PNG" struct data is uncorrupted
the "PNG" struct:
struct PNG
{
int imageWidth, imageHeight, colorChannels;
std::string pixels;
};
the struct I'm storing all serialized data in:
struct DataBuffer
{
std::map<std::string, std::vector<std::byte>> data; //All the serialized data is stored in this map
template<typename T>
void serialize(std::string path, std::string name, T obj)
{
path.append("/");
path.append(name);
serialize(path, obj);
}
template<typename T>
void serialize(std::string fullPath, T obj)
{
if (data.contains(fullPath))
{
std::cout << "Data buffer already contains value with te same path!" << std::endl;
return;
}
try
{
zpp::bits::out out(data[fullPath]);
out(obj).or_throw();
}
catch (const std::exception& error)
{
std::cerr << "Serialization failed with error: " << error.what() << std::endl;
}
catch (...) {
std::cerr << "Serialization failed with unknown error!" << std::endl;
}
}
template<typename T>
T deserialize(std::string path, std::string name)
{
path.append("/");
path.append(name);
return deserialize<T>(path);
}
template<typename T>
T deserialize(std::string fullPath)
{
T obj;
if (!data.contains(fullPath))
{
std::cout << "Data buffer doesn't contain value with the given path!" << std::endl;
return obj;
}
try
{
zpp::bits::in in(data[fullPath]);
in(obj).or_throw();
}
catch (const std::exception& error)
{
std::cerr << "Deserialization failed with error: " << error.what() << std::endl;
}
catch (...) {
std::cerr << "Deserialization failed with unknown error!" << std::endl;
}
return obj;
}
};
The write to file function:
void DataManager::writeToFile(std::string fileName, DataBuffer dataBuffer)
{
std::ofstream ofs(fileName, std::ios::out | std::ios::binary);
if (!ofs.is_open())
{
std::cerr << "Failed to open output file stream!" << std::endl;
return;
}
size_t dataCount = dataBuffer.data.size();
ofs.write((char*)&dataCount, 8);
for (auto const& [key, val] : dataBuffer.data)
{
size_t keySize = key.size();
ofs.write((char*)&keySize, sizeof(keySize));
ofs.write(&key[0], keySize);
size_t entryCount = val.size();
ofs.write((char*)&entryCount, 8);
ofs.write((char*)val.data(), entryCount);
if (!ofs.good()) //ofs.good() never returned false to me
{
std::cerr << "Something went wrong when writing " << key << " to the file!" << std::endl;
break;
}
}
ofs.close();
}
the read from file function:
void DataManager::readFromFile(std::string fileName, DataBuffer* dataBuffer)
{
std::ifstream ifs(fileName, std::ios::in, std::ios::binary);
if (!ifs)
{
std::cerr << "File doesnt exist!" << std::endl;
return;
}
if (!ifs.is_open())
{
std::cerr << "Failed to open input file stream!" << std::endl;
return;
}
size_t dataCount;
ifs.read((char*)&dataCount, 8);
for (size_t i = 0; i < dataCount; i++)
{
size_t keySize;
ifs.read((char*)&keySize, sizeof(keySize));
std::string key;
key.resize(keySize);
ifs.read(&key[0], keySize);
size_t entryCount;
ifs.read((char*)&entryCount, 8);
dataBuffer->data[key].resize(entryCount);
ifs.read((char*)dataBuffer->data[key].data(), entryCount);
if (!ifs.good()) //ifs.good() returns false after it reads the buggy "PNG" struct data
{
std::cerr << "Something went wrong when reading " << key << " from the file!" << std::endl;
break;
}
}
ifs.close();
}
EDIT
I added minimal reproducible example as "Igor Tandetnik" requested.
the minimal reproducible example:
#define STB_IMAGE_IMPLEMENTATION
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include <string>
#include <iostream>
#include <vector>
#include <fstream>
#include <stb_image.h>
#include "stb_image_write.h"
#include <zpp_bits.h>
struct PNG
{
int imageWidth, imageHeight, colorChannels;
std::string pixels;
};
int main()
{
std::string fileName = "someFile.dat"; //The file we will store the image data in
std::string srcImageName = "bed_feet_top.png"; //Texture from Minecraft 1.8.9 textures folder
std::string dstImageName = "someImage.png"; //The name of image we will create from the read data
//Reading the image data
PNG srcImage;
unsigned char* buffer = stbi_load(srcImageName.c_str(), &srcImage.imageWidth, &srcImage.imageHeight, &srcImage.colorChannels, STBI_rgb_alpha);
if (!buffer)
{
std::cout << "Failed to read image " + srcImageName << std::endl;
return 1;
}
int dataSize = srcImage.imageWidth * srcImage.imageHeight * srcImage.colorChannels;
srcImage.pixels.assign((char*)buffer, dataSize);
//Serializing the image data
std::vector<std::byte> srcData;
try
{
zpp::bits::out out(srcData);
out(srcImage).or_throw();
}
catch (const std::exception& error)
{
std::cerr << "Serialization failed with error: " << error.what() << std::endl;
}
catch (...) {
std::cerr << "Serialization failed with unknown error!" << std::endl;
}
//Writing the image data to file
std::ofstream ofs(fileName, std::ios::out | std::ios::binary);
if (!ofs.is_open())
{
std::cout << "Failed to open output file stream!" << std::endl;
return 1;
}
size_t srcEntryCount = srcData.size();
ofs.write((char*)&srcEntryCount, 8);
ofs.write((char*)srcData.data(), srcEntryCount);
if (!ofs.good())
{
std::cerr << "Something went wrong when writing" << srcImageName << " to the file!" << std::endl;
ofs.close();
return 1;
}
ofs.close();
//Reading the image data from file
std::ifstream ifs(fileName, std::ios::in, std::ios::binary);
if (!ifs)
{
std::cout << "File doesnt exist!" << std::endl;
return 1;
}
if (!ifs.is_open())
{
std::cout << "Failed to open input file stream!" << std::endl;
return 1;
}
std::vector<std::byte> dstData;
size_t dstEntryCount;
ifs.read((char*)&dstEntryCount, 8);
dstData.resize(dstEntryCount);
ifs.read((char*)dstData.data(), dstEntryCount);
if (!ifs.good())
{
std::cerr << "Something went wrong when reading " << srcImageName << " from the file!" << std::endl;
ifs.close();
return 1; //If you comment this line you will see it will recreate the image from the read data just fine
}
ifs.close();
//Deserializing the read image data
PNG dstImage;
try
{
zpp::bits::in in(dstData);
in(dstImage).or_throw();
} catch (const std::exception& error)
{
std::cerr << "Deserialization failed with error: " << error.what() << std::endl;
} catch (...) {
std::cerr << "Deserialization failed with unknown error!" << std::endl;
}
//Recreating the image from the read image data
stbi_write_png(dstImageName.c_str(), dstImage.imageWidth, dstImage.imageHeight, dstImage.colorChannels, dstImage.pixels.c_str(), dstImage.imageWidth * sizeof(int));
}
I'm caling the objects src and dst, because I don't know how to call them shortly before and after serialization. :D

Printing All The Files Path's In C:\ With C++

I tried to print all the files path's in C:.
But I saw that I am getting permission errors.
void getAllFilesInDirectory(wstring directoryPath, vector<wstring> &files) {
for (filesystem::directory_entry directory : filesystem::directory_iterator(directoryPath)) {
if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_SYSTEM)
continue;
//Checking if directory.path is a file or a directory
if (GetFileAttributesW(directory.path().wstring().c_str()) == FILE_ATTRIBUTE_NORMAL) {
files.push_back(directory.path().wstring());
wcout << "The path is " << directory.path().wstring() << endl;
continue;
}
try {
for (filesystem::directory_entry file : filesystem::recursive_directory_iterator(directory)) {
if (GetFileAttributesW(file.path().wstring().c_str()) == FILE_ATTRIBUTE_DIRECTORY) {
continue;
}
wcout << "The path of the file is " << file.path().wstring() << endl;
files.push_back(file.path().wstring());
}
} catch (exception &e) {
wcout << "There is exception " << e.what() << " and the directory path is: " << directory.path().wstring()
<< endl;
}
}
}
My code is working when I give the function a regular directory (not one with privileges).
But when I give him "C:\" he quitting after printing a little path's.
It will be great if someone post his method for printing all the path's in the C drive.
Thanks!
You said in comments that:
I want that my code will ignore files that he doesn't have access to them
std::filesystem::directory_iterator and std::filesystem::recursive_directory_iterator both have a constructor that accepts a std::filesystem::directory_options enum as input, which has a skip_permission_denied item available for that purpose, for example:
void getAllFilesInDirectory(const wstring &directoryPath, vector<wstring> &files) {
for (filesystem::directory_entry directory : filesystem::directory_iterator(directoryPath, filesystem::directory_options::skip_permission_denied)) {
...
for (filesystem::directory_entry file : filesystem::recursive_directory_iterator(directory, filesystem::directory_options::skip_permission_denied)) {
...
}
}
}
On a side note, you may want to consider adding a namespace alias to shorten those qualified names, eg:
namespace fs = std::filesystem;
for (fs::directory_entry directory : fs::directory_iterator(directoryPath, fs::directory_options::skip_permission_denied)) {
...
for (fs::directory_entry file : fs::recursive_directory_iterator(directory, fs::directory_options::skip_permission_denied)) {
...
}
}
Also, your use of GetFileAttributesW() is wrong. You are not checking for errors, and you are not taking into account that folders and files can (and usually do) have multiple attributes assigned. Use the & (AND) operator when testing for specific attributes. And testing for the FILE_ATTRIBUTE_NORMAL attribute is not the correct way to differentiate a file from a folder. Test for the presence/lack of the FILE_ATTRIBUTE_DIRECTORY attribute instead.
Try this:
namespace fs = std::filesystem;
void getAllFilesInDirectory(const wstring &directoryPath, vector<wstring> &files) {
for (fs::directory_entry directory : fs::directory_iterator(directoryPath, fs::directory_options::skip_permission_denied)) {
DWORD attrs = GetFileAttributesW(directory.path().wstring().c_str());
if (attrs == INVALID_FILE_ATTRIBUTES) {
DWORD err = GetLastError();
wcerr << "Error " << err << " getting attributes for path " << directory.path().wstring() << endl;
continue;
}
if (attrs & FILE_ATTRIBUTE_SYSTEM)
continue;
//Checking if directory.path is a file or a directory
if (attrs & ~FILE_ATTRIBUTE_DIRECTORY) {
files.push_back(directory.path().wstring());
wcout << "The path is " << directory.path().wstring() << endl;
continue;
}
try {
for (fs::directory_entry file : fs::recursive_directory_iterator(directory, fs::directory_options::skip_permission_denied)) {
attrs = GetFileAttributesW(file.path().wstring().c_str());
if (attrs == INVALID_FILE_ATTRIBUTES) {
DWORD err = GetLastError();
wcerr << "Error " << err << " getting attributes for path " << file.path().wstring() << endl;
continue;
}
if (attrs & FILE_ATTRIBUTE_DIRECTORY)
continue;
wcout << "The path of the file is " << file.path().wstring() << endl;
files.push_back(file.path().wstring());
}
} catch (const exception &e) {
wcout << "There is exception " << e.what() << " and the directory path is: " << directory.path().wstring() << endl;
}
}
}

RtMidi - MidiInDummy: This class provides no functionality

I want to use Rtmidi to get input from launchpad.
However, despite connecting the launchpad, 0 pods are available.
"MidiInDummy: This class providers no functionality."
There's also this phrase, so something seems to be wrong.
Source:
//Source : http://www.music.mcgill.ca/~gary/rtmidi/index.html#probing
#define __WINDOWS_MM__
#include <iostream>
#include <cstdlib>
#include "RtMidi.h"
int main()
{
RtMidiIn* midiin = 0;
RtMidiOut* midiout = 0;
// RtMidiIn constructor
try {
midiin = new RtMidiIn();
}
catch (RtMidiError& error) {
error.printMessage();
exit(EXIT_FAILURE);
}
// Check inputs.
unsigned int nPorts = midiin->getPortCount();
std::cout << "\nThere are " << nPorts << " MIDI input sources available.\n";
std::string portName;
for (unsigned int i = 0; i < nPorts; i++) {
try {
portName = midiin->getPortName(i);
}
catch (RtMidiError& error) {
error.printMessage();
goto cleanup;
}
std::cout << " Input Port #" << i + 1 << ": " << portName << '\n';
}
// RtMidiOut constructor
try {
midiout = new RtMidiOut();
}
catch (RtMidiError& error) {
error.printMessage();
exit(EXIT_FAILURE);
}
// Check outputs.
nPorts = midiout->getPortCount();
std::cout << "\nThere are " << nPorts << " MIDI output ports available.\n";
for (unsigned int i = 0; i < nPorts; i++) {
try {
portName = midiout->getPortName(i);
}
catch (RtMidiError& error) {
error.printMessage();
goto cleanup;
}
std::cout << " Output Port #" << i + 1 << ": " << portName << '\n';
}
std::cout << '\n';
// Clean up
cleanup:
delete midiin;
delete midiout;
return 0;
}
Output:
MidiInDummy: This class provides no functionality.
There are 0 MIDI input sources available.
MidiOutDummy: This class provides no functionality.
There are 0 MIDI output ports available.
How can I solve this problem?
Oh, I solved it.
https://www.music.mcgill.ca/~gary/rtmidi/#compiling
https://github.com/thestk/rtmidi/issues/85
keyword : __WINDOWS_MM__, winmm.lib

Threading Segfault when reading members

I am facing some problems when I am trying to read a class variable in my worker thread (That variable was not created withing that thread). Here is my class header with static worker thread function:
class C1WTempReader
{
public:
C1WTempReader(std::string device);
virtual ~C1WTempReader();
void startTemRead();
double& getTemperature();
private:
std::string device;
std::string path;
double temperature;
pthread_t w1Thread;
std::mutex w1Mutex;
bool fileExists(const std::string& filename);
static void * threadHelper(void * arg)
{
return ((C1WTempReader*) arg)->tempReadRun(NULL);
}
void* tempReadRun(void* arg);
};
Here are the crucial methods I am using:
C1WTempReader::C1WTempReader(std::string device)
{
path = W1_PATH + device + W1_SLAVE;
if (!fileExists(path))
{
std::cout << "File " << path << " doesnt exist!" << std::endl;
path.clear();
return;
}
std::cout << "1 wire termometer device path: " << path << std::endl;
}
void C1WTempReader::startTempRead()
{
if(pthread_create(&w1Thread, NULL, threadHelper, NULL) == -1)
{
std::cout << "1W thread creation failed" << std::endl;
}
}
void* C1WTempReader::tempReadRun(void* arg)
{
w1Mutex.lock(); // SEGFAULT
std::string line;
std::ifstream myfile (path.c_str());
if (myfile.is_open())
{
while ( getline (myfile,line) )
{
size_t found = line.find("t=");
if (found != std::string::npos)
{
found += 2;
std::string temp = line.substr(found, 10);
temperature = atof(temp.c_str());
temperature /= 1000;
std::cout << "Temperature: " << temperature << " *C" << std::endl;
}
line.clear();
}
myfile.close();
}
else
{
std::cout << "Unable to open file" << std::endl;
temperature = 1000; // bad value
}
w1Mutex.unlock();
return NULL;
}
double& C1WTempReader::getTemperature()
{
if (pthread_join(w1Thread, NULL))
{
std::cout << "1W Unable to join thread!" << std::endl;
}
return temperature;
}
Segmentation fault happens in the tempReadRun method, as soon as I try to lock the mutex. I didnt have mutexes before and I noticed that it happens whenever I try to read any of the class variables that are created ruring the class creation and are not created within the new thread. What Am I doing wrong?
And heres how I am trying to run this:
string device = "28-00000713a636";
C1WTempReader tempReader(device);
tempReader.startTempRead();
.
.
.
double temp = tempReader.getTemperature();
I have found what the problem was. In the function C1WTempReader::startTempRead():
if(pthread_create(&w1Thread, NULL, threadHelper, NULL) == -1)
{
std::cout << "1W thread creation failed" << std::endl;
}
The last argument of pthread_create had to be changed to this.
You are not passing argument to pthread_create:
if(pthread_create(&w1Thread, NULL, threadHelper, this) == -1)

How enable dragging a file on the *.exe and get it as parameter?

What do I have to do to make my program use a file that has been dragged and dropped onto its icon as a parameter?
My current main method looks like this:
int main(int argc, char* argv[])
{
if (argc != 2) {
cout << "ERROR: Wrong amount of arguments!" << endl;
cout << "\n" << "Programm closed...\n\n" << endl;
exit(1);
return 0;
}
Converter a(argv[1]);
// ...
cout << "\n" << "Programm finished...\n\n" << endl;
// cin.ignore();
return 0;
}
What I'd really like to be able to do is select 10 (or so) files, drop them onto the EXE, and process them from within my application.
EDIT:
The incomming parameter is used as filename, constructed in the cunstructor.
Converter::Converter(char* file) {
// string filename is a global variable
filename = file;
myfile.open(filename.c_str(), ios_base::in);
}
The method where the textfile gets read:
string Converter::readTextFile() {
char c;
string txt = "";
if (myfile.is_open()) {
while (!myfile.eof()) {
myfile.get(c);
txt += c;
}
} else {
error("ERROR: can't open file:", filename.c_str());
}
return txt;
}
EDIT2:
deleted
Update:
I got again to this point.
Actual Main method:
// File path as argument
int main(int argc, char* argv[]) {
if (argc < 2) {
cout
<< "ERROR: Wrong amount of arguments! Give at least one argument ...\n"
<< endl;
cout << "\n" << "Programm closed...\n\n" << endl;
cin.ignore();
exit(1);
return 0;
}
vector<string> files;
for (int g = 1; g < argc; g++) {
string s = argv[g];
string filename = "";
int pos = s.find_last_of("\\", s.size());
if (pos != -1) {
filename = s.substr(pos + 1);
cout << "argv[1] " << argv[1] << endl;
cout << "\n filename: " << filename << "\n pos: " << pos << endl;
files.push_back(filename);
}
files.push_back(s);
}
for (unsigned int k = 0; k < files.size(); k++)
{
cout << "files.at( " << k << " ): " << files.at(k).c_str() << endl;
Converter a(files.at(k).c_str());
a.getATCommandsFromCSV();
}
cout << "\n" << "Programm finished...\n\n" << endl;
cin.ignore();
return 0;
}
Actually the console window apears for maybe 0.5 sec and closes again.
It doen't stop on any of my cin.ignore(); Maybe it doesn't get there?
Can anyone help?
Your program does not need to do anything special apart from handling command-line arguments. When you drag-drop a file onto an application in Explorer it does nothing more than to pass the file name as argument to the program. Likewise for multiple files.
If all you expect is a list of file names, then just iterate over all arguments, do whatever you want with them and be done. This will work for zero to almost arbitrarily many arguments.
Maybe you could write a test program like this:
int main(int argc, char* argv[])
{
// argv[0] is not interesting, since it's just your program's path.
for (int i = 1; i < argc, ++i)
cout << "argv[" << i << "] is " << argv[i] << endl;
return 0;
}
And see what happens after you throw different files at it.
EDIT: Just look at Joey's answer.
Answer to the main question
TO SEE THE ANSWER TO YOUR LAST PROBLEM SEE BOTTOM OF THIS ANSWER
All drag&dropped files are get-able as argv[orderOfTheFile] (orderOfTheFile is from 1-n),
however how does windows create that order, now that is a real mystery...
Anyway let's say I would create 26 plain text files ( *.txt ), from a.txt to z.txt on my Desktop,
now if I would drag&dropped them on my ArgsPrinter_c++.exe located directly on C:\ drive,
an output would be similar to this:
argc = 27
argv[0] = C:\ArgsPrinter_c++.exe
argv[1] = C:\Users\MyUserName\Desktop\c.txt
argv[2] = C:\Users\MyUserName\Desktop\d.txt
argv[3] = C:\Users\MyUserName\Desktop\e.txt
argv[4] = C:\Users\MyUserName\Desktop\f.txt
argv[5] = C:\Users\MyUserName\Desktop\g.txt
argv[6] = C:\Users\MyUserName\Desktop\h.txt
argv[7] = C:\Users\MyUserName\Desktop\i.txt
argv[8] = C:\Users\MyUserName\Desktop\j.txt
argv[9] = C:\Users\MyUserName\Desktop\k.txt
argv[10] = C:\Users\MyUserName\Desktop\l.txt
argv[11] = C:\Users\MyUserName\Desktop\m.txt
argv[12] = C:\Users\MyUserName\Desktop\n.txt
argv[13] = C:\Users\MyUserName\Desktop\o.txt
argv[14] = C:\Users\MyUserName\Desktop\p.txt
argv[15] = C:\Users\MyUserName\Desktop\q.txt
argv[16] = C:\Users\MyUserName\Desktop\r.txt
argv[17] = C:\Users\MyUserName\Desktop\s.txt
argv[18] = C:\Users\MyUserName\Desktop\t.txt
argv[19] = C:\Users\MyUserName\Desktop\u.txt
argv[20] = C:\Users\MyUserName\Desktop\v.txt
argv[21] = C:\Users\MyUserName\Desktop\w.txt
argv[22] = C:\Users\MyUserName\Desktop\x.txt
argv[23] = C:\Users\MyUserName\Desktop\y.txt
argv[24] = C:\Users\MyUserName\Desktop\z.txt
argv[25] = C:\Users\MyUserName\Desktop\a.txt
argv[26] = C:\Users\MyUserName\Desktop\b.txt
My ArgsPrinter_c++.exe source code:
#include <iostream>
using namespace std;
int main(int argc, char* argv[]) {
cout << "argc = " << argc << endl;
for(int i = 0; i < argc; i++)
cout << "argv[" << i << "] = " << argv[i] << endl;
std::cin.ignore();
return 0;
}
Your last problem
I have created a simple program that creates only a sceleton of your class so it can be used, and the program's main itself ran JUST FINE => if your program exits too soon, the problem will be in your class...
Tested source code:
#include <iostream>
#include <vector>
using namespace std;
class Converter{
public:
Converter(const char* f){ cout << f << endl; }
void getATCommandsFromCSV(){ cout << "called getATCommandsFromCSV" << endl; }
};
int main(int argc, char* argv[]) {
vector<string> files;
for (int g = 1; g < argc; g++) {
string s = argv[g];
string filename = "";
int pos = s.find_last_of("\\", s.size());
if (pos != -1) {
filename = s.substr(pos + 1);
cout << "argv[1] " << argv[1] << endl;
cout << "\n filename: " << filename << "\n pos: " << pos << endl;
files.push_back(filename);
}
files.push_back(s);
}
for (unsigned int k = 0; k < files.size(); k++)
{
cout << "files.at( " << k << " ): " << files.at(k).c_str() << endl;
Converter a(files.at(k).c_str());
a.getATCommandsFromCSV();
}
cout << "\n" << "Programm finished...\n\n" << endl;
cin.ignore();
return 0;
}