Thread: Can't Return/Assign Char Pointer

  1. #1
    Registered User
    Join Date
    Nov 2007
    Posts
    26

    Can't Return/Assign Char Pointer

    Hey Folks,

    I'm getting an "incompatible types in assignment" error and warning as well as a "return makes pointer from integer without cast" warning. Yes, I'm a newb. I've been reading the tutorials here and on other sites as well as K & R but I still haven't been able to get this code straigtened out. I want to return the contents of the pointer to char array from each call to get_input to the specified part of the structure in input (). Thanks for reading.

    Code:
    contact input ();
    char* get_input (char[26], int);
    Code:
    contact input ()                                                /* gets an entry from the user */
    {
         contact entry = {'\0','\0','\0','\0','\0','\0','\0','\0'}; /* initializes the structure   */
         char prompt1[26] = "Please enter a new name.";
         char prompt2[26] = "Enter a street address.";
         char prompt3[26] = "Enter a city.";
         char prompt4[26] = "Enter a province.";
         char prompt5[26] = "Enter a post code.";
         char prompt6[26] = "Enter a country.";
         char prompt7[26] = "Enter a date of birth.";
         char prompt8[26] = "Enter a phone number.";
         char prompt9[26] = "Enter an email address.";
    
         entry.name = get_input (prompt1, 50);
         entry.add.street = get_input (prompt2, 50);
         entry.add.city = get_input (prompt3, 50);
         entry.add.state = get_input (prompt4, 50);
         entry.add.post = get_input (prompt5, 50);
         entry.add.country = get_input (prompt6, 50);
         entry.birth = get_input (prompt7, 50);
         entry.phone = get_input (prompt8, 50);
         entry.email = get_input (prompt9, 50);
         
         return (entry);
    }    
    
    char *get_input (char prompt[26], int size)
    {
         char string [50];
         char *pointer;
         pointer = &string;
         char junk = 0;
         int length;
         
                    do{
                    printf ("\n%s\n\n>", prompt);
                    fgets(string, sizeof(string), stdin);   
                        if ( strchr(string, '\n') == NULL ){         /* if overflow */
                        printf ("\nYour entry is too long, please try again.\a");
                        while((junk = getchar()) != '\n' && junk != EOF);
                        string[0] = '\0';
                        }
                    } while (string[0] == '\0' || string[0] == '\n');
         length = strlen (string);             
         if (string[length - 1] == '\n'){
             string[length - 1] == '\0';}                            /* replace \n  */
         return *pointer;
    }
    Last edited by SiliconHobo; 12-12-2007 at 07:24 PM.

  2. #2
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    You define char *pointer, which means *pointer is a char. So when you return *pointer, you return a char. (To return a char *, you need to return pointer itself.) However! The pointer you return won't be valid, since it points to memory allocated to string[50] (which doesn't exist any more, once the function ends). If you want the memory to persist, you can malloc() it. (You just have to remember to free() it once you have finished using that string.)
    Last edited by tabstop; 12-12-2007 at 07:37 PM. Reason: tried (probably in vain) to be clearer

  3. #3
    Registered User
    Join Date
    Nov 2007
    Posts
    26
    Okay, thanks. Just to make sure I have this straight, malloc assigned variables persist globally until freed?

    I've added this line to the initialization of get_input:
    Code:
    pointer = (char*) malloc(sizeof(string));
    and changed it's return value from *pointer to pointer but I'm still getting the incompatible type error. Also, where should I put the free? Is it a problem to have pointer malloced with each call to get_input and only freed once after the last call to get_input? Or perhaps I should malloc and free it only once or malloc and free it with each call to the function? Thank you for clarifying the use of this important function (malloc).
    Last edited by SiliconHobo; 12-12-2007 at 08:01 PM.

  4. #4
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    The incompatible type is pointer = &string? It should just be pointer = string (since string, by itself, is also a pointer to char). And if you're malloc'ing pointer, you don't need string[50] anyway anymore.

    You need to have one free() for every malloc(). I can't quite see what's going on with your struct, so I can't say for sure what will be best. This is my advice based on the assumption that entry.whatever is a char * (otherwise those assignment operators aren't working either):

    1. get_entry malloc's some space and returns it through pointer. This pointer is then assigned to entry.whatever, so entry is now in charge of that memory area.
    2. You will have repeated malloc's on the same pointer name, but since each pointer gets reassigned to its permanent variable, that's ok.
    3. When entry dies, you first need to free all the entry.whatever's.

    If I'm wrong about your struct, then this will have to be adjusted.

  5. #5
    Registered User
    Join Date
    Nov 2007
    Posts
    26
    Hmmm, the structure components are all char arrays so I tried this in input:

    Code:
    char *string;
    Code:
         string = get_input (prompt1, 50);
                entry.name = *string;
                free (string);
         string = get_input (prompt2, 50);
                entry.add.street = *string;
                free (string);
    etc.

    with and without the pointer = &string line in get_input I'm still getting these pesky assignment type errors. I don't see why this isn't working... I'm assigning the returned char pointer to a variable and then assigning the contents to the structure component which is a char array. Should it be a pointer to a pointer or something?

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    You cannot assign array

    Use strcpy to copy C-strings.

    Do not return pointer to the local variable
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    As mentioned, you cannot assign a char * to a char[]. If all your entry.whatever's are char[], then you will have to use strncpy and friends to get the data into that array.

    OR, you could pass the name entry.whatever into your getInput! You're already passing the size (50) into the function, so pass the character array in as well and fgets right in to it. No string[50], no pointer, no returning necessary.

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    getInput should most likely take a buffer as parameter.
    Then you can use strcpy to copy your local string into the buffer at the end of the function.
    Usually, all functions like these take a buffer for the reason that the calling function can decide what type of buffer to pass and you do not have to allocate memory on the heap which needs to be freed later.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  9. #9
    Registered User
    Join Date
    Nov 2007
    Posts
    26
    Yeah, my original version passed the structure but I couldn't figure out how to pass different pieces of the structure without writing a different version of get_input for each array in the structure. How can I pass a part of a structure in like entry.name, entry.add.street etc. I tried:

    delcaration
    Code:
    contact get_input (char[26], contact);
    call
    Code:
    get_input (prompt1, entry.name);
    function
    Code:
    contact get_input (char prompt[26], contact string)
    .......
    return (string);
    but something's still not quite right. Do I pass one array from the structure with each call or pass the whole array each time and add another parameter to somehow tell fgets which array to write to? I'll be really happy when I get this working. Thanks you!!!

  10. #10
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    But entry.name is not a contact, it's a char[]. So your function needs to be prepared to accept such a thing.

    I should think you would want to call your function as
    Code:
    get_input(prompt1, entry.name);
    which means your prototype would be
    Code:
    void get_input(char prompt[], char result[])
    (Notice that you're not using a return value of get_input, so you don't have to return anything.) Then your fgets just needs to write into result.

  11. #11
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    You can also just pass along the entire struct and the function decides what to do with it. It might also be a better choice in the end in case your function needs to access or change some other members.
    Code:
    void get_input(struct* mystruct);
    Also note that you do not have to do this:
    Code:
         char string [50];
         char *pointer;
         pointer = &string;
    (Which btw, is wrong because &string is char** and pointer is char*).
    Instead, you can just do string (no & before since this is an array - it automatically gets converted to char* whenever you type its name) wherever you need to get the address of the array.
    Last edited by Elysia; 12-14-2007 at 05:05 AM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  12. #12
    Registered User
    Join Date
    Nov 2007
    Posts
    26
    Sweet. Thanks for your help and patience everyone! I finally have it working with the following code:

    Code:
    void input ()                                                   /* gets an entry from the user */
    {
         contact entry = {'\0','\0','\0','\0','\0','\0','\0','\0'}; /* initializes the structure   */
         char prompt1[26] = "Please enter a new name.";
         char prompt2[25] = "Enter a street address.";
         char prompt3[14] = "Enter a city.";
         char prompt4[18] = "Enter a province.";
         char prompt5[19] = "Enter a post code.";
         char prompt6[17] = "Enter a country.";
         char prompt7[23] = "Enter a date of birth.";
         char prompt8[22] = "Enter a phone number.";
         char prompt9[24] = "Enter an email address.";
    
         get_input (prompt1, entry.name, sizeof(entry.name));
         get_input (prompt2, entry.add.street, sizeof(entry.add.street));
         get_input (prompt3, entry.add.city, sizeof(entry.add.city));
         get_input (prompt4, entry.add.state, sizeof(entry.add.state));
         get_input (prompt5, entry.add.post, sizeof(entry.add.post));
         get_input (prompt6, entry.add.country, sizeof(entry.add.country));
         get_input (prompt7, entry.birth, sizeof(entry.birth));
         get_input (prompt8, entry.phone, sizeof(entry.phone));
         get_input (prompt9, entry.email, sizeof(entry.email));
    
         
         save_entry (entry);
    }    
    
    int get_input (char prompt[], char string[], int size)
    { 
         char *fgets_ptr;
         char junk = 0;
         int length;
          
                    do{
                    printf ("\n%s\n>", prompt);
                    fgets(string, size, stdin);
                    if (fgets_ptr==NULL) return -1 ;   
                        if ( strchr(string, '\n') == NULL ){         /* if overflow */
                        printf ("\nYour entry is too long, please try again.\a");
                        while((junk = getchar()) != '\n' && junk != EOF);
                        string[0] = '\0';
                        }
                    } while (string[0] == '\0' || string[0] == '\n');
         length = strlen(string);             
         if (string[length - 1] == '\n'){
             string[length - 1] = '\0';}                             /* replace \n  */
    }

  13. #13
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Code:
    Warning	11	warning C4715: 'get_input' : not all control paths return a value	63
    Warning	12	warning C4700: uninitialized local variable 'fgets_ptr' used	53
    You have bugs.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  14. #14
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Code:
        char *fgets_ptr;
         char junk = 0;
         int length;
          
                    do{
                    printf ("\n%s\n>", prompt);
                    fgets(string, size, stdin);
                    if (fgets_ptr==NULL) return -1 ;
    fgets_ptr should, presumably be the output of fgets(), rather than undefined like it is now.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  15. #15
    Registered User
    Join Date
    Nov 2007
    Posts
    26
    Code:
    fgets_ptr = fgets(string, size, stdin);
    Thanks. And what's that other warning about return path? What compiler are you using Elysia? It compiled clean in DevC++ 4.9.9.2.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. sorting number
    By Leslie in forum C Programming
    Replies: 8
    Last Post: 05-20-2009, 04:23 AM
  2. Direct3D problem
    By cboard_member in forum Game Programming
    Replies: 10
    Last Post: 04-09-2006, 03:36 AM
  3. Could somebody please help me with this C program
    By brett73 in forum C Programming
    Replies: 6
    Last Post: 11-25-2004, 02:19 AM
  4. towers of hanoi problem
    By aik_21 in forum C Programming
    Replies: 1
    Last Post: 10-02-2004, 01:34 PM
  5. Half-life SDK, where are the constants?
    By bennyandthejets in forum Game Programming
    Replies: 29
    Last Post: 08-25-2003, 11:58 AM