-1

It would be nice to cast a string (array of chars) to an int when reading from files or taking input is this possible.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define SIZE 500

int main(void)
{
 FILE* pfile;
 pfile = fopen("/tmp/code","r");                              //open file
 char *stringBuffer = (char *)malloc(SIZE * sizeof(char));   //dynamic string

  char ch;
  int i = 0;
  ch = getc(pfile);                                          //read file
  while(ch != EOF)                                           //until end
  {                                                          //pass into string 
        counter++;
        stringBuffer[i] = ch;
        ch = getc(pfile);
        i++;
    }

    fclose(pfile);                                              //resize string

    int stringSize = (int)(sizeof(stringBuffer)/sizeof(char));
    stringBuffer = (char *)realloc(stringBuffer,(stringSize * sizeof(char)));

    printf("the string works: %s \n",stringBuffer);

    int intger = (int)*stringBuffer;    //this is what i want to work!!!!

    //but more like
    //int intger = (int)stringBuffer; 

    printf("the intger doesn't work if more than 1 decimal place: %i \n",(intger - 48));

    free(stringBuffer);
    return(0);
    }
~                                                                                                                                          
~      

I do realize I could 1.cast the char as int & convert from ASCII to real number 2.multiplier each (now int) by is decimal place (determined by array position) 3.add ints together for example (warning this code is kinda ugly, I haven't look twice at it yet and is just a test so far)

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

    #define SIZE 500

    int main(void)
    {
    FILE* pfile;
    pfile = fopen("/tmp/code","r");                                            

    char *stringBuffer = (char *)malloc(SIZE * sizeof(char));                 

    char ch;
    int i = 0;
    ch = getc(pfile);                                                         
    while(ch != EOF)                                                          
    {
        stringBuffer[i] = ch;
        ch = getc(pfile);
        i++;
    }

    fclose(pfile);

    int stringSize = (int)(sizeof(stringBuffer)/sizeof(char));
    stringBuffer = (char *)realloc(stringBuffer,(stringSize * sizeof(char)));

    printf("the string works: %s \n",stringBuffer);
    int multi;
    int sum;

   for(int x =0; x < stringSize; x++)
   {
      int intger = ((int)stringBuffer[((stringSize - 1) - x)] - 48);

      if( x != 0 )
      {
        multi = (int)pow(10,x);
        sum += ( multi * intger );
      }
      else
        sum += intger;
    }
    printf("the int works: %i \n",sum);
    free(stringBuffer);
    return(0);
    }

but still casting as string as int would be nice(I assume c++ has this?).

Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • 1
    [Please see this discussion on why not to cast the return value of `malloc()` and family in `C`.](http://stackoverflow.com/q/605845/2173917). – Sourav Ghosh Apr 17 '17 at 06:34
  • 3
    atoi is a standard library function that probably does what you want? – nneonneo Apr 17 '17 at 06:35
  • `(int)*stringBuffer` dereferences just the first character in the string and promotes it to an int. If you want the first 4 characters (or whatever your `sizeof(int)` is) to be converted to a single integer is you can do `*(int*)stringBuffer` But I am not sure if that is what you want. Do you want to convert the decimal string to an integer? – Ajay Brahmakshatriya Apr 17 '17 at 06:50
  • `atoi()` is in `stdlib.h`. This is probably what you want as nneonneo says – J...S Apr 17 '17 at 07:47
  • 1
    @AjayBrahmakshatriya except, you can't, aliasing violation, alignment error and whatnot. – Antti Haapala -- Слава Україні Apr 17 '17 at 08:07
  • @AnttiHaapala Yes, I was trying to understand what he is trying to do. If he wants decimal string to integer conversion atoi is the way to go. If he has a 4 byte integer's binary data in the file, he would have to do what I said. Question is very unclear to me. – Ajay Brahmakshatriya Apr 17 '17 at 08:51
  • 2
    @AjayBrahmakshatriya *If you want the first 4 characters (or whatever your sizeof(int) is) to be converted to a single integer is you can do `*(int*)stringBuffer`* That violates strict aliasing. You *can not* safely treat a `char *` as an `int *`. Do that on a system that has actual alignment restrictions on things like `int` and your program will likely fail with a `SIGBUS` or similar. – Andrew Henle Apr 17 '17 at 09:08
  • 1
    @AndrewHenle Fine, will have to do it through a Union of char[sizeof(int)] and int then. That should be fine because the entire Union will be aligned to the same alignment as that of int and that would be a correct type punning. – Ajay Brahmakshatriya Apr 17 '17 at 09:10

2 Answers2

0

It does not work the way you expect.

==> In case of a statement like

  int intger = (int)stringBuffer;

Casting a "string" (or, the pointer to the first element of the char array) to int is highly implementation defined behaviour and if not properly supported by the implementation, will cause undefined behaviour.

==> OTOH, a statement like

 int intger = (int)*stringBuffer; 

is an attempt to dereference the first memory location pointed by stringBuffer and then cast that value to int (which would have been done implicitly anyway). This does not convert the whole string content to an integer type. That is why you see something like

the integer doesn't work if more than 1 decimal place: % [......]

Solution: From your problem statement, looks like you can make use of strtol() or variants. You need to read a whole line with fgets() or similar and then, (after parsing, if required) pass that to strtol() to convert to a long int.

After that, notes about your code:

  • In while(ch != EOF) loop body, you have an uncontrolled iteration with i, it may lead to out of bound memory access.
  • int stringSize = (int)(sizeof(stringBuffer)/sizeof(char)); is not going to give you the string size, you need to null-terminate the string and use strlen() to get the length of the string.

That said, some of general comments:

Community
  • 1
  • 1
Sourav Ghosh
  • 133,132
  • 16
  • 183
  • 261
  • Cool, thanks for the DV, guess I can then ask for a comment also to improve the post? – Sourav Ghosh Apr 17 '17 at 06:39
  • 1
    I am surprised to see two downvotes for this answer? – Thomas Padron-McCarthy Apr 17 '17 at 06:46
  • @ThomasPadron-McCarthy many people losing their keys, I guess. :) – Sourav Ghosh Apr 17 '17 at 06:47
  • lol wish i read this a hour ago I've been trying to figure out what was going on with my EOF, thanks! I don't see how I "have an uncontrolled iteration with i" can you please clarify thanks a ton. Yeah strtol(), or the fscanf() mentioned above should work fine defiantly very over complicated, but I have to learn the stdlib some how! – jhony thompson Apr 17 '17 at 08:37
  • @jhonythompson regarding the uncontrolled iteration, look at the indexing. You have statically allocated `500` bytes of memory, but you pu no bounds on the value of `i`. For some input, it is quite possible that there's no `EOF` till index `499` and then, the value of `i` will be increased to `500` and that index would cause the out of bound access. – Sourav Ghosh Apr 17 '17 at 08:46
  • *defiantly very over complicated*, that is the correct way of doing it. So I guess we are stuck with that. – Ajay Brahmakshatriya Apr 17 '17 at 09:13
0

In the case of your example, you could simplify the whole code using the fscanf function.

FILE* pfile;
pfile = fopen("/tmp/code","r");

int intger;
fscanf(pfile, "%i", &intger);

fclose(pfile);

If you need both the string and the integer, you can use the sscanf function in the same way, or the strtol function.

Matt
  • 7,100
  • 3
  • 28
  • 58