Модераторы: bsa
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Ассоциативные массивы в СИ ? 
:(
    Опции темы
Gendos
Дата 29.4.2010, 09:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 29.4.2010

Репутация: нет
Всего: нет



Есть ли аналогия или механизм который позволит сделать подобное ( как в Perl-e ):
Код


$hash{'key'} = "val";
           ^            ^
           |             |
           |     значение
           |
       ключ

$hash{'key'} = ["string1","string2", "stringN"];
                                ^^^^^^^^
                                    |
                   массив со строками

 
Для чего мне это нада?

Я получаю HTTP ответ от сервера, мне нужно хранить URL (как ключ) и строки HTTP заголовка ( как массив ссылок на строки (разделенные strtok (\n) ) ),
Иными словами по оброщению name[key][0] 1я строка, name[key][1] вторая строка...

Предпологаю что нужно писать отдельную функцию, но реализовать пока не представляю как, может все же есть готовое решение? или подскажите как мне сделать мою задумку?)

ps: Чистый СИ под Unix

Это сообщение отредактировал(а) Gendos - 29.4.2010, 09:56
PM MAIL   Вверх
yeputons
Дата 29.4.2010, 10:18 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 77
Регистрация: 1.4.2009
Где: Санкт-Петербург

Репутация: 2
Всего: 5



В чистом C такое отсутствует. Может быть есть какие-либо сторонние библиотеки, хотя в их существование под C, а не C++ я не слишком верю.
В C++ есть штука под название map<string, string> - как раз ассоциативный массив (время запроса/добавления/удаления - O(log2 N), где N - кол-во элементов в массиве).
PM MAIL ICQ Skype   Вверх
Shaggie
Дата 29.4.2010, 12:04 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Завсегдатай
Сообщений: 570
Регистрация: 21.12.2006
Где: outer space

Репутация: нет
Всего: 72



Поковыряй сторонние библиотеки: раз, два.


--------------------
Цитата(alina3000 @  6.3.2014,  10:47 Найти цитируемый пост)
Сорри что не по теме 
PM MAIL ICQ GTalk Jabber   Вверх
Gendos
Дата 29.4.2010, 12:56 (ссылка) |    (голосов:1) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 2
Регистрация: 29.4.2010

Репутация: нет
Всего: нет



Shaggie thnx. Вот пример нашел из книги "Хрестоматия по программированию на Си в Unix":
Код


/* Работа с хэш-таблицей. Часть функций написана так, чтобы
 * быть независимой от типов ключа и значения и легко
 * подвергаться модификации.
 */
