【问题标题】:Pointers to Pointers: What datatype with variable length strings?指向指针的指针:具有可变长度字符串的数据类型是什么?
【发布时间】:2014-09-01 22:33:54
【问题描述】:

我需要在 C 中存储一个名称列表。我决定一个好方法是使用双指针(或指针对指针)。

所以我会有一个名字数组。每个数组值都是指向另一个数组的指针:名称,存储为字符数组。

名称可能看起来像

unsigned char *name = "Joseph";

等等

然后我会有一个名称列表(双指针),我可以(动态地)分配每个名称(单指针)。

(type) **listOfNames;

我的问题是:双指针应该是什么类型?由于它是指向指针的指针,我在想它必须足够大以容纳任意内存地址:unsigned long,也许?还是有另一种专门用于双指针的类型?

或者——有没有更好的存储可变长度数组或可变长度字符串的方法?

【问题讨论】:

  • 只要char,或者unsigned char,如果你真的需要的话。指向 T 的指针的大小与 T 的大小不同。
  • 哦,那么char **list;?
  • 是的。否则你将很难让它指向字符串文字。
  • @user3121023 您不必这样做,例如char const *listOfNames[20];
  • 问题是名称不是const。我正在从文件中读取它们。因此,可变长度字符串的可变长度数组。我不知道编译时会有多长时间。

标签: c arrays pointers types


【解决方案1】:

如果您有unsigned char * 值的集合:

unsigned char *name_0 = "Joseph";
unsigned char *name_1 = "Helen";
unsigned char *name_2 = "Maximillian";

然后你可以创建:

unsigned char *data[] = { name_0, name_1, name_2 };
unsigned char **listOfNames = data;

请注意,您需要为指针列表分配空间——在我的代码中,这是data 数组。您可以改用malloc(),但您需要记住在某些时候对匹配的free() 进行编码。

添加适当的const 资格对于感兴趣的读者来说是一种挫败感。

如果您在运行时从文件中读取可变长度的名称列表,并且(可能)每行一个名称,那么您最好使用 POSIX getline()strdup()

必须有许多其他问题涉及这种情况,所以我将简要介绍此代码:

char **read_file(FILE *fp)
{
    char  *buffer = 0;
    size_t bufsiz = 0;
    char **lines = 0;
    size_t n_lines = 0;
    size_t n_alloc = 0;

    while (getline(&buffer, &bufsiz, fp) > 0)
    {
        if (n_lines + 1 >= n_alloc)
        {
            size_t new_num = (n_alloc + 1) * 2;
            size_t new_size = new_num * sizeof(*lines);
            char **new_lines = realloc(lines, new_size);
            if (new_lines == 0)
            {
                free(buffer);
                free(lines);
                return(0);
            }
            lines = new_lines;
            n_alloc = new_num;
        }
        lines[n_lines++] = strdup(buffer);  // Includes newline!
    }
    lines[n_lines] = 0;  // Null terminate list of strings
    free(buffer);        // Release input line's memory
    return lines;
}

请注意,代码使用纯 char 而不是 unsigned char。如果您使用unsigned char,您会遇到一些问题,因为getline()strdup() 都不希望与unsigned char 一起使用。虽然您可以自行解决问题,但这样做很麻烦。

【讨论】:

  • 我最终使用了该代码的稍微不那么美化的版本。一些细微的差异,包括我的列表是 CSV 的事实。我也没有使用strdup(),而是在每个循环开始时重新声明了缓冲区变量。
  • 哦,是的——废话!我忘记在返回之前释放buffer,所以我的代码泄漏(好吧,泄漏)内存。在主题上使用变体很好——甚至鼓励。
  • -1 作为getline 的返回测试怎么样?
  • 是的,我需要重新阅读手册页。我可能会选择> 0 作为条件,但它永远不会返回 0——-1 或大于零的某个数字。
猜你喜欢
  • 2018-03-10
  • 2019-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-01-14
  • 2021-06-28
相关资源
最近更新 更多