Problems while parsing command line arguments - c++

Here is my code:
#include <iostream>
#include <fstream>
using namespace std;
int main (int argc, char * argv[])
{
char * inputFileName = new char ;
char * outputFileName = new char ;
*(inputFileName)='\0';
*(outputFileName)='\0';
if(argc!=3)
{
cout<<"\n\nWRONG SET OF ARGUMENTS!!\n\nSYNTAX:\n"<<endl;
cout<<"\n./FileCp <SOURCE> <DESTINATION>\n"<<endl;
return 1;
}
strcpy(inputFileName,argv[1]);
strcpy(outputFileName,argv[2]);
cout<<"Input File Name = "<<inputFileName<<endl ;
cout<<"Output File Name = "<<outputFileName<<endl ;
}
This is the command I used:
./FileCp /Users/sumanthdamarla/Downloads/20130530_235557.jpg jkhs.jpg
And here is the output:
Input File Name = /Users/sumanthdajkhs.jpg
Output File Name = jkhs.jpg
The inputFileName is being overridden by outputFileName.
How to resolve this?

char * inputFileName = new char ;
char * outputFileName = new char ;
These two lines allocate space for exactly one character each.
strcpy(inputFileName,argv[1]);
strcpy(outputFileName,argv[2]);
These two lines, copies at least 2 characters (as otherwise it wouldn't count as an argument - an argument can't be "empty").
I would suggest that you use std::string instead of allocating memory. Then you can just do outFilename = argv[2]; and not have to worry about it's size.
Alternatively, if you are not going to use the name for anything other than keep it in a name that makes more sense than argv[2], then you could just declare const char *outFilename, and set it with outFilename = argv[2]; - but beware that modifying the contents of argv[2] is not recommended, as you don't know what is "behind it".

Related

Copy specific range of 2 Dimensional Char[][] Array to char * or std::string

Assuming you read the title, here's a little example in pseudo code:
char inputChar[5][20];
{put data in array obviously}
char * outputChar;
copy(inputChar[2][7], inputChar[2][18], outputChar);
printf("%s", outputChar);
or optionally (although I prefer the above version):
char inputChar[5][20];
{put data in array obviously}
std::string outputString;
copy(inputChar[2][7], inputChar[2][18], outputString);
cout outputString; //I don't know how to use std::strings with printf
I've tried std::copy and memcpy but I can't get it to work. The result either gives me random characters that aren't part of the string, or just results in compiler errors due to me not understanding the syntax fully.
EDIT:
Here is the actual code I'm using:
(assume for this example that storeMenu already has data assigned to it)
int line = 0
int frame5 = 11;
char storeMenu[9][13];
char * temp1 = new char[12];
char * temp2 = new char[12];
std::copy(&storeMenu[line+1][0], &storeMenu[line+1][frame5-10], temp1);
std::copy(&storeMenu[line][frame5-10], &storeMenu[line][12], temp2);
To use std::copy you need a pointer to the location of the character, you are passing the character itself here. You also need to initialize outputChar.
char inputChar[5][20] = {"abc","def","ghi01234567890","jkl"};
char * outputChar = new char[20];
auto last = copy(&inputChar[2][0], &inputChar[2][5], outputChar);
*last = '\0';
printf("%s\n", outputChar);
Alternatively using std::string:
char inputChar[5][20] = {"abc","def","ghi01234567890","jkl"};
string outputChar;
copy(&inputChar[2][0], &inputChar[2][5], back_inserter(outputChar));
printf("%s\n", outputChar.c_str());
Using inputs as std::string too:
string inputChar[5] = {"abc","def","ghi01234567890","jkl"};
int fromChar = 2; // from (inclusive) ^ ^
int toChar = 5; // to (exclusive) ^
string outputChar;
copy(inputChar[2].begin()+fromChar, inputChar[2].begin()+toChar, back_inserter(outputChar));
printf("%s\n", outputChar.c_str());
cout << outputChar << endl;

String to double conversion allways 0

