0

I'm trying to work with C for the first time. I have a program that calls a bash script. This script printf's a number via

COUNT=$(ls | grep tool | wc -l)
printf "%s" "$COUNT"

I want to grab this number and perform a simple math operation on it. However, I can't seem to be able to convert this value into an int so that I can divide it by 2.

I've tried things like https://stackoverflow.com/a/868508/183254

int myint = otherint - '0';

which produces a segmentation fault when I got it to compile and it attempted to do the math.

I've also tried many iterations of

int cc;
cc = count - '0';
// warning: assignment makes integer from pointer without a cast [enabled by default]
// or
// warning: initialization from incompatible pointer type [enabled by default]

to no avail.

I've read several posts that came up for the google search for those errors, but still can't seem to be able to wrap my head around what is going on I think perhaps because I don't have the context of what the questioner is trying to achieve.

Here is a little demo I put together to try and understand what is going on. Turns out it just made me more confused.

int main(){
  char *x;
  x="44";
  int xx;
  xx = (int) x - '0';
  printf("x is : %s\n", x);
  printf("xx is : %d\n",xx);// x is : 23703288
  char command[64];

  char path[9];// won't work if set to <=8
  int status;
  FILE *fp;

  //this shell script just counts the number of files in a directory
  //that match a certain string. 
  strcpy(command, "/test/test.sh");// returns 0-9; in this case it's returning 4 (supposed to anyway)


  fp = popen(command, "r");
  if (fp == NULL)
    /* Handle error */;

  while (fgets(path, 9, fp) != NULL) //again, won't work if arg2 is <=8
    //printf("%s", path);

  status = pclose(fp);

  int cc;
  cc = (int) path - '0';

  printf("result of path is %s\n",path );    // result of path is        4
  printf("result of conversion is %d\n", cc);// result of conversion is 1582717056
}

output:

x is : 44
xx is : 182607602
result of path is        4
result of conversion is 1423813191

I've found and read a couple of primers but I don't know if they are old or what but the didn't help much besides explaining pointers a bit.

What really boggles my mind is what is going on in the snippet above:

x is : 44

Ok, that makes sense since I typed out x="44";.

xx is : 182607602

wat. This looks like it must be a pointer to some address. According to the primers I read, this should come from something like &x;; why is it coming from what should be converting the char 44 to int 44?

result of path is        4

Ok (except all of those spaces). It almost seems like it's being padded or something. char path[9]; and while (fgets(path, 9, fp) != NULL) heighten my suspicion, but as commented won't work <= 8.

result of conversion is 1423813191

Same; seems to be pointing to address space. Don't understand why.

It seems to be a point of confusion for many people (including me) coming from other languages -- that's my excuse and I'm sticking to it.

Any pointers would be greatly appreciated (good primers, what's going on in this code, anything really).

Thanks.


Found an excellent 9-part series on youtube which does a great job explaining some C fundamentals: https://www.youtube.com/playlist?list=PLkB3phqR3X40reMCBYSoNUPbDvM4kybMs. Part 7 was especially useful -- it covers pointers which was a big part of my confusion.

Community
  • 1
  • 1
stormdrain
  • 7,915
  • 4
  • 37
  • 76
  • x is a `char *`, not a `char`. Your `- '0'` trick only works on a char. – Random832 Nov 20 '13 at 21:20
  • You should read a beginner C tutorial and/or book before attempting to do similar tasks. The function you are looking for is called `strtol()`; **however,** you must possess a minimal understanding of the C type system in order to be able to make sense of its use (and others). –  Nov 20 '13 at 21:23
  • @H2CO3 which is why I asked at the end for pointers to good current primers (or anything else). Thanks, though. – stormdrain Nov 20 '13 at 21:24
  • @Random832 incompatible pointer to integer conversion assigning to 'char' from 'char [3]' – stormdrain Nov 20 '13 at 21:27
  • @stormdrain I was _not_ telling you to make it a char. I was simply telling you that solutions designed for a char won't work on strings. – Random832 Nov 20 '13 at 21:38
  • @Random832 ah, ok. Sorry and thanks. – stormdrain Nov 20 '13 at 21:39

3 Answers3

1

Where you are using this line to convert a two digit number to an integer:

xx = (int) x - '0';

try changing it to

xx = atoi(x);

Here is a good reference: http://www.cplusplus.com/reference/cstdlib/atoi/

To go the other way you may like sprintf

sprintf (buffer, "%d plus %d is %d", a, b, a+b);

where you can find more information here: http://www.cplusplus.com/reference/cstdio/sprintf/

Jacob Brewer
  • 2,574
  • 1
  • 22
  • 25
  • The problem with `atoi()` is that it doesn't report any errors on conversion failure. – P.P Nov 20 '13 at 21:30
  • Yes, you have to clean your own data. Looping through with isdigit should do the trick. here is a handy link: http://stackoverflow.com/questions/3850558/how-to-check-to-ensure-you-have-an-integer-before-calling-atoi – Jacob Brewer Nov 20 '13 at 21:34
1

Your line

xx = (int) x - '0';

and line from mentioned post:

int i = c[0] - '0';

are not the same. You subtract from a pointer but in the post '0' is subtracted from char. In your case the correct version is (without any checks):

xx = x[0] - '0';

or as in post above - you have to convert (char*) to an int with any standard function

VladimirM
  • 817
  • 5
  • 7
1
 char *x;
  x="44";
  int xx;
  xx = (int) x - '0';

Here you are subtracting '0' from a pointer by casting it to an int. This logic would work if x is of type char.

What you really want is to convert the string into using strtol() or related functions.

In the same way, you can convert path to integer as well, which you do later in your code.

P.P
  • 117,907
  • 20
  • 175
  • 238
  • Isn't `x` of type `char` though? Or is `x` of type pointer in this case? I think this is a big part of my confusion. Instantiating a variable with `char *x` means what? It will point to something? It *is* pointing to something? When called, will return the address? – stormdrain Nov 20 '13 at 21:37
  • 1
    No. `x` is type `char*` i.e. a pointer to char. When you assign `"xx"` to `x` (as in char *x; -- too many x's around ;-) you are assigning the address of the string literal (which is same as the address of the first `x` in `"xx"`). – P.P Nov 20 '13 at 21:49
  • So, you mentioned I converted `path` to `int` later in the code (`cc` I assume). Why then does `cc` print what looks to be an address pointer (1423813191)? – stormdrain Nov 20 '13 at 21:54
  • Thank you so much for your help (and patience with all the `x`'s) :) Was there supposed to be a link though? I don't see anything by or on "You can read more here" or were you referencing the other answer here? – stormdrain Nov 20 '13 at 22:05
  • Yes, I talk about cc. The exact problem that happens with x also happens with path as well. Though path is of different type (char[] i.e. array of chars), it's converted to char* when you use it in an expression like path - '0'. path[] becomes char * in few other occasions too. But that's not so relevant here. You can read more here: http://stackoverflow.com/questions/1461432/what-is-array-decaying – P.P Nov 20 '13 at 22:07