Передача структуры по ссылке вместо значения в пустых функциях - PullRequest
0 голосов
/ 04 июля 2018

Я пытаюсь создать список контактов, используя структуры и функции. В настоящее время мой код компилируется, но члены структуры не изменяются вне функции, как я пытаюсь сделать. Вот мой код (удалены некоторые строки по длине)

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

struct ContactInfo
{
    char fname[50];
    char lname[50];
};

struct ContactInfo gc;

void getContactInfo(struct ContactInfo gc)
{
    printf("First Name: ");
    scanf("%s", gc.fname);

    printf("\nLast Name: ");
    scanf("%s", gc.lname);
}

void showContactInfo(struct ContactInfo gc)
{
    printf("* First Name: %s \n", gc.fname);

    printf("* Last Name: %s \n", gc.lname);
}

int main()
{
    getContactInfo(gc);

    showContactInfo(gc);

    return 0;
}

Ответы [ 3 ]

0 голосов
/ 04 июля 2018

Функция getContactInfo должна возвращать значения, но вместо этого вы передаете значения.

Самый естественный способ получить данные из функции - использовать возвращаемое значение. Также не следует использовать глобальные переменные для передачи данных. Код может выглядеть так:

struct ContactInfo getContactInfo(void)
{
    struct ContactInfo g = { 0 };  // ensure no garbage in case input fails

    printf("First Name: ");
    scanf("%49s", g.fname);

    printf("Last Name: ");
    scanf("%49s", g.lname);

    return g;
}

с кодом в main:

struct ContactInfo gc = getContactInfo();
showContactInfo(gc);
0 голосов
/ 04 июля 2018

Для getContactInfo необходимо передать указатель на структуру:

void getContactInfo( struct ContactInfo *gcptr )
{
  printf("First Name: ");
  scanf("%s", gcptr->fname);

  printf("\nLast Name: ");
  scanf("%s", gcptr->lname);
}

Поскольку вы пытаетесь изменить содержимое gc, вам нужно передать указатель на него в функцию. Помните, что C передает все аргументы по значению, поэтому вызываемая функция создает отдельный дубликат объекта, который получает значение параметра. Ваш код модифицирует этот дубликат объекта, который не влияет на фактический параметр.

Оператор -> используется, когда операндом является указатель на тип struct или union - он неявно разыменовывает указатель перед доступом к конкретному члену. Это эквивалентно написанию (*gcptr).fname и (*gcptr).lname, хотя и немного проще для глаз.

Вы бы назвали эту функцию как

getContactInfo( &gc );

Для showContactInfo вы можете оставить все как есть, поскольку вы не пытаетесь изменить параметр. Однако многим людям нравится передавать указатели на struct s для экономии памяти (вы не создаете копию struct в вызываемой функции). Если вы хотите использовать указатель, я бы рекомендовал использовать ключевое слово const, например:

void showContactInfo( const struct ContactInfo *gcptr )
{
  printf("* First Name: %s \n", gcptr->fname);
  printf("* Last Name: %s \n", gcptr->lname);
}

Ключевое слово const указывает компилятору на меня кричать, если я пытаюсь изменить содержимое объекта, на который указывает gcptr в функции showContactInfo. Как и getContactInfo выше, вы бы назвали его

showContactInfo( &gc );

Обратите внимание, что я изменил имена аргументов на gcptr только для того, чтобы отличить формальный аргумент в определении функции от фактического аргумента в вызове функции. Обычно я не люблю помещать какую-либо информацию о типе в имя переменной или аргумента, но вы можете использовать любое соглашение о присвоении имен, которое вам нравится.

0 голосов
/ 04 июля 2018

C-способ сделать это - просто старые указатели:

void showContactInfo(struct ContactInfo* gc)
{
    printf("* First Name: %s \n", gc->fname);

    printf("* Last Name: %s \n", gc->lname);
}

Кроме необходимости использовать оператор стрелки -> для доступа к свойствам, в основном это то же самое.

Сам C не имеет ссылок, как в C ++.

...