-1

I am wanting to write a program in c that takes in an integer, an input file and an output file when compiled. The execution code should be as follows:

./example N input_file output_file

I'm trying to work out how to configure this in c. So far I have managed to successfully take in the input_file and output_file and code is as follows:

int main(int argc, char *argv[]){
FILE *M, *fin, *fout;
int *N;

// check if we have 3 arguments - remember that the first one is the file name
if(argc!=4){
    printf("ERROR: not enough input parameters\n");
    printf("USE: %s input output\n",argv[0]);
    exit(1);
}

N = argv[1];
printf("%f \n",DECIMATION_FACTOR);
// open input files as binary read-only
fin=fopen(argv[2],"rb");
if(fin == NULL) {
    printf("ERROR: %s does not exist\n",argv[1]);
    exit(1);
}

// open output files as binary - overwrite the file if it alredy exists
fout=fopen(argv[3],"w+b");
if(fout == NULL) {
    printf("ERROR: %s cannot be created\n",argv[2]);
    exit(1);
}

}

How can I input an integer where N is?

Major Anarchy
  • 17
  • 1
  • 4

2 Answers2

1

All arguments are C strings (zero terminated pointers to char). You need to convert the string to integer. The standard library offers many facilities to do so, which differ based on the type of control that you want to have on strings which should be integers and are in fact something else. One option is:

char *endptr;
long int val = strtol(argv[1], &endptr, 0);
if (*endptr != 0) {
    // Failed to convert the whole string (at least something was left behind)
}
else {
    // Everything was converted: now you can trust the input, or you need to 
    // check errno for ERANGE. In this case set errno=0 before calling strtol.
}
Costantino Grana
  • 3,132
  • 1
  • 15
  • 35
1

The lines

int *N;
[...]
N = argv[1];

will not work, because argv[1] is a pointer to a string, not an integer or a pointer to an integer.

In order to convert a string to an integer, you can use the function strtol, for example like this:

int N;
char *p;

N = strtol( argv[1], &p, 10 );

if ( p == argv[1] )
{
    fprintf( stderr, "error converting value!\n" );
    exit( EXIT_FAILURE );
}

printf( "The number was successfully converted to %d.\n", N );

Note that this program will not check whether the input is in the representable range of an int. It will simply return LONG_MAX (e.g. 2,147,483,647 or 9,223,372,036,854,775,807, depending on your platform) and truncate it to an int. However, as described in the documentation of the function strtol (link see above), it is possible to check for such a range error, by checking the value of errno.

Andreas Wenzel
  • 22,760
  • 4
  • 24
  • 39
  • The difference between this test and the one in my answer is that if something from the string was converted to `long int`, this will accept the partial conversion. My version requires that the whole string gets converted. There's no right or wrong, but different behaviors. – Costantino Grana Mar 06 '22 at 16:04
  • @CostantinoGrana: Yes, your solution is better because you are rejecting input such as `31abc2def`, whereas my program considers it valid input for the number `31`. However, your solution is inconsistent because it accepts leading whitespace characters (because `strtol` accepts them), whereas it rejects trailing whitespace characters. Therefore, an ideal solution would check whether all remaining characters are whitespace characters, and only reject the input if that is not the case. – Andreas Wenzel Mar 06 '22 at 16:18
  • @CostantinoGrana: This is what I have done in the function `get_int_from_user` in the second code snippet in [this answer of mine to another question](https://stackoverflow.com/a/69636446/12149471). – Andreas Wenzel Mar 06 '22 at 16:18