【问题标题】:Strange output without a pointer没有指针的奇怪输出
【发布时间】:2020-11-07 00:45:01
【问题描述】:

我是 C 的初学者,我想编写一个将用户输入转换为摩尔斯电码的程序。 这就是我所做的:

char morseCode[26][4] = {  
                        ".-",   /*  A   */
                        "-..",  /*  B   */
                        "-.-.", /*  C*  */
                        "-..",  /*  D   */
                        ".",    /*  E   */
                        "..-.", /*  F*  */
                        "--.",  /*  G   */
                        "....", /*  H*  */
                        "..",   /*  I   */
                        ".---", /*  J   */
                        "-.-",  /*  K   */
                        ".-..", /*  L*  */
                        "--",   /*  M   */
                        "-.",   /*  N   */
                        "---",  /*  O   */
                        ".--.", /*  P*  */
                        "--.-", /*  Q*  */
                        ".-.",  /*  R   */
                        "...",  /*  S   */
                        "-",    /*  T   */
                        "..-",  /*  U   */
                        "...-", /*  V*  */
                        ".--",  /*  W   */
                        "-..-", /*  X*  */
                        "-.--", /*  Y*  */
                        "--.."  /*  Z   */
                        };
char uString[100], newString[100];
int uChoice;

int main(){
    //printf("morseCode[%d] = %s\n", 2, morseCode[2]);

    printf("Enter text (max 100 characters): ");
    fgets(uString, 100, stdin);

    printf("\nString in morse code: \n");

    for (int i = 0; i < strlen(uString); i++) {
        uString[i] = toupper(uString[i]);
        newString[i] = uString[i] - 'A';
        
        printf("newString[%d] = %d\tmorseCode[newString[%d]] = %s\n", i, newString[i], i, morseCode[newString[i]]);
        }
    return 0;
}

请注意,我在面临输出错误的 cmets 中放置了一个 *。这是我打印出来的样子:imgur

我在网上寻找解决方案,发现有人做了同样的事情,但他这样声明他的“莫尔斯电码”版本:

char *morseCode[] = {/* Strings here*/};

当我这样做时,一切都运行良好,并且完全按照预期输出。 为什么将morseCode 设为指针可以解决这些问题?我认为任何具有char 数据类型的数组都会立即成为指针?这只是我应该一直做的最佳做法吗?

【问题讨论】:

  • 不要弄乱你的字符串,而是做类似int index = uString[i] - 'A'的事情。在继续引用无效索引之前,您还应该确保您的输入没有超出允许的范围。
  • 这一行包含了一个初学者常犯的不幸错误:for (int i = 0; i &lt; strlen(uString); i++) {每次循环计算字符串的长度。通过在进入循环之前计算一次长度并将结果保存在变量中来修复它。然后在循环中使用变量。这与您遇到的行为无关,但它是糟糕的代码。

标签: c pointers char


【解决方案1】:

char morseCode[26][4] 只为每个字符串分配四个字节。 C 中的字符串必须以空字符结尾。 ".-." 等字符串文字会自动包含此字符。您的某些字符串有四个非空字符,例如".--."。因此,当包含空字符时,它们需要五个字符。因为您使用[4] 定义了数组,所以数组中没有足够的空间容纳空字符,因此未包含在内。这会在打印字符串时导致错误。

您可以通过将 [4] 更改为 [5] 来修复它。

更改为指针有效,因为字符串文字不是用于初始化数组,而是放在内存中,并创建了指向它们的指针。当他们初始化数组时,如果空字符不合适,则将其排除在外。当它们被放入内存时,会包含空字符。

【讨论】:

  • 非常详细的解释。非常感谢!
【解决方案2】:

您的代码的问题在于,char [26][4] 类型的第二维 (4) 不够大,无法包含某些字符串的内容,因为其中一些包含四个可打印字符 加上一个字符串终结者。当您使用这样的字符串来初始化您的数组元素之一时,只使用前四个字符,使该元素没有终止符。未定义的行为是由于尝试使用这些未终止元素之一,就好像它是一个字符串一样。该问题可以通过将声明更改为

来解决
char morseCode[26][5] = /* ... */

在每种情况下都为字符串终止符留出足够的空间。

为什么将morseCode 设为指针可以解决这些问题?

使morseCode 一个数组 指针解决了这个问题,因为数组包含指向字符串文字的指针,这些指针总是正确终止,而不是直接包含字符。

我认为任何具有 char 数据类型的数组都会立即成为指针?

没有。没有这种与char 数组特别相关的特殊行为。您可能会想到数组的一般属性,即在几乎所有上下文中,当数组值 表达式求值 时,生成的数组会自动转换为指向数组的第一个元素。这并不意味着数组与指针是一样的,特别是,这并不意味着 char *[26]char[26][4] 相同。前者的元素是指针(x86_64 上每个 8 字节)。后者的元素是由四个chars 组成的数组,每个数组(4 个字节,与架构无关)。

这只是我应该一直做的最佳实践吗?

首选指向数组的指针,也不是首选指向数组的指针数组,这不是最佳实践。您确实需要学习和理解差异。那么你应该在任何给定的编程情况下选择更合适的那个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-10
    • 1970-01-01
    • 2012-11-11
    • 2020-01-22
    • 2014-09-11
    相关资源
    最近更新 更多