Доступ к переменным в структурах C - PullRequest
1 голос
/ 16 ноября 2009

Я не слишком знаком с программированием на C, и мне нужно сделать несколько модификаций исходного кода, вот проблема:
У меня есть это в заголовочном файле:

<i>typedef struct</i> <b>word</b> {
  long    wnum;
  float   weight;
} <b>WORD</b>;</p>

<p><i>typedef struct</i> <b>svector</b> {
  WORD  *words;
  double  norm;
} SVECTOR;
В моем файле .c у меня есть такая функция, как
double function(SVECTOR *a, SVECTOR *b){

}

что я должен сделать в своей функции для доступа к переменным wnum и weight ???
Заранее спасибо;)

Ответы [ 6 ]

4 голосов
/ 16 ноября 2009

Вы проходите мимо:

a->words->wnum
a->words->weight

Или:

a->words[SUBINDEX].wnum
a->words[SUBINDEX].weight

В зависимости от того, что вы получаете в качестве фактических параметров для вашей функции.

  1. Если вы получаете указатель на один элемент SVECTOR, вы можете использовать первый подход.
  2. С другой стороны, если вы получите указатель на элементы сервера SVECTOR, вам может показаться, что второй подход более удобен.
4 голосов
/ 16 ноября 2009

Обязательно проверьте нулевые указатели, но в целом это будет:

a->words->wnum
a->words->weight

Потому что это называется словами, это звучит так, как будто это массив (проверьте код, чтобы убедиться). Скорее всего, вам придется перебрать массив. Если вы можете показать больше кода или указать на некоторую документацию, мы могли бы выяснить, какой размер у этого массива.

for( unsigned int t = 0; t < [SIZE OF words ARRAY]; ++t )
{
   a->words[t].wnum;
   a->words[t].weight;
}
2 голосов
/ 16 ноября 2009

Судя по именам SVECTOR и словам, похоже, что вы имеете дело с массивами. Вот несколько вариантов:

/**
 * a and words are meant to be treated as arrays
 */
a[i].words[j].wnum = ...;
a[i].words[j].weight = ...;
/**
 * a is treated as an array, words is not
 */
a[i].words->wnum = ...;
a[i].words->weight = ...;
/**
 * a is not treated as an array, words is
 */
a->words[j].wnum = ...;
a->words[j].weight = ...;
/**
 * a and words are not treated as arrays
 */
a->words->wnum = ...;
a->words->weight = ...;

Так зачем использовать ., когда мы применяем индекс, и ->, когда мы этого не делаем? Прежде всего, помните, что вы используете -> при доступе к членам структуры через указатель и . при доступе к членам через экземпляр структуры. Операция индексации массива определяется как a[i] == *(a + i); акт подписки эффективно разыменовывает указатель. Таким образом, тип words равен struct word * (указатель на слово структуры), а тип words[i] равен struct word. Таким образом, нам нужно будет использовать -> для первого и . для второго. То же самое относится и к a и b.

IF a, b или words должны рассматриваться как массивы, их размер должен быть где-то известен.

2 голосов
/ 16 ноября 2009

a->words->wnum

-> оба разыменовывают указатель и позволяют ссылаться на поле структуры.

1 голос
/ 16 ноября 2009

Редактировать : (добавлено words, я упустил тот факт, что были две вложенные структуры, в моем стремлении объяснить различные операторы разграничения ...)
то есть оригинальный ответ был похож на some_long_var = a->wNum;, что, конечно, неправильно ...

2-я попытка; -)

some_long_var = a->words->wNum;
//  or
some_float_var = a->words->weight;

должен сделать трюк.

Так как a и b являются указателями, их необходимо сначала разыменовать, прежде чем их члены смогут получить доступ. Оператор -> делает обе вещи одновременно.

В качестве альтернативы вы можете сделать что-то вроде

some_long_var = a[0].words->wNum;

(или, возможно, со значением чем 0 в качестве нижнего индекса, если вы ожидаете, что a будет массивом). Дело в том, что в C, массивы часто «видны» как указатели на тип элемента, найденного в массиве , и поэтому оператор массива [] может быть функционально и часто семантически правильным способом разыменования указатель.

Наконец, но это более хитроумно (но полезно для углубления понимания семантики различных операторов c), вы можете сделать это в два шага, при этом оператор * выполняет разыменование, а оператор-член (.) Получает желаемый член структуры / класса:

some_long_var = (*a).words->wNum;
0 голосов
/ 16 ноября 2009

У вас есть указатель на тип, определенный WORD, поэтому:

a->words->(member)

Если у вас просто был элемент без указателя, вы должны сделать:

a->words.(member) 
...