Vigenère Cipher code - c++

How would I go about modifying this code to accept input from the user rather than using a predetermined string? Specifically, I need the program to require exactly two command line arguments. The first will either be the code "-e" or "-d" to indicate encoding or decoding of a message (this determines adding or subtracting you shift values) and the second parameter will be a single word that will be the keyword that you use for the encryption or decryption.
#include <iostream>
#include <cstring>
#include <algorithm>
// Vigenere Cipher Methods:
// Note: assumes that both strings as arguments have length > 0, and that
// the key only contains letters of the alphabet from [A-Z]
void vigenere_encrypt(std::string& s, std::string key)
{
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
std::transform(key.begin(), key.end(), key.begin(), ::toupper);
unsigned int j = 0;
for (int i = 0; i < s.length(); i++)
{
if (isalpha(s[i]))
{
s[i] += key[j] - 'A';
if (s[i] > 'Z') s[i] += -'Z' + 'A' - 1;
}
j = j + 1 == key.length() ? 0 : j + 1;
}
}
void vigenere_decrypt(std::string& s, std::string key)
{
std::transform(s.begin(), s.end(), s.begin(), ::toupper);
std::transform(key.begin(), key.end(), key.begin(), ::toupper);
unsigned int j = 0;
for (int i = 0; i < s.length(); i++)
{
if (isalpha(s[i]))
{
s[i] = s[i] >= key[j] ?
s[i] - key[j] + 'A' :
'A' + ('Z' - key[j] + s[i] - 'A') + 1;
}
j = j + 1 == key.length() ? 0 : j + 1;
}
}
int main(void)
{
std::string s("AceInfinity's Example");
std::string key("Passkey");
vigenere_encrypt(s, key);
std::cout << "Encrypted: " << s << std::endl;
vigenere_decrypt(s, key);
std::cout << "Decrypted: " << s << std::endl;
return 0;
}
Update
Thanks to your input and a few other sources I have re-developed my main code as is shown below. I am having trouble getting the program to decrypt and encrypt strings properly and I am not sure if the error is somewhere in the code itself, or operator error. Does anything look out of the ordinary here and how could I get this code functional to where it can encrypt or decrypt given user input?
#include <iostream>
#include <string>
int usage( const char* exe_name )
{
std::cerr << "Usage: " << exe_name << " -e <text to encrypt>\n"
<< " " << exe_name << " -d <text to decrypt>\n" ;
return 1 ;
}
int main( int argc, char* argv[] )
{
if (argc < 3 ) return usage( argv[0] ) ;
const std::string option = argv[1];
std::string text = argv[2];
// cat the remaining cmd line args
for( int i = 3 ; i < argc ; ++i ) { text += ' ' ; text += argv[i] ; }
const std::string key("Passkey");
if ( option== "-e" )
std::cout << "Encrypt: '" << text << "'\n" ;
else if ( option == "-d" )
std::cout << "Decrypt: '" << text << "'\n" ;
else
{
std::cout << "Unrecognised command line option '" << option << "'\n";
return usage( argv[0] ) ;
}
}

If you want command line arguments, you'll need to change the prototype of your main function a little bit and use the standard argv array:
int main(int argc, const char** argv)
{
std::string s("AceInfinity's Example");
if (argc != 3)
{
std::cout << "Usage: -e text\n" << " -d text\n";
return 0;
}
std::string arg1 = argv[1];
std::string arg2 = argv[2];
if (arg1 == "-e")
{
vigenere_encrypt(s, arg2);
std::cout << "Encrypted: " << s << std::endl;
}
else if (arg1 == "-d")
{
vigenere_decrypt(s, arg2);
std::cout << "Decrypted: " << s << std::endl;
}
else
std::cout << "Unrecognised command line option " << arg1 << "\n";
return 0;
}
Minimal effort made for a quick example, code probably works, e&oe, caveat emptor, etc.
Of course, you'd really be best off using a proper command line argument parser, like getopt, and you'll still need some way to supply the plaintext for encryption or ciphertext for decription, but that's left as an exercise for the reader. Reading from stdin by using std::cin is one way of doing so, for example.

Use cin to accept input from the user and input it into a string. Parse the string to obtain the -e/-d flags and the keyword. If the input is not what you want, prompt the user to try again.

Related

Command Line Arguments With "-" Prefix

