C无法打印两次字符串

时间:2014-01-11 17:48:16

标签: c string pointers

我正在做一个我必须创建Black Jack模拟的项目。所以我开始创建一个套牌和一个绘图功能。由于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;
}

3 个答案:

答案 0 :(得分:5)

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

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

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

答案 1 :(得分:2)

变量card是函数drawCard中的本地数组。

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

函数drawCard返回后,您不能再依赖此数组的内容。

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

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

但是由于函数fputs也使用了堆栈,因此很快就会覆盖那段内存,当你再次调用fputs时,之前的字符值就不再存在了。

BTW,看看您对变量fputs的使用情况,我觉得您打算将其声明为card而不是char card[50]

答案 2 :(得分:1)

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

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

但是当调用返回时,堆栈会被调整回来。此时, next 函数调用实例将重用相同的空间。如果你坚持参考那个空间,它会被表面随机和不断变化的东西所破坏......

相关问题