How do you get the values of the flags in getopt, I have tried googling it but all I got is on how to switch cases and set flags. I got the below code and what I am trying to do is to have three flags, -a, -b, -c but only two flags are passed like ./filename -a somevalue -c anothervalue or ./filename -b somevalue -c anothervalue any help?
int main(int argc, char *argv[])
{
int flagA = 0;
int flagB = 0;
while (1) {
char c;
c = getopt (argc, argv, "abc:");
if (c == -1) {
break;
}
switch (c) {
case 'a':
flagA = 1;
//cout<<optarg<<endl; //I tried printing the value but it only prints the second flag value
break;
case 'b':
flagB = 1;
cout<<optarg<<endl;
break;
case 'c':
cout<<optarg<<endl;
break;
case '?':
default:
cout<<"Usage: %s [-a] [-b <something>].\n", argv[0]<<endl;
}
if(flagA > 0){
//do something using the values of flagA and flagC
}
else if(flagB > 0){
//do something using the values of flagB and flagC
}
}
return 0;
}
If you intend to use optarg with a flag, the flag must have : after it in the option string.
c = getopt(argc, argv, "a:b:c:");
Your usage output statement should not have compiled for you. Also, you are attempting to mix C style format specifiers into a C++ output stream, which is incorrect.
cout << "Usage: " << argv[0] << " [-a] [-b <something>].\n";
There are multiple problems with the code, but the key one is in your invocation of getopt(). You have the option control string "abc:", which means that neither -a nor -b takes an option.
Assuming you're using a POSIX standard version of getopt() and not GNU getopt(), then when you run either:
./filename -a somevalue -c anothervalue
./filename -b somevalue -c anothervalue
the somevalue after the first flag means that options are finished and the remaining arguments are non-option arguments. GNU getopt(), in the absence of the environment variable POSIXLY_CORRECT, will permute the argument list so that -c anothervalue is also recognized (and the arguments are permuted such that somevalue ends up at the end).
Your code would be better written:
#define _XOPEN_SOURCE 600
#include <iostream>
#include <unistd.h>
using namespace std;
int main(int argc, char *argv[])
{
int flagA = 0;
int flagB = 0;
int opt;
char *c_opt = 0;
while ((opt = getopt(argc, argv, "abc:")) != -1)
{
switch (opt)
{
case 'a':
flagA = 1;
cout << "A: " << flagA << "\n";
break;
case 'b':
flagB = 1;
cout << "B: " << flagB << "\n";
break;
case 'c':
c_opt = optarg;
cout << "C: " << c_opt << "\n";
break;
default:
cerr << "Usage: " << argv[0] << " [-a] [-b] [-c <something>]\n";
return -1;
}
}
if (flagA)
{
// do something using the values of flagA and c_opt (if set)
}
else if (flagB)
{
// do something using the values of flagB and c_opt (if set)
}
else if (c_opt)
{
// do something using just c_opt (neither flagA nor flagB is set)
}
else
{
// do something if no options are specified (report error?)
}
for (int i = optind; i < argc; i++)
cout << "File: " << i << ": " << argv[i] << "\n";
return 0;
}
The code above (as amended) compiles cleanly with GCC 4.9.1 on Mac OS X 10.10 (Yosemite):
g++ -O3 -g -std=c++11 -Wall -Wextra -Werror opt.cpp -o opt
The BSD-ish getopt() hews close to the POSIX standard, so the result I get is:
$ ./opt -a 5 -c something
A: 1
File: 2: 5
File: 3: -c
File: 4: something
$
florw.wat commented:
I want the -a and -b options to take an argument. What I am trying to do is I have two functions which take two arguments, so if -a is set then I would like to call function a else if -b then call function b. I need the two values to call the functions.
Given that clarification, the code might look like:
#define _XOPEN_SOURCE 600
#include <cstdlib>
#include <iostream>
#include <unistd.h>
using namespace std;
static void usage(const char *arg0)
{
cerr << "Usage: " << arg0 << " [-a filename | -b filename] -c <something>\n";
exit(EXIT_FAILURE);
}
int main(int argc, char *argv[])
{
char *a_opt = 0;
char *b_opt = 0;
char *c_opt = 0;
int opt;
while ((opt = getopt(argc, argv, "a:b:c:")) != -1)
{
switch (opt)
{
case 'a':
a_opt = optarg;
cout << "A: " << a_opt << "\n";
break;
case 'b':
b_opt = optarg;
cout << "B: " << b_opt << "\n";
break;
case 'c':
c_opt = optarg;
cout << "C: " << c_opt << "\n";
break;
default:
cerr << "Unknown option: " << optopt << "\n";
usage(argv[0]);
break;
}
}
if (optind != argc || c_opt == 0 || (a_opt && b_opt) || (a_opt == 0 && b_opt == 0))
usage(argv[0]);
else if (a_opt)
cout << "A&C: " << a_opt << " " << c_opt << "\n";
else
cout << "B&C: " << b_opt << " " << c_opt << "\n";
return 0;
}
Sample run:
$ ./opt -a option -c something
A: option
C: something
A&C: option something
$
Related
int c = 0;
while (c = getopt(argc, argv, "p:t:e:") != -1) {
std::cout<<"c: "<<c<<std::endl;
switch (c) {
case 'p':
if (optarg) {
std::cout << "lol" << std::endl;
person = atoi(optarg);
}
break;
case 't':
if (optarg) {
time = stod(optarg);
std::cout << "ll" << std::endl;
}
break;
case 'e':
if (optarg) {
ecg = atoi(optarg);
std::cout << "2dasf" << std::endl;
}
break;
}
}
Been trying to make getopt work on my Mac. C is printed as 1, but None of the print statements within the switch are printed. This works perfectly in Linux. What is wrong with my Mac?
I'm writing a C++ application which converts fahrenheit to celsius and kelvin, and kelvin to celsius and fahrenheit, etc. Since it's stupid to write an interative application here, I decided to familiarize myself with the getopt function in unistd.h.
Format:
F2C -k 273.15
Output:
FAHR CELSIUS KELVIN
32 0 273.15
Here is my code:
#include <iostream>
#include <stdlib.h>
#include <unistd.h>
#define VERSION 0.1
#define HELP help(argv[0])
#define OPTS "vk:f:c:h"
float ver = (float)VERSION;
void help(char *s);
namespace Fahrenheit
{
float FK(float F) {
return ((5.0/9.0) * (F - 32.0) + 273.15);
}
float FC(float F) {
return ((5.0/9.0) * (F - 32.0));
}
void printfahr(float F) {
std::cout << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << F << "\t\t" << FC(F) << "\t\t" << FK(F) << std::endl;
}
}
namespace Celsius
{
float CF(float C) {
return ((C*(9/5)) + 32);
}
float CK(float C) {
return (C+273.15);
}
void printc(float C) {
std::cout << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << CF(C) << "\t\t" << C << "\t\t" << CK(C) << std::endl;
}
}
namespace Kelvin
{
float KF(float K) {
return (((9.0/5.0) * (K-273.15)) + 32);
}
float KC(float K) {
return (K-273.15);
}
void printk(float K) {
std::cout << "FAHR\t\tCELSIUS\t\tKELVIN" << std::endl;
std::cout << KF(K) << "\t\t" << KC(K) << "\t\t" << K << std::endl;
}
}
int main(int argc, char *argv[])
{
char arg = '\0';
if(argc < 2 && argc == 1 && argc > 0) {
help(argv[0]);
exit(1);
}
/*** Use function getopt() defined in unistd.h to accept 5 arguments: -v, -h, -k, -f, and -c ***/
while((arg=getopt(argc, argv, OPTS))!=-1)
{
float floatarg = atof(optarg);
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(floatarg);
break;
case 'f':
Fahrenheit::printfahr(floatarg);
break;
case 'c':
Celsius::printc(floatarg);
break;
default:
HELP;
break;
}
}
return 0;
}
void help(char *s) {
std::cout << "Usage:\t"<< s << " [-option] [argument]" << std::endl;
std::cout << "option:\t" << "-c [temperature]: convert a Celsius temperature to Fahrenheit and Kelvin" << std::endl;
std::cout << "\t" << "-f [temperature]: convert a Fahrenheit temperature to Celsius and Kelvin" << std::endl;
std::cout << "\t" << "-h: show help information" << std::endl;
std::cout << "\t" << "-k [temperature]: convert a Kelvin temperature to Fahrenheit and Celsius" << std::endl;
std::cout << "\t" << "-v: show version information" << std::endl;
}
My problem is that whenever I use an option that accepts no arguments (like -v) I get a core dump.
dbx has shown me that the SIGSEV occurs at line 70 (float floatarg = atof(optarg);).
When I run the program like this:
./F2C -k 273.15
The math is done correctly and I get a clear printout. It's only when I use -v or -h that my program SIGSEV's.
Extra information:
This program was compiled with the Sun studio compiler suite, version 5.12.
I'm completely baffled as to why my program SIGSEV's. It is inconsistent and makes no sense.
I would appreciate any help available.
Should have done some optarg checking. After all, you can't convert null to a float.
new main():
#define FLOATARG atof(optarg)
int main(int argc, char *argv[])
{
char arg = '\0';
if(argc < 2 && argc == 1 && argc > 0) {
help(argv[0]);
exit(1);
}
/*** Use function getopt() defined in unistd.h to accept 5 arguments: -v, -h, -k, -f, and -c ***/
while((arg=getopt(argc, argv, OPTS))!=-1)
{
switch(arg)
{
case 'v':
std::cout << "The current version is: << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(FLOATARG);
break;
case 'f':
Fahrenheit::printfahr(FLOATARG);
break;
case 'c':
Celsius::printc(FLOATARG);
break;
default:
HELP;
break;
}
}
return 0;
}
The shortest fix is:
float floatarg = optarg ? atof(optarg) : 0.0;
You can also rewrite your code like
float floatarg = 0.0;
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
floatarg = atof(optarg);
Kelvin::printk(floatarg);
break;
case 'f':
floatarg = atof(optarg);
Fahrenheit::printfahr(floatarg);
break;
...
or
float floatarg = 0.0;
if(optarg) {
floatarg = atof(optarg);
}
switch(arg)
{
case 'v':
std::cout << "The current version is:" << ver << std::endl;
break;
case 'h':
HELP;
break;
case 'k':
Kelvin::printk(floatarg);
break;
case 'f':
Fahrenheit::printfahr(floatarg);
break;
...
I'm new to C++. I'm writing a simple calculator using command line. The command line should have this format:
programname firstNumber operator secondNumber
Here what I got so far:
#include <iostream>
#include <fstream>
using namespace std;
int main(int argc, char* argv[])
{
if (argc != 3)
{
cerr << "Usage: " << argv[0] << endl;
exit(0);
}
else
{
int firstNumber = atoi(argv[1]);
char theOperator = atoi(argv[2]);
int secondNumber = atoi(argv[3]);
switch (theOperator)
{
case'+':
{
cout << "The answer is " << firstNumber + secondNumber << endl;
break;
}
case '-':
{
cout << "The answer is " << firstNumber - secondNumber << endl;
break;
}
case '*':
{
cout << "The answer is " << firstNumber * secondNumber << endl;
break;
}
case '/':
{
if (secondNumber == 0)
{
cout << "Can not devide by a ZERO" << endl;
break;
}
else
{
cout << "The answer is " << firstNumber / secondNumber << endl;
break;
}
}
}
}
}
The program does not run. When I run it, it displays an appropriate usage message and end the program. Can anyone please help me?
Others have already given you the answer but you could have very easily figured this one out on your own. Just print what argc is at the point where you know the code is going into:
int main(int argc, char* argv[])
{
if (argc != 3)
{
cout << "argc is: " << argc << endl; // Debug output that you delete later
cerr << "Usage: " << argv[0] << endl;
exit(0);
}
else
And then come back with what argc is. When you find that argc is actually 4 and you want to know what is inside argc you should write some code to print it so that you can figure it out... Like this:
int main(int argc, char* argv[])
{
cout << "argc is: " << argc << endl; // Debug output that you delete later
for (int i = 0; i < argc; ++i)
{
// Print out all of the arguments since it's not working as you expect...
cout << "argv[" << i << "] = " << argv[i] << endl;
}
if (argc != 3)
{
cerr << "Usage: " << argv[0] << endl;
exit(0);
}
else
and you would have very quickly figured out what is wrong...
Please learn how to do this because it will save your but in the future and you won't have to wait for an answer here.
Additionally there is another error in your code.
Why on earth are you converting the + character from a string to an int?
else
{
int firstNumber = atoi(argv[1]);
char theOperator = atoi(argv[2]); // <<< WTF? Why?
int secondNumber = atoi(argv[3]);
switch (theOperator)
You probably want to get rid of the atoi part there and just go with:
char theOperator = argv[2][0]; // First character of the string
Provided that the second argument will always have only one letter... Which you might want to enforce/check. See strlen() and std::string and note that the type of argv[2] is char* (pointer to char).
I also recommend that you read How to debug small programs which is linked from the SO Howto-Ask Help Page. It may help a little. And no, I don't think your question is bad. Debugging small programs is a skill you'll need in the future if you intend to program so it will benefit you to learn it now.
Welcome to programming and C++ :)
The parameter argc also counts the program's name.
Try this:
if (argc != 4) // We expect 4 arguments: programname number operator number
{
cerr << "Usage: " << argv[0] << " <number> <operator> <number>" << endl;
exit(0);
}
In your code, running the program correctly (with all 3 parameters) displays the error message because argc equals 4.
If you type in
programname firstNumber operator secondNumber
You have 4 arguments, not 3.
argv[0] = programname
argv[1] = firstNumber
argv[2] = operator
argv[3] = secondNumber
Looks like your program is working correctly... at least as far as printing the usage message goes.
See also the other comments regarding your use of the operator argument.
I have a C++ executable that, in normal use, accepts a file name as an argument option in the following manner:
executable -i myFile.txt
I want to use Bash process substitution to create a 'virtual file' and send information (simple, line by line data) to this executable in the following manner:
executable -i <(echo "${myData}")
However, my C++ program is not accessing the information when I use this process substitution. The main file reading section of code in the C++ program is the following:
ifstream file1 (fileName1);
string line;
int currentLineNumber = 0;
if (verboseFlag == 1) {cout << "reading data from file " << fileName1 << "..." << endl;}
while (getline (file1, line)){
currentLineNumber++;
if (verboseFlag == 1) {cout << "line " << currentLineNumber << ": ";}
istringstream linestream(line);
string item;
int itemNumber = 0;
while (getline (linestream, item, ',')){
itemNumber++;
if (verboseFlag == 1) {cout << "item " << itemNumber << ": " << item << " ";}
// data
if (itemNumber == 1) {x[currentLineNumber]=atof(item.c_str());}
if (itemNumber == 2) {y[currentLineNumber]=atof(item.c_str());}
}
}
file1.close();
Could you point me in the right direction on solving this reading problem? Is there some better approach that would work for both normal file reading and process substitution 'file' reading?
I'm new to this process substitution and I very much appreciate any assistance on this.
EDIT:
Following some comments, what follows is a minimal working example illustrating the problem I am encountering:
// definition of standard input/output stream objects
#include <iostream>
// manipulate strings as though they were input/output streams
#include <sstream>
// input and output operations
#include <stdio.h>
// file input and output operations
#include <fstream>
// manipulate C strings and arrays
#include <string.h>
// classify and transform individual characters
#include <ctype.h>
// Standard General Utilities Library
#include <stdlib.h>
// getopts (handle command line options and arguments)
#include <unistd.h>
// sstream (handle conversion from char* to double)
#include <sstream>
using namespace std;
double returnDoubleFromPointerToChar(const char *cText){
std::stringstream ss ( cText );
double dText = 0;
ss >> dText;
return dText;
}
int returnNumberOfLinesInFile(const char *fileName1){
int lineCount = 0;
string line;
ifstream file1(fileName1);
while (std::getline(file1, line))
++lineCount;
file1.close();
return lineCount;
}
int main (int argc, char **argv){
char *fileName1 = NULL; // input file name (i) (required input)
int verboseFlag = 0; // verbose flag (v)
int index; // internal variable
int c; // internal variable
opterr = 0;
// process command line arguments and options
while ((c = getopt (argc, argv, "i:v")) != -1)
switch (c){
case 'i':
fileName1 = optarg;
break;
case 'v':
verboseFlag = 1;
break;
case '?':
if (
optopt == 'i'
){
fprintf (stderr, "option -%c requires an argument.\n", optopt);
}
else if (isprint (optopt)){
fprintf (stderr, "unknown option `-%c'.\n", optopt);
}
else {
fprintf (stderr, "unknown option character `\\x%x'.\n", optopt);
}
return 1;
default:
abort ();
}
for (index = optind; index < argc; index++) printf ("non option argument %s\n", argv[index]);
if (verboseFlag == 1){
cout << endl;
cout << "input file name: " << fileName1 << endl;
}
// Determine the number of lines in the input file.
int numberOfLinesInInputFile=returnNumberOfLinesInFile(fileName1);
if (verboseFlag == 1) {cout << "number of lines in input file: " << numberOfLinesInInputFile << endl;}
// number of data points
int n=numberOfLinesInInputFile-1;
// x variable
double x[n];
// y variable
double y[n];
// Access the data in the input file.
ifstream file1 (fileName1);
string line;
int currentLineNumber = 0;
if (verboseFlag == 1) {cout << "reading data from file " << fileName1 << "..." << endl;}
while (getline (file1, line)){
currentLineNumber++;
if (verboseFlag == 1) {cout << "line " << currentLineNumber << ": ";}
istringstream linestream(line);
string item;
int itemNumber = 0;
while (getline (linestream, item, ',')){
itemNumber++;
if (verboseFlag == 1) {cout << "item " << itemNumber << ": " << item << " ";}
// data
if (itemNumber == 1) {x[currentLineNumber]=atof(item.c_str());}
if (itemNumber == 2) {y[currentLineNumber]=atof(item.c_str());}
}
if (verboseFlag == 1) {cout << endl;}
}
file1.close();
return 0;
}
EDIT:
I have added the solution code below (following from a comment by that other guy):
// include WBM C++ library
// #include "lib_cpp.c"
// definition of standard input/output stream objects
#include <iostream>
// manipulate strings as though they were input/output streams
#include <sstream>
// input and output operations
#include <stdio.h>
// file input and output operations
#include <fstream>
// manipulate C strings and arrays
#include <string.h>
// classify and transform individual characters
#include <ctype.h>
// Standard General Utilities Library
#include <stdlib.h>
// getopts (handle command line options and arguments)
#include <unistd.h>
// sstream (handle conversion from char* to double)
#include <sstream>
using namespace std;
// example usage:
// ./graph2d -i data.txt -o data.eps -v
// ./graph2d -i data.txt -o graph.eps -t "training test error versus epochs" -x "epochs" -y "error measure" -v
// ./graph2d -i data.txt -o graph.eps -t "training test error versus epochs" -x "epochs" -y "error measure" -a 70 -b 50 -c 22 -d 7 -v
// ./graph2d -i <(echo "${dataForTrainingErrorVersusEpoch}") -o graph.eps -t "training test error versus epochs" -x "epochs" -y "error measure" -v
double returnDoubleFromPointerToChar(const char *cText){
std::stringstream ss ( cText );
double dText = 0;
ss >> dText;
return dText;
}
int main (int argc, char **argv){
char *fileName1 = NULL; // input file name (i) (required input)
char *fileName2 = NULL; // output file name (o) (required input)
char *graphTitleMain = NULL; // graph title (t)
char *graphTitleAxisx = NULL; // graph x axis title (x)
char *graphTitleAxisy = NULL; // graph y axis title (y)
double axisyMaximum = DBL_MAX; // y axis maximum (a)
double axisyMinimum = DBL_MAX; // y axis minimum (b)
double axisxMaximum = DBL_MAX; // x axis maximum (c)
double axisxMinimum = DBL_MAX; // x axis minimum (d)
int verboseFlag = 0; // verbose flag (v)
int index; // internal variable
int c; // internal variable
opterr = 0;
// process command line arguments and options
while ((c = getopt (argc, argv, "i:o:t:x:y:a:b:c:d:v")) != -1)
switch (c){
case 'i':
fileName1 = optarg;
break;
case 'o':
fileName2 = optarg;
break;
case 't':
graphTitleMain = optarg;
break;
case 'x':
graphTitleAxisx = optarg;
break;
case 'y':
graphTitleAxisy = optarg;
break;
case 'a':
axisyMaximum = returnDoubleFromPointerToChar(optarg);
break;
case 'b':
axisyMinimum = returnDoubleFromPointerToChar(optarg);
break;
case 'c':
axisxMaximum = returnDoubleFromPointerToChar(optarg);
break;
case 'd':
axisxMinimum = returnDoubleFromPointerToChar(optarg);
break;
case 'v':
verboseFlag = 1;
break;
case '?':
if (
optopt == 'i' ||
optopt == 'o' ||
optopt == 't' ||
optopt == 'x' ||
optopt == 'y' ||
optopt == 'a' ||
optopt == 'b' ||
optopt == 'c' ||
optopt == 'd'
){
fprintf (stderr, "option -%c requires an argument.\n", optopt);
}
else if (isprint (optopt)){
fprintf (stderr, "unknown option `-%c'.\n", optopt);
}
else {
fprintf (stderr, "unknown option character `\\x%x'.\n", optopt);
}
return 1;
default:
abort ();
}
for (index = optind; index < argc; index++) printf ("non option argument %s\n", argv[index]);
if (verboseFlag == 1){
cout << endl;
cout << "input file name: " << fileName1 << endl;
cout << "output file name: " << fileName2 << endl;
}
// x variable
vector<int> x;
// y variable
vector<int> y;
// Access the data in the input file.
ifstream file1 (fileName1);
string line;
int currentLineNumber = 0;
if (verboseFlag == 1) {cout << "reading data from file " << fileName1 << "..." << endl;}
while (getline (file1, line)){
currentLineNumber++;
if (verboseFlag == 1) {cout << "line " << currentLineNumber << ": ";}
istringstream linestream(line);
string item;
int itemNumber = 0;
while (getline (linestream, item, ',')){
itemNumber++;
if (verboseFlag == 1) {cout << "item " << itemNumber << ": " << item << " ";}
// data
if (itemNumber == 1) {x.push_back(atof(item.c_str()));}
if (itemNumber == 2) {y.push_back(atof(item.c_str()));}
}
if (verboseFlag == 1) {cout << endl;}
}
file1.close();
int numberOfLinesInInputFile = currentLineNumber + 1;
// number of data points
int n=numberOfLinesInInputFile;
// graph
if (verboseFlag == 1){
cout << "graph main title: " << graphTitleMain << endl;
cout << "graph x axis title: " << graphTitleAxisx << endl;
cout << "graph y axis title: " << graphTitleAxisy << endl;
}
// Create a new canvas.
TCanvas *c1 = new TCanvas(graphTitleMain, graphTitleMain); // #u
// Create a new graph.
//TGraph *graph = new TGraph(n, x, y);
TGraph *graph = new TGraph(n, &x[0], &y[0]);
// Set the graph titles.
graph->SetTitle(graphTitleMain);
graph->GetXaxis()->SetTitle(graphTitleAxisx);
graph->GetYaxis()->SetTitle(graphTitleAxisy);
// Set the marker styles.
graph->SetMarkerColor(2); // red
graph->SetMarkerStyle(kFullCircle); // circle
graph->SetMarkerSize(1); // default size
// Set the graph range, if ranges have been specified in command line options.
if (
axisyMaximum != DBL_MAX &&
axisyMinimum != DBL_MAX
){
if (verboseFlag == 1){
cout << "graph y axis minimum: " << axisyMinimum << endl;
cout << "graph y axis maximum: " << axisyMaximum << endl;
}
graph->GetYaxis()->SetRangeUser(axisyMinimum, axisyMaximum);
}
if (
axisxMaximum != DBL_MAX &&
axisxMinimum != DBL_MAX
){
if (verboseFlag == 1){
cout << "graph x axis minimum: " << axisxMinimum << endl;
cout << "graph x axis maximum: " << axisxMaximum << endl;
}
graph->GetXaxis()->SetRangeUser(axisxMinimum, axisxMaximum);
}
// Draw the canvas, then draw the graph and then save the canvas to an image file.
c1->Draw();
graph->Draw("ALP");
// disable ROOT messages
gErrorIgnoreLevel = 5000;
if (verboseFlag == 1) {cout << "saving file " << fileName2 << "..." << endl;}
c1->SaveAs(fileName2);
if (verboseFlag == 1) {cout << endl;}
return 0;
}
First of all, I trimmed out two thirds of your program and it still shows the problem. This is significantly closer to minimal:
#include <iostream>
#include <fstream>
using namespace std;
int returnNumberOfLinesInFile(const char *fileName1){
int lineCount = 0;
string line;
ifstream file1(fileName1);
while (std::getline(file1, line))
++lineCount;
file1.close();
return lineCount;
}
int main (int argc, char **argv){
char *fileName1 = argv[1];
cout << "input file name: " << fileName1 << endl;
int numberOfLinesInInputFile=returnNumberOfLinesInFile(fileName1);
cout << "number of lines in input file: " << numberOfLinesInInputFile << endl;
ifstream file1(fileName1);
string line;
cout << "File contents: " << endl;
while (getline (file1, line)){
cout << "line: " << line << endl;
}
file1.close();
return 0;
}
The problem here is that you open the file twice. <(process substitution) only runs the command once and streams the result. Bash doesn't take the liberty of running the command again if you want to read output again, since the command could have been doing a lot of other things besides spitting out text.
Make sure your program only opens and reads the contents once, and it'll work. This may require you to rewrite your logic a bit, or just be lazy and read it all into memory at once.
Your code works fine for me (I'm on OS X).
Keep in mind that, unlike real files, "virtual files" are usually pipe endpoints (implemented in bash using file descriptor special files). So, you cannot open, read, and close a virtual file more than once, or you will get nothing the second time around.
Attempting to use MsiEnumRelatedProducts with various input is constantly returning only ERROR_INVALID_PARAMETERS for me. The documentation doesn't give any details on what the source of the invalid parameter could be but I've tried many different options. Currently I have this code below to demonstrate the problem. Replace the with a valid upgrade guid.
int _tmain(int argc, _TCHAR* argv[])
{
const wchar_t* upgrade = L"812D9038-YOUR-GUID-B2EB-64F4E0B3FB3D";
wchar_t product[39];
DWORD index = 0;
switch (MsiEnumRelatedProducts(upgrade, 0, index++, product)) {
case ERROR_SUCCESS:
wcout << L"ERROR_SUCCESS" << endl;
break;
case ERROR_NO_MORE_ITEMS:
wcout << L"ERROR_NO_MORE_ITEMS" << endl;
break;
case ERROR_BAD_CONFIGURATION:
wcout << L"ERROR_BAD_CONFIGURATION" << endl;
break;
case ERROR_INVALID_PARAMETER:
wcout << L"ERROR_INVALID_PARAMETER" << endl;
break;
case ERROR_NOT_ENOUGH_MEMORY:
wcout << L"ERROR_NOT_ENOUGH_MEMORY" << endl;
break;
default:
wcout << L"DEFAULT" << endl;
break;
}
}
Try enclosing your upgrade code in curly brackets so it looks like {GUID}.