Указатель на строковый массив в C - PullRequest
10 голосов
/ 11 января 2012

Играть с указателями в C весело (не совсем).

У меня есть несколько массивов строк, которые я хочу объявить простым способом, желательно что-то вроде:

arrayOfStrings1 = {"word1", "word2", etc. };
arrayOfStrings2 = {"anotherword1", "anotherword2", etc. };
arrayOfStrings3 = etc.
etc.

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

pointerToArrayOfStrings = arrayOfStrings1;
doStuff();
pointerToArrayOfStrings = arrayOfStrings2;
doSomeOtherStuff();

В моем наивном понимании массивов строк и указателей на них я попытался вот что:

// Danish transforms
const unsigned char* da_DK[] = {"b","bb","c","c","cc","d","dd","e","f","ff","g","gg","h","hh","j","j","jj","k","k","kk","l","l","l","l","ll","m","mm","n","n","nn","p","pp","r","r","r","rr","s","s","s","ss","t","t","tt","v","v","vv","æ"};

// British english transforms
const unsigned char* en_GB[] = {"a","a","a","a","a","a","a","a","a","a","a","a","a","age","ai","aj","ay","b","cial","cian","cian","dj","dsj","ea","ee","ege","ei","ei","eigh","eigh","f","f","f","g","g","gs","i","i","i","j","j","k","ks","kw","l","m","n","n","o","r","s","s","sd","sdr","sion","sion","sj","sj","tial","tion","tion","tj","u","u","u","u","w","ye","ye","z"};

    // More languages....

const unsigned char** laguageStrings;

// Assign language
if (streq(language, "da-DK")){
    laguageStrings= da_DK;
}
else if (streq(language, "en-GB")){
    laguageStrings= en_GB;
}
else
         return 0;
}

Язык - это char *, содержащий язык "en-GB", "da-DK" и т. Д., streq() - это просто домашняя (немного более быстрая, чем strcmp()) функция сравнения строк.

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

Каков будет правильный способ решения этой проблемы?

Ответы [ 2 ]

22 голосов
/ 11 января 2012

Существует два способа работы с массивом символов (строк) в C. Они следующие:

char a[ROW][COL];
char *b[ROW];

Графическое представление доступно в виде встроенного комментария в коде.

Исходя из того, как вы хотите представить массив символов (строк), вы можете определить указатель на него следующим образом

    char (*ptr1)[COL] = a;
    char **ptr2 = b;

Это принципиально разные типы (тонким образом), поэтому указатели на них также немного отличаются.

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

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

#define ROW 5
#define COL 10

int main(void) 
{
    int i, j;
    char a[ROW][COL] = {"string1", "string2", "string3", "string4", "string5"};
    char *b[ROW];

    /*

    a[][]

      0   1   2   3   4   5   6     7    8   9
    +---+---+---+---+---+---+---+------+---+---+
    | s | t | r | i | n | g | 1 | '\0' |   |   |
    +---+---+---+---+---+---+---+------+---+---+
    | s | t | r | i | n | g | 2 | '\0' |   |   |
    +---+---+---+---+---+---+---+------+---+---+
    | s | t | r | i | n | g | 3 | '\0' |   |   |
    +---+---+---+---+---+---+---+------+---+---+
    | s | t | r | i | n | g | 4 | '\0' |   |   |
    +---+---+---+---+---+---+---+------+---+---+
    | s | t | r | i | n | g | 5 | '\0' |   |   |
    +---+---+---+---+---+---+---+------+---+---+

    */  

    /* Now, lets work on b */    
    for (i=0 ; i<5; i++) {
        if ((b[i] = malloc(sizeof(char) * COL)) == NULL) {
            printf("unable to allocate memory \n");
            return -1;
        }
    }

    strcpy(b[0], "string1");
    strcpy(b[1], "string2");
    strcpy(b[2], "string3");
    strcpy(b[3], "string4");
    strcpy(b[4], "string5");

    /*

       b[]              0   1   2   3   4   5   6    7     8   9
    +--------+        +---+---+---+---+---+---+---+------+---+---+
    |      --|------->| s | t | r | i | n | g | 1 | '\0' |   |   |
    +--------+        +---+---+---+---+---+---+---+------+---+---+
    |      --|------->| s | t | r | i | n | g | 2 | '\0' |   |   |
    +--------+        +---+---+---+---+---+---+---+------+---+---+
    |      --|------->| s | t | r | i | n | g | 3 | '\0' |   |   |
    +--------+        +---+---+---+---+---+---+---+------+---+---+
    |      --|------->| s | t | r | i | n | g | 4 | '\0' |   |   |
    +--------+        +---+---+---+---+---+---+---+------+---+---+
    |      --|------->| s | t | r | i | n | g | 5 | '\0' |   |   |
    +--------+        +---+---+---+---+---+---+---+------+---+---+

    */

    char (*ptr1)[COL] = a;
    printf("Contents of first array \n");
    for (i=0; i<ROW; i++)
        printf("%s \n", *ptr1++);


    char **ptr2 = b;
    printf("Contents of second array \n");
    for (i=0; i<ROW; i++)
        printf("%s \n", ptr2[i]);

    /* b should be free'd */
    for (i=0 ; i<5; i++)
        free(b[i]);

    return 0;
}
1 голос
/ 11 января 2012

Как правильно решить эту проблему?

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

Другой способ, хотя и более корректный, заключается в использовании хеш-таблицы (также известной как "словарь" или "карта хеш-функции" или "ассоциативная карта" в других языках / технологиях): Поиск для хорошей реализации хеш-таблицы в C

Возможно, это не тот ответ, который вы искали, но вы задали неправильный вопрос к правильной проблеме.

...