I'm trying to write a program which I'll be able to start with custom arguments. Like in this example "program.exe -width 1920 -height 1080". I wrote a simple code, which should work.
#include <iostream>
int main(int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
if (argv[i] == "-width")
{
std::cout << "Width: " << argv[++i] << "\n";
}
else if (argv[i] == "-height")
{
std::cout << "Height: " << argv[++i] << "\n";
}
}
return 0;
}
And this program doesn't work. It's not displaying anything. I also tried checking this code line by line with debugger, but when argv[i] == "-width" it just skips it.
Is there a way to fix it or there are just some other methods of doing this?
You are comparing pointers, not strings. To compare strings via ==, you should use std::string.
Also you should check if the elements argv[++i] exists.
#include <iostream>
#include <string>
int main(int argc, char* argv[])
{
for (int i = 1; i < argc; i++)
{
if (argv[i] == std::string("-width") && i + 1 < argc)
{
std::cout << "Width: " << argv[++i] << "\n";
}
else if (argv[i] == std::string("-height") && i + 1 < argc)
{
std::cout << "Height: " << argv[++i] << "\n";
}
}
return 0;
}
You can also use the s suffix
cout << ("wilson" == "wilson"s) << endl;
output:
1

how can I find the sequence number (index) of word in such a paragraph c++?

I'm working on a project which needs to find the number of words and the indices of each word in the paragraph ...I have written the code which is counting the number of word in a string but I stuck with finding the indices of words,
such as : Hi John How are you I miss you ..
I need to print the indices like : 0 1 2 3 4 5 6 7
here is the code:
int _tmain(int argc, _TCHAR* argv[])
{
int count_words(std::string);
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
int number_of_words=1;
int counter []={0};
for(int i = 0; i < input_text.length();i++)
if(input_text[i] == ' ')
number_of_words++;
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl;
system ("PAUSE");
}
Hopefully this helps. Edited to include use of count_words function.
#include <iostream>
#include <sstream>
void count_words(std::string);
int main(){
std::string input_text, output_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
count_words(input_text);
system ("PAUSE");
return 0; //MUST RETURN AN INTEGER VALUE FROM 'INT MAIN'
}
void count_words(std::string inputString){
std::string output_text;
std::stringstream indexes;
int number_of_words=0; //If there are no words, it would be false, make it 0.
//int counter []={0}; //This serves no purpose.
if(!inputString.empty()){// test to make sure it isn't empty.
number_of_words++;
for(int i = 0; i < inputString.length();i++){ // For loops should have curly braces {} containing their statement.
if(inputString[i] == ' '){
number_of_words++;
}
if((isalpha(inputString[i]))&&inputString[i-1]==' '){ //test for following space separated word
indexes << i << " ";
}
}
}
output_text = indexes.str(); //convert stringstream to string
std::cout << "Number of words: " << number_of_words << std::endl;
//std:: cout << number_of_words << std::endl; //duplicate info
std::cout << "Indexes: " << output_text << std::endl;
}
I'm not sure if i understand the question. You only need print the "indices"?? like this? (Using your own code)
#include <iostream>
#include <vector>
#include <string>
void stringTokenizer(const std::string& str, const std::string& delimiter, std::vector<std::string>& tokens) {
size_t prev = 0, next = 0, len;
while ((next = str.find(delimiter, prev)) != std::string::npos) {
len = next - prev;
if (len > 0) {
tokens.push_back(str.substr(prev, len));
}
prev = next + delimiter.size();
}
if (prev < str.size()) {
tokens.push_back(str.substr(prev));
}
}
int main()
{
std::vector <std::string> split;
std::string input_text;
std::cout<< "Enter a text: ";
std::getline(std::cin,input_text);
stringTokenizer(input_text, " ", split);
int number_of_words = 0;
for (std::vector<std::string>::iterator it = split.begin(); it != split.end(); it++, number_of_words++) {
std::cout << *it << " " << number_of_words << std::endl;
}
}

Recursion of an index