#include <stdio.h>
#include <string.h>     /* prototype for strchr() */
extern void *malloc(unsigned size);
/* типы ключа и значения: в нашем случае это строки */
typedef unsigned char uchar;
typedef uchar *VAL; typedef uchar *KEY;
/* Для использования следует реализовать операции
int  HASHFUNC(KEY); int  EQKEY(KEY, KEY);
void FREEVAL(VAL);  void SETVAL(VAL, VAL);
void FREEKEY(KEY);  void SETKEY(KEY, KEY);
*/
#define HASHSIZE 21     /* размер таблицы: очень хорошо 2**n */
uchar *strudup(const uchar *s){ /* создание копии строки в "куче" */
  uchar *p =  (uchar *) malloc(strlen(s)+1); strcpy(p, s); return p;
}
/* одна из возможных хэш-функций */
unsigned int hash; /* последнее вычисленное значение хэш-функции */
int HASHFUNC(KEY key){
    unsigned int i = 0; uchar *keysrc = key;
    while(*key){
      i = (i << 1)|(i >> 15); /* ROL */
      i ^= *key++;
    }
    hash = i % HASHSIZE;
    printf( "hash(%s)=%d\n", keysrc, hash);  /* отладка */
    return hash;
}
#define EQKEY(s1, s2)   (strcmp(s1, s2) == 0)
#define FREEKEY(s)      free(s)
#define FREEVAL(s)      free(s)
#define SETVAL(at,s)    at = strudup(s)
#define SETKEY(at,s)    at = strudup(s)
#define KEYFMT          "%s"
#define VALFMT          "%s"
/* ================== типо-независимая часть ================= */
struct cell {
    struct cell *next; /* ссылка на очередной элемент */
    KEY key;           /* ключ     */
    VAL val;           /* значение */
} *hashtable[ HASHSIZE ];  /* хэш-таблица */
/* получение значения по ключу */
struct cell *get(KEY key){
    struct cell *p;
    for(p = hashtable[HASHFUNC(key)]; p; p = p->next)
        if(EQKEY(p->key, key))
            return p;
    return NULL;    /* отсутствует */
}
/* занести пару ключ:значение в таблицу */
void set(KEY key, VAL val){
    struct cell *p;
    /* проверить - не было ли звена с таким ключом */
    if((p = get(key)) == NULL){       /* не было   */
        if(!(p = (struct cell *) malloc(sizeof(*p)))) return;
        SETKEY(p->key, key);
        p->next = hashtable[hash]; /* hash вычислено в get() */
        hashtable[hash] = p;
    } else /* уже было: изменить значение */
        FREEVAL(p->val);
    SETVAL(p->val, val);
}
/* удаление по ключу */
int del(KEY key){
    int indx = HASHFUNC(key);
    struct cell *p, *prev = NULL;
    if((p = hashtable[indx]) == NULL) return 0;
    for( ;p ;prev = p, p=p->next)
        if(EQKEY(p->key, key)){
            FREEVAL(p->val); FREEKEY(p->key);
            if( p == hashtable[indx] ) /* голова списка */
                 hashtable[indx] = p->next;
            else     prev->next = p->next;
            free((void *) p ); return 1; /* удален */
        }
    return 0;  /* не было такого */
}
/* распечатать пару ключ:значение */
void printcell(struct cell *ptr){
    putchar('(');
    printf( KEYFMT, ptr->key ); putchar(',');
    printf( VALFMT, ptr->val ); putchar(')');
}
/* распечатка таблицы (для отладки) */
void printtable(){
  register i; struct cell *p;
  printf("----TABLE CONTENTS----\n");
  for(i=0; i < HASHSIZE; i++)
      if((p = hashtable[i]) != NULL){
      printf( "%d: ", i);
      for(; p; p=p->next)
         printcell(p), putchar(' ');
      putchar('\n');
      }
}
/* итератор */
struct celliter {
    int index; struct cell *ptr;
};
/* выдать очередное значение */
struct cell *nextpair(struct celliter *ci){
    struct cell *result;
    while((result = ci->ptr) == NULL){
        if( ++(ci->index) >= HASHSIZE )
            return NULL;    /* больше нет */
        ci->ptr = hashtable[ci->index];
    }
    ci->ptr = result->next; return result;
}
/* инициализация итератора */
struct cell *resetiter(struct celliter *ci){
    ci->index = (-1); ci->ptr = NULL;
    return nextpair(ci);  /* первое значение */
}
/* =========================================================== */
void main(){ /* таблица из имен и размеров файлов текущего каталога */
 struct celliter ci; struct cell *cl;
 char key[40], value[40]; struct cell *val;
 extern FILE *popen();    FILE *fp;     char *s ;
 /* popen() читает вывод команды, заданной в 1-ом аргументе */
 fp = popen( "ls -s", "r" );
 while( fscanf( fp, "%s%s", value, key) == 2 )
    set(key, value);
 pclose(fp);  /* popen() надо закрывать pclose(); */
 for(;;){
    printf( "-> " );  /* приглашение */
    if( !gets( key )) break;   /* EOF */
    if( *key == '-' ){         /* -КЛЮЧ          :удалить     */
        printf( del( key+1 ) ? "OK\n" : "нет такого\n");
        continue;
    }
    if( !*key || !strcmp(key, "=")){ /* = :распечатать таблицу*/
        printtable();    continue;
    }
    if(s = strchr(key, '=')){ /* КЛЮЧ=ЗНАЧЕНИЕ  :добавить     */
        *s++ = '\0';
        set(key, s); continue;
    }
    if((val = get( key )) == NULL) /* КЛЮЧ :найти значение */
         printf( "нет такого ключа\n");
    else{ printf( "значение "); printf(VALFMT, val->val);
          putchar('\n');
    }
 }
 /* распечатка таблицы при помощи итератора */
 for( cl = resetiter(&ci) ; cl ; cl = nextpair(&ci))
    printcell(cl), putchar('\n');
}




PM MAIL   Вверх
shara
Дата 14.5.2010, 23:46 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 344
Регистрация: 29.6.2004
Где: печенье?

Репутация: 2
Всего: 2



опишу идею  smile 


Код

char fullString[] = "Bla Bla1 Bla2 Bla4 ... BlaN";  // исходна строка параметров
char separator = ' '; // разделителем для параметров считать ПРОБЕЛ

int totalParams = CountSeparators( fullString,  separator ); 
// функцию CountSeparators() нужно написать руцями. 
// просто возвращает сколько раз определенный символ встречается в строке 
// (кажется в стандартной Си-шной билиотеке есть нечто подобное)

char **params; // сдесь будет масив указателей
params = malloc (totalParams  * sizeof(char*)); // выделим памяти по количеству 'найденных' параметров

char *cursor = fullString;

int i = 0;
while (*cursor != 0) {        // бежим последовательно по всей строке
  if (*cursor == separator) // если нашли разделитель
     params[i++] = cursor;  // запомним указатель i-того параметра

  ++cursor; // следующий символ
}

// тестируем что получилось

for (i = 0; i< totalParams; ++i)
  printf (" param #%i '%s'\n", i, params[i]);




чтобы уж совсем выводились только параметры то все разделители потом нужно будет заменить на символ конца строки, т.е. на '\0' и сделать из одной большой строки много маленьких =)

поидее должно работать
З.Ы. за опечатки не пинать сильно, писал с головы - если что исправлю

Цитата(Gendos @  29.4.2010,  11:56 Найти цитируемый пост)
Shaggie thnx. Вот пример нашел из книги "Хрестоматия по программированию на Си в Unix":

 smile ОГО, ниче се примерчик )))

Это сообщение отредактировал(а) shara - 14.5.2010, 23:57


--------------------
   с точки зрения аэродинамики шмель не может летать  
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Вопросы по реализации алгоритмов рассматриваются здесь


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.1784 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.