【问题标题】:C can't print a string twiceC不能两次打印字符串
【发布时间】:2014-01-11 17:48:16
【问题描述】:

我正在做一个项目,我必须创建一个 Black Jack 模拟。所以我开始创建一个deck和一个draw函数。由于 C 中没有字符串,我创建了两个指针数组以将它们用作自定义字符串数组。问题是,当我打印卡片以查看其价值和花色时,只有第一次打印出预期的内容。第二次是乱码。谁可以给我解释一下这个 ?这是我的代码

#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
char* suit[] = {"Diamonds", "Hearts", "Spades", "Clubs"};
char* facevalue[] = { "Seven", "Eight", "Nine", "Ten", "Jack","Queen", "King", "Ace"};
char* drawCard()
{
    char* card[50];
    int cardNumber=rand()%8;
    int cardColor=rand()%4;
    strcpy(card,facevalue[cardNumber]);
    char of[]=" of  ";
    char* xrwma =suit[cardColor];
    strncat(card,of,5);
    strncat(card,xrwma,8);
    return card;
}
int main()
{
    srand(time(NULL));
    char* c=drawCard();
    puts(c);
    puts(c);
    return 0;
}

【问题讨论】:

    标签: c string pointers


    【解决方案1】:

    问题是您正在返回一个指向自动数组的指针。一旦函数返回,数组就会超出范围。尝试取消引用返回的指针会导致 undefined behaviour。对puts() 的第一次调用虽然在技术上未定义,但恰好适用于您的情况。第二个没有。

    请参阅Returning a pointer to an automatic variable 进行讨论。

    一种解决方案是在main() 内分配数组,将指向它的指针(及其大小)传递给drawCard(),然后让drawCard() 填充它。

    【讨论】:

    • 另外,首选哪种解决方案?将指针传递给 drawCard() 或使用 f.e malloc ?为了有一个更干净的代码。谢谢
    【解决方案2】:

    变量card是函数drawCard中的一个局部数组。

    因此,当函数drawCard执行时,它被分配到堆栈中。

    函数drawCard返回后,就不能再依赖这个数组的内容了。

    任何后续操作都可能随时覆盖该内存。

    您的程序在第一次调用puts 时成功打印它的事实只不过是“运气问题”——正确的字符恰好位于变量c 指向的内存中,在第一次调用函数fputs

    但由于函数 fputs 也使用堆栈,那块内存很快就会被覆盖,并且当您再次调用 fputs 时,之前的字符值不再存在。

    顺便说一句,看看您对变量 card 的使用情况,我觉得您打算将其声明为 char card[50] 而不是 char* card[50]

    【讨论】:

    • +1 表示char* card[50]。这意味着编译器的警告没有完全参与。 OP 应该解决的问题。
    • 我直接声明为char *card可以吗?
    • 好吧,char* card = malloc(50*sizeof(char))char card[50],随你喜欢。请记住,如果您选择第一个选项,那么您必须在稍后调用free(...),如果您选择第二个选项,那么您不能在函数之外使用它。
    【解决方案3】:

    严格来说,问题在于drawCard() 返回的自动变量的生命周期。它只适用于一个函数调用实例。 C 不会阻止你返回它,但它总是在以后没有用处。

    原因是:本地(自动存储类)在堆栈上分配。 真的快;一个算术运算——从堆栈指针中减去——可以分配函数中的每个局部。

    但是当调用返回时,堆栈被调整回来。此时 next 函数调用实例将重用相同的空间。如果您坚持对该空间的引用,它将被表面上随机且不断变化的东西所破坏...

    【讨论】:

      猜你喜欢
      • 2021-05-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多