Hello fellow programmers, I have a question about recursion that I do not understand, being new to C++ and all. So for this exercise I am completing, I need to: 1. Ask user for a string 2. Ask user for a string to search in the first string entered. 3. report and index of the string if it finds it. For instance the user enters the string "Search me", string to search for is "me", and the index would return "7". I am throwing my hands up at this point for some help on how to complete it, any help would be appreciated. Here is my code thus far. The stuff that is in the for loop isn't a complete thought, just FYI.
int index_of(string stringToSearchIn, string stringToSearchFor, int index)
{
if (stringToSearchIn.length() < stringToSearchFor.length())
{
cout << "Your string cannot be found." << endl;
system("PAUSE");
return OUTLIER;
}
else
{
bool found = true;
for (int i = ZERO; i < stringToSearchFor.length; i++)
{
found = found && stringToSearchIn(i) == stringToSearchFor(i);
}
return index;
}
return index_of(stringToSearchIn.substr(INCREASE), stringToSearchFor, index++);
}
int main()
{
//Initializing values
string userString;
string userSearch;
int userIndex = 0;
//Asking for user input for string
cout << "This program will find the occurence of one string inside of another." << endl;
cout << "Enter the string to be searched: " << userString;
//Getting the string
getline(cin, userString);
//Asking for user input for search input
cout << "Now enter the string you want to search for: " << userSearch;
//Getting the string
getline(cin, userSearch);
//Displaying results
cout << "The index of the substring is = " << index_of(userString, userSearch, userIndex);
//Keeping console window open until key press
system("PAUSE");
return ZERO;
}
Catch.:)
#include <iostream>
size_t index_of( const char *s, const char *t )
{
const char *p = s;
const char *q = t;
while ( *q && *p == *q ) ++p, ++q;
if ( *q == '\0' )
{
return 0;
}
else if ( *p == '\0' )
{
return -1;
}
else
{
size_t n = 1 + index_of( s + 1, t );
return n == 0 ? -1 : n;
}
}
int main()
{
const char *s = "Search me";
const char *t = "me";
size_t n = index_of( s, t );
if ( n != -1 )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}
The output is
string me is found at position 7
For other strings I did not test the function.:)
For objects of type std::string you can call it like
size_t n = index_of( s.c_str(), t.c_str() );
Otherwise if you want to write a similar recursive function for objects of type std::string then you need either to add a static local variable that to keep the current position inside the source string or add one more parameter for index or use member function substr.
Also my advice is do not use manifest constant ZERO for zero. In my opinion it is a bad style of programming. It only confuses readers because ZERO can be anything including some user-defined class.
For example (without testing)
#include <iostream>
#include <string>
std::string::size_type index_of( const std::string &s, const std::string &t )
{
static std::string::size_type pos;
if ( s.size() < t.size() ) return std::string::npos;
if ( s.compare( pos, t.size(), t ) == 0 ) return 0;
++pos;
std::string::size_type n = index_of( s, t );
--pos;
return n == std::string::npos ? std::string::npos : n + 1;
}
int main()
{
std::string s = "Search me";
std::string t = "me";
std::string::size_type n = index_of( s, t );
if ( n != std::string::npos )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}
As for your function realization then it can look for example the following way
#include <iostream>
#include <string>
std::string::size_type index_of( const std::string &stringToSearchIn,
const std::string &stringToSearchFor,
std::string::size_type index )
{
if ( stringToSearchIn.length() < stringToSearchFor.length() + index )
{
return std::string::npos;
}
else if ( stringToSearchIn.compare( index,
stringToSearchFor.length(),
stringToSearchFor ) == 0 )
{
return index;
}
else
{
std::string::size_type n =
index_of( stringToSearchIn, stringToSearchFor, ++index );
return n == std::string::npos ? std::string::npos : n;
}
}
int main()
{
std::string s = "Search me";
std::string t = "me";
std::string::size_type n = index_of( s, t, 0 );
if ( n != std::string::npos )
{
std::cout << "string " << t << " is found at position " << n << std::endl;
}
else
{
std::cout << "string " << t << " is not found" << std::endl;
}
return 0;
}

How can I separate numbers and letters in a C++ String?

