Search code examples
cstringstructreturn-type

Pass a string in a struct to a function and return it


I want to return the name of the smallest city population-wise, if it is the second city. (Please don't mind the if statement, I know it's bland), the missing return is what bothers me.

I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?

typedef struct Coordinate{
    int x,y;
}Coordinate;

typedef struct city{
    char name[20];
    int population;
    Coordinate coordinates;
}city;

char *rSmallestCity(city **cl, int n)
{
     char *rtrn = NULL;
     if(cl[n-2]->population>cl[n-1]->population)
     {
         rtrn = &cl[n-1]->name;
     }
     return rtrn;
}

int main()
{
    city c1 ={.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4};
    city c2 ={.name="Delhi", .population=300, .coordinates.x=3, .coordinates.y=2};
    city *clist[2];
    clist[0]=&c1;
    clist[1]=&c2;
    printf("\n%s is smallest\n",rSmallestCity(clist,2));
}

warning: assignment to 'char ' from incompatible pointer type 'char ()[20]' [-Wincompatible-pointer-types]|


Solution

  • I assume I should declare a pointer inside the function rSmallestCity, like *rtrn but I guess the source variable is destroyed before it is used?

    A good question. And your assumption is correct. Creating a variable inside a function it's existence ends upon leaving the function. But in this case, because the struct member name is already a char * you do not need to create another variable. Just return c1.name. (see code example below.)

    A few other suggestions:

    In the struct declaration:

    typedef struct Coordinate{
        int x,y;
    }Coordinate;
    

    You've used the same symbol (Coordinate) for the struct name, and for it's typedef. This is not a good practice. If you need both a struct name and a typedef, pick different symbols. BTW, in this this example, only one or the other is needed. Say you pick the typedef, then the struct is completely defined by:

    typedef struct {
        int x,y;
    }Coordinate;
    

    That suggestion applies to both struct declarations in your example code.

    The signatures for the main function do not include int main(){...} rather
    int main(void){..., return 0;} and int main(int argc, char *argv[]){..., return 0;}

    The following code example illustrates some of the other suggestions for improvements in comments under your post,

    typedef struct {
        int x,y;
    }Coordinate;
    
    typedef struct {
        char name[20];
        int population;
        Coordinate coordinates;
    }city;
    
    //return char * rather than char to allow for full null terminated char array (string)
    char * rSmallestCity(city c1[],int cityCount)//generisize function prototype to 
    {                                            //to easily accommodate bigger arrays if needed
        long long size, sizeKeep = 8e9; //index and population. initialize larger than possible population
        int indexKeep = 0;
        //note you do not need to define a char *, the struct already contains one
    
        for(int i=0; i<cityCount; i++)//use a loop rather than a single comparison, keep the smalles
        {
            size = c1[i].population; 
            sizeKeep = (size < sizeKeep) ? indexKeep = i, size  : sizeKeep;
        }
    
        printf("\n%s\n",c1[indexKeep].name);
        return c1[indexKeep].name;
    };
    
    int main(void)//use minimum signature for main, and call return before leaving.
    {
            //combining your original declarations and assignments for struct
            //into a single declaration/definition.
            city c1[] = {{.name="Mumbai", .population=310, .coordinates.x=3, .coordinates.y=4},
                        {.name="Delhi",  .population=300, .coordinates.x=3, .coordinates.y=2}};
            int cityCount = sizeof(c1)/sizeof(c1[0]);
    
            printf("\n%s is smallest",rSmallestCity(c1, cityCount));
    
            return 0;
    };