3

I am trying to print the integer value of each character in a given string using a function. When I pass a string to this function, it converts each character in the given string to an integer and then saves it to a result array. I have also created an array of pointers which will hold the address of each character's corresponding integer. But when I return this array of pointers, I am not able to print all integer values correctly.

#include <stdio.h>
int *c2i(char *str); 

int main(){

    char s[20];
    int *p, i;
    printf("Enter your string:\n");
    scanf("%s", s);
    p=c2i(s);
    for(i=0; i<4; i++){
        printf("\n%d\t%d\n", *p, p);
        p++;
    }

    return 0;
}

int *c2i(char *str){

    int i=0, result[20], *ptr[20];

    while(*(str+i)!='\0'){
        result[i]=*(str+i) & 0xff;
        ptr[i]=&result[i];
        i++;
    }
    printf("%d %d %d %d %d %d %d %d", *ptr[0], *ptr[1], *ptr[2], *ptr[3], ptr[0], ptr[1], ptr[2], ptr[3]);

    return *ptr;
}

I have included many printf statements just for debugging purposes. The output of the program when I try to run the code above is:

Enter your string:

abcd

97 98 99 100 6356588 6356592 6356596 6356600

97 6356588

1999382056 6356592

20 6356596

1 6356600

I am only getting the first value correctly when I print it in the main() function. When I increment the pointer and try to print the next values, I am getting garbage results. I can see that the address is the same but the values have been corrupted. What am I doing wrong here?

Chris Frederick
  • 5,482
  • 3
  • 36
  • 44
Karna
  • 55
  • 1
  • 10
  • 1
    You can't return arrays from functions in C, but this code does not even attempt that; here `ptr[0]` is returned, which is a pointer to a local variable. The lifetime of the local variable has ended after the function has returned.... – ad absurdum Nov 01 '17 at 15:12
  • Can this problem be solved using static integer pointer variable and returning ptr instead of *ptr? – Karna Nov 01 '17 at 15:29
  • What is your expected output? – theGleep Nov 01 '17 at 15:30
  • @SrihariRaoM -- probably, but that is not ideal; better to either pass an array from the caller into the function, or dynamically allocate within the function. You could also wrap `ptr[]` in a `struct` and return that, since `struct`s can be returned from functions. – ad absurdum Nov 01 '17 at 15:33
  • Possible duplicate of [Returning an array using C](https://stackoverflow.com/questions/11656532/returning-an-array-using-c) – Bo Persson Nov 01 '17 at 15:52

3 Answers3

3

You can't return the stack-allocated array since once the function call finishes, it is no longer marked in use. Instead, you should malloc the array, for example int *ptr = malloc(sizeof(int)*20);. Also remember to free the array when done with it (it's good practice). See these posts for details

Returning an array using C

returning a local variable from function in C

information_interchange
  • 2,538
  • 6
  • 31
  • 49
2

How about this

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

#define MAXLEN 20

void c2i(char *str, int *out, int len); 

int main(){

    char s[MAXLEN];
    int  out[MAXLEN];
    int *p, i;

    printf("Enter your string:\n");
    /* fgets safer that scanf, 
      protects buffer overrun */
    fgets(s, sizeof(s), stdin);
    /* fgets gives you the newline char though, 
      so remove it */
    if(s[strlen(s)-1] == '\n') {
        s[strlen(s)-1] = '\0';
    }

    c2i(s,out,strlen(s));
    for(i=0; i<strlen(s); i++){
        printf("%d\n", out[i]);
    }

    return 0;
}

void c2i(char *str, int *out, int len){

    int i=0;

    for(i=0; i<len; i++)
    {
        out[i]=*(str+i) & 0xff;
    }
}

Passing the out buffer to c2i means you don't need to malloc/free a buffer, but this is probably just a matter of taste.

Using fgets means rather than scanf means you're protected from buffer overruns and your strings can have spaces in them too.

Luke Smith
  • 893
  • 4
  • 8
2
#include <stdio.h>

int** c2i(char *str) {

    int i=0, *result, **ptr;
    result = (int *)malloc(20*sizeof(int)) ;
    ptr = (int **)malloc(10*sizeof(int *)) ;

    while(*(str+i)!='\0'){
        result[i]=*(str+i) & 0xff;
        ptr[i]=&result[i];
        i++;
    }
    printf("%d %d %d %d %p %p %p %p", *ptr[0], *ptr[1], *ptr[2], *ptr[3], ptr[0], ptr[1], ptr[2], ptr[3]);

    return ptr;
}
int main(){

    char s[20];
    int **p, i;
    printf("Enter your string:\n");
    scanf("%s", s);
    p=c2i(s);
    for(i=0; i<4; i++){
        printf("\n%d\t%p\n", **p, *p);
        p++;
    }

    return 0;
}

double-pointer might solve your issue, look at your modified code..this gives you the desired result.here i'm attaching the screen shot of execution..enter image description here

Srikanth Chekuri
  • 1,944
  • 1
  • 9
  • 19
  • Your program is logically wrong. `result[20]` array is a local variable of function `c2i()` and you are storing the address of its elements in `ptr[i]` and returning ptr and in `main()`, reading the content of a local variable address in it. You are lucky that It's working somehow but this is undefined behavior. – H.S. Nov 01 '17 at 16:09
  • @H.S. yes result array should also be created using malloc . edited – Srikanth Chekuri Nov 01 '17 at 16:12
  • Still, there are issues in your program. In this statement - `ptr = (int *)malloc(10*sizeof(int *)) ;` you are typecasting malloc return to `(int *)` but `ptr` is of type `int **`. Moreover, you should not typecast the malloc result. – H.S. Nov 01 '17 at 16:16
  • @srikanth_16 I copy pasted your code and tried to execute the same but I am not getting the output that you have got. – Karna Nov 01 '17 at 16:24
  • here is the link to ideone. seems it is working fine. https://ideone.com/YHGgmX . let me now what is the problem you are having ?? – Srikanth Chekuri Nov 01 '17 at 16:26
  • @srikanth_16 after creating result array using malloc I am getting the expected output. Again thanks for helping man. – Karna Nov 01 '17 at 16:33