5

I'm trying to figure out how to be able to read in a .txt file as a command prompt argument instead user input. If I have the program

#include <iostream>
#include "cmdline.h"
using namespace std;

int main (int cnt, char * args[]) {
    int a = cmdline_int(args, 1);
    int b = cmdline_int(args, 2);
    cout << "sum = " << a << " + " << b << " = " << a + b << endl;
    return 0;   
}

where the file "cmdline.h" contains

#include <cstdlib>
#include <string>
using namespace std;

int cmdline_int( char* cmdline_a[], int n ) {
  return atoi( cmdline_a[ n ] );
}
char cmdline_char( char* cmdline_a[], int n ) {
  char c = cmdline_a[ n ][0];
  return c;
}

I can run the program as

./program 3 5

and the output will be

sum = 3 + 5 = 8

however if I have a file (textfile.txt) that simply contains those same numbers in list form, i.e.

3
5

and try to run it as

./program < textfile.txt

I get

Segmentation fault

it does the same thing if textfile.txt contains "3 5", though its important that I use a text file in list form anyway. What do I need to change to make "./program textfile.txt" have the same output as "./program 3 5" ?
I'm guessing the problem lies between the int main parenthesis, I'm just not sure what specifically.

4 Answers 4

6

Test program

When you want to check such things, I would recommend first understanding how the application receives them. I would start with the following minimal program:

int main (int argc, char * argv[]) {
  for (int i = 0; i < argc; i++)
    cout << argv[i] << endl;
  return 0;   
}

And execute it

  • ./program 3 5 outputs:

    ./program
    3
    5
    
  • ./program < textfile.txt outputs:

    ./program
    

So now you can see that the issue is with how the txt file is passed to the application. And the reason your application crashes is because you use the arguments without validating that they actually exist!

Explanation

The symbol (<) means opening the file up and attaching it to the standard input (cin) of your application.

./program < textfile.txt is not related to the arguments, instead you have to read it from cin.

Solution using arguments

Use

./program `cat textfile.txt`

The cat command will "replace itself" with the contents of the file and it will work as if you manually wrote it.

Solution using < and cin

When running with ./program < textfile.txt the following will print the numbers:

int a, b;
cin >> a >> b;
cout << a << endl;
cout << b << endl;

Combined solution

This will work for both:

int main (int argc, char * argv[]) {
  int a, b;
  if (argc == 1) { // No extra arguments, read from cin
    cin >> a >> b;
  } else { // Use args
    a = cmdline_int(argv, 1);
    b = cmdline_int(argv, 2);
  }

  // Do something with a,b
  return 0;
}
Sign up to request clarification or add additional context in comments.

2 Comments

is there something I could change so "./program < textfile.txt" would work? because I technically need the input to follow that format (this is for an assignment so the only thing I can change is what's in program.cpp). I should mention that I honestly don't understand much of what's happening inside cmdline.h (it was written by the prof to be used for this assignment).
@zeurosis, I added an explanation about '<'. But(!) please try to understand code, not brute-force it!
2

Run your program as:

./program myfile.txt

and use the argv[1] command line parameter to accept the file name instead. Parse accordingly:

#include <iostream>
#include <fstream>
#include <string>

int main(int argc, char* argv[]) {
    if (argc > 1) {
        std::ifstream fs(argv[1]);
        int a, b;
        while (fs >> a >> b) {
            std::cout << a << ' ' << b << '\n';
        }
    } else {
        std::cout << "No arguments." << '\n';
    }
}

2 Comments

is there an alternative to doing that than using "ifstream"? I haven't learned that yet and because this is for a class I can't use anything we haven't technically learned yet. also, what is fs()? I'm not familiar with that either
@zeurosis There are alternatives. This is the idiomatic way to read the file content. I have updated the answer with relevant headers for you to explore.
0

You redirect the textfile.txt into your program, so you couldn't read it from the parameter directly.

You could read the file content from the redirect by using cin

char c;
while (std::cin.get(c))
{
    // process char
}

Or, you could pass the filename as paramter like ./program textfile.txt, and read from the file

char* filename = args[1];
std::ifstream infile(filename);
int a = 0, b = 0;
infile >> a >> b;

1 Comment

for the first part, under the "while" do I still use the cmdline_int(args,#) parts? also I'm not familiar with ifstream and infile() therefore I'm not allowed to use them (I know, very restrictive, sorry). the input really has to follow the format ./program < textfile.txt, including the less than sign, as thst's what the prof will type but with his own text file
0
#include <stdio.h>
int main(int argc, char* argv[]) {
  *//read from textfile one char at a time:*
  char c;
  while ((c=getchar()) != EOF){ 
     *//Command line should look like:
     //./program < textfile.txt*
    printf("%c",c); //print char 
  }
  return 0;
}

1 Comment

When you share code snippet as answer, please try to explain it. You can visit and check how to answer a question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.