Обращаясь к данным как по имени, так и по номеру в C - PullRequest
1 голос
/ 10 ноября 2009

У меня есть двадцать или около того целых чисел, на которые я хочу ссылаться по имени, когда они задаются, но я также хотел бы иметь возможность ссылаться на них по номеру, как они были в массиве, поэтому я могу распечатайте их один за другим, используя цикл for. Любые идеи, как кодировать это в C? Вот что я говорю в псевдокоде:

/* a data structure to keep a count of each make of car I own */
my_cars;

/* set the counts */
my_cars.saabs = 2;
my_cars.hondas = 3;
my_cars.porsches = 0;

/* print the counts */
for(all i in my_cars) {
    print my_cars[i];
}

Это слишком много требует языка низкого уровня, как C?

Ответы [ 8 ]

7 голосов
/ 10 ноября 2009
struct car {
    const char *name;
    int count;
} my_cars[] = {{"Saab", 2}, {"Honda", 3}, {"Porsche", 0}};
int i;
for (i = 0; i < sizeof(my_cars) / sizeof(my_cars[0]); i++)
    printf("%s: %d\n", my_cars[i].name, my_cars[i].count);
6 голосов
/ 10 ноября 2009

Для этого вы должны использовать массив вместо отдельных полей данных

#include <stdio.h>

typedef enum CarType {
  CART_SAAB,
  CART_HONDA,
  CART_PORSHE,

  CART_COUNT_
} CarType;

typedef struct MyCars {
  unsigned ncars[CART_COUNT_];
} MyCars;

int main(void)
{
  MyCars my_cars = { 0 } ;
  unsigned i;

  my_cars.ncars[CART_SAAB] = 2;
  my_cars.ncars[CART_HONDA] = 3;

  for (i = 0; i < CART_COUNT_; ++i)
    printf("%u\n", my_cars.ncars[i]);

  return 0;
}
5 голосов
/ 10 ноября 2009

C может делать все, что может любой другой язык. Это похоже на домашнюю работу, и я уверен, что вы должны сделать что-то с ключом. Помните, ваш инструктор хочет, чтобы вы использовали структуры данных, которые он или она пытается научить вас. Он на самом деле не хочет, чтобы проблема решалась случайным образом, он хочет, чтобы она решалась с использованием обсуждаемых вами тем.

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

3 голосов
/ 10 ноября 2009

enum Makes { SAAB, HONDA, PORSCHE, INVALID };<br> int my_cars[INVALID];<br> my_cars[SAAB] = 2;<br> my_cars[HONDAS] = 3;<br> my_cars[PORSCHE] = 0;

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

Низкоуровневый способ C сделать это состоит в том, чтобы обернуть структуру автомобилей в союз:

// define a structure for the cars.
typedef struct 
{
    int saabs;
    int hondas;
    int porsches;
} cars;

// wrap it into a union:
typedef union 
{
  cars byname;
  int  byid[3]; // Note: Number and type must match with the cars structure. 
} cars2;

int main (int argc, char **arg)
{
  cars2 my_cars;
  int i;

  // fill out by name:
  my_cars.byname.saabs = 1;
  my_cars.byname.hondas = 5;
  my_cars.byname.porsches = 3;

  // print by index:
  for (i=0; i<3; i++)
    printf ("%d\n", my_cars.byid[i]);
}
1 голос
/ 10 ноября 2009

Вам нужны две структуры данных. Массив для хранения чисел и карта от имени к индексу в массиве. В C ++ вы бы использовали один из классов карты в стандартной библиотеке. Я не знаю, что доступно в C, но я уверен, что есть реализации карт.

0 голосов
/ 10 ноября 2009

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

union my_cars {
    struct names {
        int saab;
        int ford;
        ...
    }

    int[NUM_MAKES] nums;
}

Вы должны быть осторожны, чтобы убедиться, что NUM_MAKES синхронизируется с количеством определяемых вами марок. Тогда вы можете сделать что-то вроде:

my_cars.names.saab = 20;
my_cars.nums[0] = 30;

И изменить тот же элемент.

К вашему сведению, мой C немного ржавый, поэтому там могут быть синтаксические ошибки, не стесняйтесь исправлять.

EDIT:

Ах, я прочитал некоторые другие ответы, используя ENUM или DEFINE, и они могли бы быть на самом деле проще / проще, чем этот ... но профсоюзы все еще стоит знать.

0 голосов
/ 10 ноября 2009

Возможно, есть несколько вариантов.

Можно иметь одно и то же пространство в памяти, определенное (и использованное) двумя различными способами. Другими словами, вы можете иметь структуру с именованными членами и ссылаться на нее как на структуру или как массив в зависимости от того, как вы намеревались обращаться с ней.

В качестве альтернативы, вы можете сделать перечислимый typedef, который называет местоположения в массиве, например,

typedef enum {
  SABS = 0,
  HONDAS,
  PORSCHES
} cars;

Это позволит вам ссылаться на смещения в массиве по имени, например,

mycars[SABS] = 5;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...