I am trying to read a double precision floating point number from a binary file and assign it to a static double variable. I have tried numerous methods however the result of the conversion regardless of the method is 0.The number is correctly read from the file(as an array of characters), however something happens when I try to convert it... The included headers are: # include < string > # include < sstream > #include < stdlib.h >
The code snippet of the method is given bellow:
FILE * pFile;
char mystring [100];
double v;
string temp;
QString t_string;
pFile = fopen ("path_to_binary_file","r");
if (pFile != NULL)
{
if ( fgets (mystring , 100 , pFile) != NULL )
{
//I am putting a \0 on the last position since my array finishes with \n
mystring[strlen(mystring) - 1] = '\0';
temp.assign(mystring, mystring + 12);
t_string = QString::fromStdString(temp);
// std::istringstream s(temp);
// s >> sheethConstant;
v = t_string.toDouble();//atof(mystring);
static_variable = v;
}
fclose (pFile);
}
If the decimal separator is a comma you must handle with locale.
Since you're using Qt is possible to set a QLocale object and setting a locale that uses the comma (I've only take one that works, it's not specific to your situation).
#include <QDebug>
#include <QLocale>
int main(int argc, char *argv[]) {
QString t_string("0,04019173434");
QLocale locale(QLocale::Catalan);
double number = locale.toDouble(t_string);
qDebug() << "String is" << t_string << ", number is " << number;
return 0;
}

C++ How to pass command line argument to read txt file

What I've been trying to do is...
1) to read txt files by command line argument,
2) to use strings in the txt files as arguments for the main method (or whatever method you need to invoke).
For example, there are two txt files, one of which is named character.txt and the other match.txt.
The contents of the files would be like this.
character.txt
//This comprises of six rows. Each of the rows has two string values
Goku Saiyan
Gohan Half_Saiyan
Kuririn Human
Piccolo Namekian
Frieza villain
Cell villain
match.txt
//This comprises of three rows, each of them is one string value
Goku Piccolo
Gohan Cell
Kuririn Frieza
If I use those strings without using command line, I'd declare the strings in character.txt like this.
typedef string name; //e.g. Goku
typedef string type; //e.g. Saiyan, Human, etc
Now I'm looking for how to read and send string values from txt files like the ones above, and to use them for functions inside the main method, ideally like this way.
int main(int argc, char *argv)
{
for (int i = 1; i < argc; i++) {
String name = *argv[i]; //e.g. Goku
String type = *argv[i]; //e.g. Saiyan, Human, etc
String match = * argv[i]; //Goku Piccolo
//I don't think any of the statements above would be correct.
//I'm just searching for how to use string values of txt files in such a way
cout << i << " " << endl; //I'd like to show names, types or matchs inside the double quotation mark.
}
}
Ideally, I'd like to invoke this method in this way.
According to this web site., at least I understand it is possible to use command line arguments with C++, but I cannot find any more information. I'd appreciate if you'd give any advice on it.
PS. I'm using Windows and Code Blocks.
Asuming you just want to read contents of the files and process it, you can start with this code (Without any errors checks tho). It simply gets filenames from command line and reads file contents into 2 vectors. Then you can just process these vectors as u need.
#include <string>
#include <fstream>
#include <iostream>
#include <vector>
std::vector<std::string> readFileToVector(const std::string& filename)
{
std::ifstream source;
source.open(filename);
std::vector<std::string> lines;
std::string line;
while (std::getline(source, line))
{
lines.push_back(line);
}
return lines;
}
void displayVector(const std::vector<std::string&> v)
{
for (int i(0); i != v.size(); ++i)
std::cout << "\n" << v[i];
}
int main(int argc, char **argv)
{
std::string charactersFilename(argv[1]);
std::string matchesFilename(argv[2]);
std::vector<std::string> characters = readFileToVector(charactersFilename);
std::vector<std::string> matches = readFileToVector(matchesFilename);
displayVector(characters);
displayVector(matches);
}
to see how to use command line arguments look at this.
http://www.cplusplus.com/articles/DEN36Up4/
you cannot use the contents of the file which you have passed to your app through command line arguments. only the name of the file is passed to the app.
you should open the file using that name and read its contents. take a look at this:
http://www.cplusplus.com/doc/tutorial/files/
First the main function prototype should be
int main(int argc, char **argv)
OR
int main(int argc, char *argv[])
Second after retrieving files names in the main function you should open each file and retrieve its contents
Third Sample code
int main(int argc, char* argv[])
{
for(int i=1; i <= argc; i++) // i=1, assuming files arguments are right after the executable
{
string fn = argv[i]; //filename
cout << fn;
fstream f;
f.open(fn);
//your logic here
f.close();
}
return 0;
}
You define main prototype incorrectly. You also need std::ifstream to read files.
If you expect exactly two arguments, you may check argc and extract arguments directly:
int main(int argc, char* argv[]) {
if(argc != 3) {
std::cerr << "Usage: " << argv[0]
<< " name.txt match.txt" << std::endl;
return 1;
}
std::ifstream name_file(argv[1]);
std::ifstream match_file(argv[2]);
// ...
return 0;
}
If you expect unspecified number of files, than you need a loop and an array to save them, i.e. vector:
int main(int argc, char* argv[]) {
std::vector<std::ifstream> files;
for(int i = 1; i < argc; ++i)
files.emplace_back(argv[i]);
// ...
return 0;
}
And do not forget to check if files are openable.
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
FILE *fp = fopen( argv[1], "r");
char line[50];
if (fp == NULL)
{
printf("File opening Unsuccessful\n");
exit(1);
}
while (fgets(line , 30 , fp) != NULL)
{
printf("%s",line);
}
fclose(fp) ;
return 0;
}