I'm having several input strings containing numbers and letters. Sometimes the space is missing. I would like to add an additional Space each time the string changes from numbers to letters or from letters to numbers.
Example inputs:
"30EinsteinStreet"
"548 Roe Drive5500 TestCity"
"44B SaarlouisDrive1234Testtown"
they should become:
"30 EinsteinStreet"
"548 Roe Drive 5500 TestCity"
"44 B SaarlouisDrive 1234 Testtown"
My existing function is not working and I think far to complex. Can anyone provide an easy solution? Preferably using modern C++11 classes but no Boost. Also I'm using GCC so all the regex stuff doesn't work for me.
Thanks
Here is my existing method:
inline string separateAlphanumChunks(const std::string& s)
{
string ret = "";
const int sl = s.length();
//int inserts = 0;
if (sl<=4)
return s;
for (int i=0 ; i< sl ; i++)
{
// cerr << "separateAlphanumChunks: '" << ret << "'" <<endl;
// check if index would go out of range
if (i+4 > sl)
{
ret += s.substr (i,sl-i);
//TODO add the remain to ret
break;
}
// seperate chars
const char c0 = s[i+0];
const char c1 = s[i+1];
// check if 0 and 1 are the same class
const bool c0c = isCharAnInt (c0);
const bool c1c = isCharAnInt (c1);
bool class0 = false;
if (c0c == c1c)
{
class0 = c0c;
}
else
{
ret += c0;
// cerr << "cont1: '" << c0 << "'" <<endl;
continue;
}
// seperate chars
const char c2 = s[i+2];
const char c3 = s[i+3];
// check if 2 and 3 are the same class
const bool c2c = isCharAnInt (c2);
const bool c3c = isCharAnInt (c3);
bool class2 = false;
if (c2c == c3c)
{
class2 = c2c;
}
else
{
ret += c0;
// cerr << "cont2: '" << c0 << "'" <<endl;
continue;
}
// check if the 2 classes are different
if (class0 != class2)
{
// split!
ret += c0+(c1+string(" ")+c2)+c3;
//inserts++;
i+=3;
}
else
{
ret += c0;
// cerr << "cont3: '" << c0 << "'" <<endl;
continue;
}
}
// remove double spaces
//replaceStringInPlace(ret, " "," ");
//cerr << "separateAlphanumChunks: '" << ret << "'" <<endl;
return ret;
}
inline bool isCharAnInt (char c)
{
//TODO might be able to use isdigit() here
int i = c - '0';
return ((i>=0) && (i<=9));
}
I saw various complex answers, and this is the reason to give another answer too.
The answer of your problem is exactly in the problem statement:
"add an additional Space each time the string changes from numbers to letters or from letters to numbers."
So here is exactly what you want ( I used some code from a previous answer ) the compilation should be done using the flag -std=c++11
#include <string>
#include <iostream>
using namespace std;
enum charTypeT{ other, alpha, digit};
charTypeT charType(char c){
if(isdigit(c))return digit;
if(isalpha(c))return alpha;
return other;
}
string separateThem(string inString){
string oString = "";charTypeT st=other;
for(auto c:inString){
if( (st==alpha && charType(c)==digit) || (st==digit && charType(c)==alpha) )
oString.push_back(' ');
oString.push_back(c);st=charType(c);
}
return oString;
}
int main(){
string str1 = "30EinsteinStreet";
string str2 = "548 Roe Drive5500 TestCity";
string str3 = "44B SaarlouisDrive1234Testtown";
cout << separateThem(str1) << endl;
cout << separateThem(str2) << endl;
cout << separateThem(str3) << endl;
}
I think what you are looking for and what Ajay is hinting at is a finite-state machine to parse strings.
Although this is not a C++11 solution, and you might find more elegant solutions by means of regex, I provided the code sample below.
#include <iostream>
#include <sstream>
bool isDigit(const char c)
{
bool res = true;
switch (c)
{
case '0': case '1': case '2': case '3': case '4':
case '5': case '6': case '7': case '8': case '9':
break;
default:
res = false;
break;
}
return res;
}
std::string separateNumbers(const std::string& inputString)
{
const size_t N = inputString.length();
std::ostringstream os;
bool readDigit = false;
for (size_t i = 0; i < N; ++i)
{
if (isDigit(inputString[i]))
{
if ((i > 0) && (i < N) && (! readDigit))
{
if (inputString[i] != ' ')
os << ' ';
}
readDigit = true;
}
else
{
if ((i > 0) && (i < N) && (readDigit))
{
if (inputString[i] != ' ')
os << ' ';
}
readDigit = false;
}
os << inputString[i];
}
return os.str();
}
int main(int argc, char** argv)
{
std::string strings[3] = {
"30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
};
for (int i = 0; i < 3; ++i)
{
std::cout << "input #" << i << ": " << strings[i] << std::endl;
std::cout << "output #" << i << ": " << separateNumbers(strings[i]) << std::endl;
std::cout << std::endl;
}
return 0;
}
What I would suggest is to go trough a iteration trough string elements.
Something like that will help:
#include <string>
#include <iostream>
using namespace std;
string separateThem(string inString){
string numbers = "1234567890";
string oString = "";
int i;
for(i=0; i<inString.size()-1; i++){
if ((numbers.find(inString[i]) != string::npos) && (numbers.find(inString[i+1]) == string::npos) && !isspace(inString[i+1])){
oString += inString.substr(i,1) + " ";
}
else if ((numbers.find(inString[i]) == string::npos) && (numbers.find(inString[i+1]) != string::npos) && !isspace(inString[i+1])){
oString += inString.substr(i,1) + " ";
}
else oString += inString.substr(i,1);
}
oString += inString.substr(i,1);
return oString;
}
int main(){
string str1 = "30EinsteinStreet";
string str2 = "548 Roe Drive5500 TestCity";
string str3 = "44B SaarlouisDrive1234Testtown";
cout << separateThem(str1) << endl;
cout << separateThem(str2) << endl;
cout << separateThem(str3) << endl;
}
If you execute this the output will be:
30 EinsteinStreet
548 Roe Drive 5500 TestCity
44 B SaarlouisDrive 1234 Testtown
Hope this helps :)
Here is my five cents.
#include <iostream>
#include <string>
#include <cctype>
std::string SeparateAlphanumChunks( const std::string &s )
{
std::string::size_type n = 0;
bool ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) ++n;
}
}
std::string t;
t.reserve( s.size() + n );
ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) t.push_back( ' ');
}
t.push_back( c );
}
return t;
}
int main()
{
for ( const std::string &s : { "30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
} )
{
std::cout << SeparateAlphanumChunks( s ) << std::endl;
}
return 0;
}
The output is
30 EinsteinStreet
548 Roe Drive 5500 TestCity
44 B SaarlouisDrive 1234 Testtown
You also may change the string "in place". For example
#include <iostream>
#include <string>
#include <cctype>
std::string & SeparateAlphanumChunks( std::string &s )
{
std::string::size_type n = 0;
bool ctype = std::isdigit( s[0] );
for ( char c : s )
{
if ( !ctype != !std::isdigit( c ) )
{
ctype = std::isdigit( c );
if ( !isblank( c ) ) ++n;
}
}
s.reserve( s.size() + n );
ctype = std::isdigit( s[0] );
for ( std::string::size_type i = 0; i < s.size(); i++ )
{
if ( !ctype != !std::isdigit( s[i] ) )
{
ctype = std::isdigit( s[i] );
if ( !isblank( s[i] ) )
{
s.insert( i, 1, ' ' );
}
}
}
return s;
}
int main()
{
for ( std::string s : { "30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
} )
{
std::cout << SeparateAlphanumChunks( s ) << std::endl;
}
return 0;
}
Upgrade to GCC 4.9 (whose first release was back in April) and use a simple regex:
#include <regex>
#include <iostream>
std::string fix(const std::string& in)
{
return std::regex_replace(
in,
std::regex("(?:([a-zA-Z])([0-9]))|(?:([0-9])([a-zA-Z]))"),
"\\1\\3 \\2\\4",
std::regex_constants::format_sed
);
}
int main()
{
const std::string in[] = {
"30EinsteinStreet",
"548 Roe Drive5500 TestCity",
"44B SaarlouisDrive1234Testtown"
};
for (auto el : in)
std::cout << fix(el) << '\n';
}
/*
"30 EinsteinStreet"
"548 Roe Drive 5500 TestCity"
"44 B SaarlouisDrive 1234 Testtown"
*/
(live demo)
I would suggest you to iterator the string as raw-string (i.e. string::c_str()), and generate a new string altogether. This would be my algorithm (not very complete):
For each character, check if it is a digit. If no, just append to new string.
If yes, check if it is first character - if yes, just append to new string.
If the digit is last character, then append to new string.
If digit is falling in between, check if last appended character was space. If no space was there, put a space, and then put digit.
If last inserted character was a digit, and this is also a digit, insert.
However, if last was digit, but this is not a digit (and not a space), then insert a space.
You may need to tweak it further.
What if string is like this:
"enter 144 code here 123 "
?

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;
}