C语言中指向字符串数组的指针

12

在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;
}

语言是一个包含"en-GB", "da-DK"等语言的char *streq()只是一个自制(比strcmp()稍快)的字符串比较函数。

长话短说,根据编译器的不同,这种方法可能有效,报告编译器警告或编译,但会给出意外的结果。

解决这个问题的正确方法是什么?


2
你应该用NULL指针结束你的字符串数组,这样你就可以合理地遍历它们:const char * strs[] = { "aa", "bb", NULL }; - Kerrek SB
@KerrekSB 我已经更新了文本,以使我的问题更清晰。希望你现在明白了。 - Woodgnome
@Woodgnome,我建议你编辑一下你的问题,给出最简单的自包含(即完整的,可以编译的)问题示例。一个极简的例子。并且包括编译器_警告_和/或运行时错误(或调试器输出错误)。 - mctylr
@Woodgnome 这个问题不完整且含糊。我已尽力回答。给你加1赞,因为回答这个问题需要清楚理解字符数组(字符串)。 - Sangeeth Saravanaraj
@Woodgnome 我认为你想要的不是一个字符串数组的指针,而是一个指向字符串指针数组的指针。如果硬编码的字符串对你的使用足够了,那么可以非常类似于你写的单行声明(不需要malloc)。 - cesss
显示剩余5条评论
2个回答

26

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;
}

那么如果我想将我的字符串数组定义为 char *[COLS],我必须使用 malloc() 然后再使用 strcpy() 吗?难道没有办法用字符串列表进行初始化,例如 {"string1", "string2", ...} 吗? - Woodgnome
2
@Woodgnome 是的,你不能像给整型变量赋值一样,将字符串赋值给char[]char *。对于字符串,你需要使用字符串库函数,如strcpy() - Sangeeth Saravanaraj
1
@Woodgnome 感谢您选择我的答案。我希望它对您有帮助!如果您喜欢这个答案,请随意点赞!谢谢! :) - Sangeeth Saravanaraj
@SangeethSaravanarj 你回答后我立刻点赞了 :P 我也对那个踩的人感到困惑。关于我的后续问题,我会用不同的措辞;我知道我不能声明一个字符数组 string[5]; 然后稍后像 string = "test"; 这样初始化它,但我读到过可以像 char *string = "test"; 这样初始化只读字符串 - 如果是这样的话,在你的例子中使用 char *b[ROWS] = {...} 也是可能的吗?当然,前提是我不需要对字符串进行任何更改。 - Woodgnome
1
这个案例的问题是 char *b[rows]= {"first","second" ... 如果你想要改变字符串,它会导致未指定的行为!因此最好使用 malloc() 函数! - Meninx - メネンックス
显示剩余2条评论

1
正确的解决方法是什么?
嗯,正确的方法是使用一个专门设计用于处理多语言界面的库 - 比如gettext
另一种方法,虽然不太完善,但可以使用一个哈希表(在其他语言/技术中也被称为“字典”或“哈希映射”或“关联映射”):寻找一个好的C语言哈希表实现
这可能不是你想要的答案,但你向正确的问题提出了错误的问题。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接