【问题标题】:What am I misunderstanding about char**?我对 char** 有什么误解?
【发布时间】:2012-10-12 10:51:45
【问题描述】:

我正在为计算机科学课做一些作业,而一项相当乏味的作业的最后一部分是编写一个可以反转句子的函数。教授提供的函数原型是这样的:

int reverseSentence(char** sentence, char **
                newsentence, int maxWords)

...其中 sentence 是原始句子,newsentence 是我们应该转储倒置句子的位置,maxWords 是原始句子中的单词数。我这样写我的函数...

int reverseSentence(char** sentence, char **
                newsentance, int maxWords)
{

    int i = maxWords;
    int x = 0;
    while(i > 0){
        newsentance[x] = sentence[i];
        x++;
        i--;
    }

    return maxWords;
}

但是,循环似乎永远在进行。另外,我似乎对如何使用char** 有误解。我以为它只是一个字符串数组,比如char[words][characters]。但是我收到有关以该形式将一组单词传递给函数的警告。我不是要求任何人为我做功课,只是为了澄清我在如何使用char** 方面所缺少的。

感谢任何帮助。谢谢。

P.S - 这就是我尝试测试我的代码的方式:

char sentence[3][4] = {"Hi\n", "my\n", "fri\n"};
char newsentence[3][4];
reverseSentence(sentence, newsentence, 3);

【问题讨论】:

  • 假设代码没有崩溃(即传入的变量具有合理的值),循环应该终止。你为 maxWords 传递了什么值?
  • 这就是我尝试在我的 main 中测试代码的方式:(在 P.S. 之后在原始问题中更新)
  • 是句子,不是句子 :)

标签: c pointers char


【解决方案1】:

如您的评论中所示,代码

char sentence[3][4] = {"Hi\n", "my\n", "fri\n"};

有效,但与char ** 不兼容。相反,它应该是:

char *sentence[3] = {"Hi\n", "my\n", "fri\n"};

第一个在内存中是这样布局的,字符打包成一个块,三组,每组四个字符:

+---+---+---+---+---+---+---+---+---+---+---+---+
| H | i | \n| \0| m | y | \n| \0| f | r | i | \n|
+---+---+---+---+---+---+---+---+---+---+---+---+

请注意,最后一个条目有一个尾随 NUL (\0),因为数组中可用的 4 个字符中没有空间。

第二个声明(你想要的)是一个包含三个指向 NUL 终止字符串的指针的数组:

+---------------+---------------+---------------+
|    char *     |    char *     |    char *     |
+---------------+---------------+---------------+
       |               |               |
       |               |               |    +---+---+---+---+---+
       |               |               +--> | f | r | i | \n| \0|
       |               |                    +---+---+---+---+---+
       |               |    +---+---+---+---+
       |               +--> | m | y | \n| \0|
       |                    +---+---+---+---+
       |    +---+---+---+---+
       +--> | H | i | \n| \0|
            +---+---+---+---+

【讨论】:

  • 我应该如何为新闻句子分配空间?我现在得到 EXC_BAD_ACCESS。
  • 参考上图,需要为指针数组分配空间(长度与sentence相同),然后使newsentence中的指针指向与在sentence 中,正好相反。所以newsentence = malloc(maxWords * sizeof(char *));
  • 啊,我明白了,所以这样做的目的是为了不重复记忆中的原始单词 - 只需以相反的顺序指向它们,对吗?
  • @AnthonyFrizalone:是的,完全正确。有很多可能的方法来编写“反转句子中的单词”功能,听起来这就是练习要寻找的方法。
  • 声明char sentence[3][4] = {"Hi\n", "my\n", "fri\n"};是有效的,sentence是一个由3个char[4]组成的数组,组成char[4]用字符串初始化。它相当于 char sentence[3][4] = {{'H','i','\n','\0'}, {'m','y','\n','\0'}, {'f','r','i','\n'}}; 问题在于语义,最后一个不是 0 终止的,因此将 sentence[2] 传递给期望(指向)0 终止 char[] 的东西会导致未定义的行为。
【解决方案2】:

我不确定为什么它会永远循环……但有几点需要注意:

  1. 你以i = maxWords开头...这似乎是错误的。数组是从 0 开始索引的,那么如果设置 i = maxWords 会发生什么?
  2. 命名有点奇怪。首先,您在newsentance 中有错字。其次你叫它maxWords,但它应该更像numWords,对吧?
  3. 如果您对char* 的理解是它是一个“字符串数组,例如 char[words][characters]”,那么您对 ​​C 类型的看法与它实际存在的方式之间存在巨大的差距(简称总结是类型/内存是 C) 中最重要、最基础和令人困惑的部分之一。你有一本教科书来了解 C 中的类型是如何表示的吗?我不确定你是否需要知道这个任务......可能是天真的工作。

编辑哦,天哪。您对原句的声明甚至可以编译吗?我不太确定怎么做。您可能想再次阅读有关指针的内容...

【讨论】:

  • 它可以被称为maxWords,因为巨魔教授希望他们同时检查NULL并且不超过maxWords
  • 我同意你所说的一切——我的教授负责命名 maxWords 和拼写错误——是的,它是迟钝的,但我不想因为没有像她那样命名而失去分数。我没有关于此事的教科书......我了解指针的工作原理。如果我没记错的话, char* 是指向字符数组中第一个字符的指针,这些字符一起创建一个字符串,对吗?我相信我不明白的是 char**。似乎它是一个指向字符指针的指针......但我不确定如何将其扩展为指向一个句子......
  • 好的,我想我开始明白了。那么,我的函数实现是否正确?例如。如果传入的变量初始化正确,它会起作用吗?
  • 如果您添加 Greg 编写的两行代码并修改一些索引问题,您就完成了。但是您已经完全避免学习 C 内存/指针(听起来您认为自己做到了,但是查看图表并理解它们与了解数以百计的细微差别对于真正的基本知识很重要)之间确实存在很大差异东西),我认为你错过了重点......也许我是一个迂腐的驴子
  • 对指针有了基本的了解。我知道如何将指针用于引用调用等基本内容。我已经做了大约 5 年的 iPhone 程序员,所以我了解指针是如何用于传递对象和诸如此类的东西的。但是,不,我不是 C 语言指针方面的专家。编辑:如果您有任何好的文章/教程,我会很乐意阅读它们。
【解决方案3】:

您可以将 char** 句子视为字符串向量。您可以使用字符串函数,例如 strlen,例如:strlen(sentence[0]) 会给您第一行的长度。然后,您可以从结尾到开头,从 lenght - 1 到 0 开始。不要忘记计算中间的空格,以便正确减少单词计数器。请记住,您可能会发现不止一个空格分隔两个单词,并且在递减计数器时应该考虑到这一点。不要忘记将 '\0' 放在新字符串的末尾。

要复制到新的“字符串向量”,您应该小心使用 malloc 和 realloc,或者...您可以搜索最长的行并分配具有该大小的所有行。请记住,当你打印一个字符串时,它会在你得到 '\0' 字符时停止,不管向量的大小。

【讨论】:

    猜你喜欢
    • 2021-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-21
    • 1970-01-01
    相关资源
    最近更新 更多