search and replace with pointers

Im trying to implement a 'search and replace all'. I have 2 pointers to monitor characters nclude
#include
#include
using namespace std;
const int BUFSIZE = 256;
const char * const SEARCH = "the";
const char * const REPLACE = "Who is John";
int main()
{
char buf[BUFSIZE];
Error(SOURCE_FILE);
//open file for append and update
fstream destination(DESTINATION_FILE,
ios_base::in | ios_base::out | ios_base::app);
//check if destination file is open
if (!destination.is_open())
Error(SOURCE_FILE);
bufPtr += length; //move bufPtr to point past the SEARCH
destination << bufPtr; //write rest of buf to destination
//destination.seekg(0);
//write lines from source to destination
//if(!(destination << buf << '\n'))
//Error(SOURCE_FILE);
}
source.close();
destination.close();
return 0;
}
You're not checking for the case where strstr() doesn't find the search string. It returns NULL in that case, and your while loop loop won't do the right thing in that case.

How to initialize char**?

Here is my piece of code:
char** filename;
*(filename) = "initialize";
printf("filename = %s",*(filename));
I got this error when I tried to run it:
Run-Time Check Failure #3 - The variable 'filename' is being used without being initialized.
Is there any way to fix this?
char *a = "abcdefg";
char **fileName = &a;
C way:
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
char * filename = (char*) malloc( 100 ); // reserve 100 bytes in memory
strcpy(filename,"initialize"); // copy "initialize" into the memory
printf("filename = %s",filename); // print out
free(filename); // free memory
filename = 0; // invalid pointers value is NULL
C++ way:
#include <string>
#include <iostream>
string filename("initialize"); // create string object
cout << "filename = " << filename; // write out to stanard out
You need to allocate room for filename using new or malloc. As it is, filename is just a pointer to a random area of memory you have not requested...
filename = new char*;
char** filename = new char*;
*(filename) = "initialize";
printf("filename = %s",*(filename));
But why do you need that stuff?
#Naszta's answer is the one you should listen to. But to correct all these other wrong answers on new:
size_t len = strlen("initialize") + 1;
char* sz = new char [len];
strncpy(sz, "initialize", strlen("initialize"));
The real C++ way of doing it is better, of course.
string filename = "initialize";
cout << "filename = " << filename;
For initializing char **variable you can also use the following way.
//define length
int length = 1;
std::string init_str = "your_string";
//inititlize char **var length
char **my_var = static_cast<char **>(calloc(length, sizeof(char *)));
my_var[0] = static_cast<char *>(calloc(init_str.size() + 1, sizeof(char)));
//copy string value in char **my_var
strcpy(argv[0], api_flag.c_str());
This way you can initialize for multiple values and assign values for length (N)
You haven't allocated the char* that you're trying to assign to:
char** filename = new char*;
*filename = "initialize";