0

I am trying to write a C program, where a user must input two arguments into the command line. First, they must provide a name of a text file of values to be read. Second, they must provide a value of 0 or 1, which will be saved as an integer to be used as a boolean (0=false, 1=true).

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[]){
   FILE *f;
   char *fname;
   int boolVal;

  if (argc != 2){
    printf("This program requires two input types, data file and boolean value of 0 or 1\n");
    return 1;
  } 

  fmame = argv[1];
  boolVal = argv[2];
  printf("The file name is %s and the boolVal is %d.\n", fmame, boolVal);

   f = fopen(fname, "r");
   if (f == NULL) perror ("Could not open file");
      else {
         if (fgets(myStr, 1000, f) != NULL )
            puts(myStr);
            fclose(f);
      }
   return 0;
}

I get an error:

testArg.c: In function ‘main’:
testArg.c:16: warning: assignment makes integer from pointer without a cast

I have two questions: Is my reading in of the file name correct? Second, how to solve the issue of casting?

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • It's not an error, it's a warning. – dfranca Mar 24 '15 at 12:31
  • In C it's actually a warning on most compilers. It's incorrect, but it's technically possible to do at the static level @danielfranca. – Qix - MONICA WAS MISTREATED Mar 24 '15 at 12:33
  • @danielfranca, it's a constraint violation, a compiler must _at least_ warn, but may also refuse to compile. In other words, this warning should be treated as an error. – mafso Mar 24 '15 at 13:00
  • the program returns -1 if incorrect number of arguments (which should be 3, not 2 as the program name is argv[0]) so why is the program returning a success indication (0) when it could not open the file? – user3629249 Mar 25 '15 at 01:55

5 Answers5

3

Following your requirement,

where a user must input two arguments into the command line. First, they must provide a name of a text file of values to be read. Second, they must provide a value of 0 or 1, which will be saved as an integer to be used as a boolean (0=false, 1=true).

your code should read like

if (argc != 3)
{  //code

remember, the binary name also counts. So ./<binary> <filename> <1/0> makes the argc as 3.

Next, the reason for the warning in your code is for

boolVal = argv[2];

All the command line inputs are read in a form of string [char *]. You can understand that easily if you check the data type of argv[2]. Isn't it say char *? Then, you need to convert that (alpha)numeric string to an integer value before you assign that value to an int variable.

So, what you need here is

boolVal = atoi(argv[2]);

or, even better and recommended,

boolVal = strtol(argv[2], NULL, 0);    

Please check the man page of strtol() for details.

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Why not `if (argc > 2) { //code` to allow addition of additional command line arguments later without a rewrite of existing code? – David C. Rankin Mar 24 '15 at 12:42
  • Thank you so much! I wonder if I may also ask... why does my code here print out the first line of the file into the console? Is there a way I can suppress that? I get a feeling it occurs during part of the else statement. –  Mar 24 '15 at 13:08
  • @JosephHudson yes, it prints that because you asked it to do so. :-) See, if the `fgets()` returns success, the `puts(string);` will be executed, printning the first line of your file. If you don't want the o/p, remove the `puts()`. – Sourav Ghosh Mar 24 '15 at 13:19
2

You are assigning one pointer that bool variable. You have to do like this.

boolVal=atoi(argv[2]);

Now it will not throw any warning. Then you have to check the condition that is not as argc != 3. Otherwise it give you a segmentation fault. Because argc will have the count from zero. If you are simple giving the ./a.out then the argc count is one.

You are accessing like this, argv[2] So you have to check that argc != 3.

 int atoi(const char *nptr);

atoi will convert the array value into integer value. From the man page of atoi

The atoi() function converts the initial portion of the string pointed to by nptr to int.

Refer here.

Karthikeyan.R.S
  • 3,991
  • 1
  • 19
  • 31
2

One way to compare the value of a string argument passed in argv to to 1 would be as follows:

boolVal = argv[2][0] == '1';

This, however, is a shortcut that works because the string is a single character long. For longer strings, use strcmp:

boolVal = strcmp(argv[2], "yes") == 0;

Note: you should also check that argc is three because of mandatory parameter at position zero.

Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

Change this:

if (argc != 2)

To this:

if (argc != 3 || (argv[2][0] != '0' && argv[2][0] != '1') || argv[2][1] != '\0')

And this:

boolVal = argv[2];

To this:

boolVal = argv[2][0]-'0';
barak manos
  • 29,648
  • 10
  • 62
  • 114
0

This:

if (argc != 2){

should be

if (argc != 3){

as argv[0] will be the name of the program that you run and you want two other inputs too. Thus, the check with argc should be with 3 instead of 2.

As for the warning, it is because here:

boolVal = argv[2];

boolVal is of type int while argv[2] is of type char*. You can't directly assign them and this is what the compiler is complaining about. Use

sscanf(argv[2],"%d",&boolVal);

to extract a number from argv[2] and store it in the address of boolVal. sscanf returns the total number of items successfully scanned and assigned. So, You can also check if the extraction was successful by using

if(sscanf(argv[2],"%d",&boolVal)==1)
    //Extraction successful!

Furthermore, you can check if the successfully extracted number is either 1 or 0 by using

if(boolVal !=0 && boolVal !=1)
    //Bad Value
Spikatrix
  • 20,225
  • 7
  • 37
  • 83