Передать строку в структуре функции и вернуть ее - PullRequest
2 голосов
/ 30 марта 2020

Я хочу вернуть название самого маленького города по населению, если это второй город. (Пожалуйста, не возражайте против оператора if, я знаю, что он мягкий), меня беспокоит пропущенный возврат.

Я предполагаю, что должен объявить указатель внутри функции rSmallestCity, как *rtrn, но я угадайте, что исходная переменная уничтожена перед ее использованием?

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));
}

предупреждение: присвоение 'char ' из несовместимого типа указателя 'char () [20]' [- Wincompatible-pointer-types] |

Ответы [ 3 ]

2 голосов
/ 30 марта 2020

Я предполагаю, что должен объявить указатель внутри функции rSmallestCity, как * rtrn, но я предполагаю, что исходная переменная уничтожается перед использованием?

Хороший вопрос. И ваше предположение верно. Создание переменной внутри функции, ее существование заканчивается после выхода из функции. Но в этом случае, поскольку член структуры name уже является char *, вам не нужно создавать другую переменную. Просто верните c1.name. (см. пример кода ниже.)

Несколько других предложений:

В объявлении структуры:

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

Вы использовали тот же символ (Coordinate) для имени структуры и для ее typedef. Это не очень хорошая практика. Если вам нужно как имя структуры , так и typedef, выберите разные символы. Кстати, в этом примере нужен только один или другой. Скажем, вы выбрали typedef, тогда структура полностью определяется следующим образом:

typedef struct {
    int x,y;
}Coordinate;

Это предложение относится к обоим объявлениям struct в вашем примере кода.

Сигнатуры для функции main не включают int main(){...}, а
int main(void){..., return 0;} и int main(int argc, char *argv[]){..., return 0;}

В следующем примере кода показаны некоторые другие предложения по улучшению комментарии под вашим постом,

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;
};
2 голосов
/ 30 марта 2020

Решение, которое я первоначально оставил в комментарии под OP (уберите & в строке &cl[n-1]->name;), требует некоторых объяснений, чтобы избежать проблем позже.

(Это образовательный ответ, а не полный ответ на указатели, распад массива, ... И много примеров можно найти в stackoverflow. Я попытался упростить)

Попробуйте этот простой код.

int main()
{
    char myString1[25]="Toulouse" ; // French City
    printf("%p\n",myString1);
    printf("%p\n",&myString1);
}

Вывод такой же, но имя массива и адрес имени массива не совпадают. Имя массива оценивается по адресу его первого элемента. Так что это работает в вашем случае, но во время компиляции выдается предупреждение, и это очень важно. Во-первых, не удаляйте предупреждения компиляции.

Теперь попробуйте этот код:

int main()
{
    char myString1[25]="Toulouse" ; // French City
    printf("%p\n",myString1+1);
    printf("%p\n",&myString1+1);
}

Выходы разные. Потому что myString1 оценивается в char* и &myString1 в char [25]. Таким образом, +1 в первом случае добавляет один (sizeof char) к указателю, а в другом случае добавляет 25.

1 голос
/ 30 марта 2020

Удалите «&» в строке: rtrn = &cl[n-1]->name;

Чтобы упростить задачу, вы присвоили «адрес char[]» для char*, но синтаксис массива делает его работающим независимо.

...