【问题标题】:int differs in level of indirection from char[2] errorint 与 char[2] 错误的间接级别不同
【发布时间】:2015-06-22 23:40:55
【问题描述】:

代码来自绝对初学者 C 指南,当我尝试在 Visual Studio 中编译它时,我收到此错误./BlackJack.c<41> : warning C4047: '==' : 'int' differes in levels of indirection from 'char [2]'。这是二十一点游戏的主要功能。

第 行是if (ans == "H") {

main()
{
    int numCards; /* Equals 52 at the beginneing */
    int cards[52], playerPoints[2], dealerPoints[2], total[2]; 
    /* For user Hit/Stand or     Yes/No response */

    do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
        dealerGetsCard(&numCards, cards, dealerPoints);
        printf("\n");
        playerGetsCard(&numCards, cards, playerPoints);
        playerGetsCard(&numCards, cards, playerPoints);
        do {
            ans = getAns("Hit or stand (H/S)? ");
            if (ans == "H") { 
                platerGetsCard(&numCards, cards, playerPoints); 
            }
        }
        while ( ans != 'S');
        totalIt(playerPoints, total, PLAYER);
        /* Player's total */
        do {
            dealerGetsCard(&numCards, cards, dealerPoints);
        } while (dealerPoints[ACEHIGH] < 17);
        /* 17: Dealer stop */
        totalIt(dealerPoints, total, DEALER);
        /* Dealer's total */
        findWinner(total);
        ans = getAns("\nPlay again (Y/N)? ");
    } while (ans == 'Y');
    return;
}

(更新):这是完整的代码。

#include <stdio.h>
#include <time.h>
#include <ctype.h>
#include <stdlib.h>

#define BELL '\a'
#define DEALER 0
#define PLAYER 1

#define ACELOW 0
#define ACEHIGH 1

int askedForName = 0;

/****************************
This program specific prototype
****************************/
void dispTitle(void);
void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int * numCards);
int dealCard(int * numCards, int cards[52]);
void dispCard(int cardDrawn, int points[2]);
void totalIt(int points[2], int total[2], int who);
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2]);
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2]);
char getAns(char mesg[]);
char ans;
void findWinner(int total[2]);


main()
{
    int numCards; /* Equals 52 at the beginneing */
    int cards[52], playerPoints[2], dealerPoints[2], total[2]; /* For user Hit/Stand or Yes/No response */

    do { initCardsScreen(cards, playerPoints, dealerPoints, total, &numCards);
    dealerGetsCard(&numCards, cards, dealerPoints);
    printf("\n");
    playerGetsCard(&numCards, cards, playerPoints);
    playerGetsCard(&numCards, cards, playerPoints);
    do {
        char ans = getAns("Hit or stand (H/S)? ");
        if (ans == "H") { 
            playerGetsCard(&numCards, cards, playerPoints); 
        }
    }
    while ( ans != 'S');
    totalIt(playerPoints, total, PLAYER);
    /* Player's total */
    do {
        dealerGetsCard(&numCards, cards, dealerPoints);
    } while (dealerPoints[ACEHIGH] < 17);
    /* 17: Dealer stop */
    totalIt(dealerPoints, total, DEALER);
    /* Dealer's total */
    findWinner(total);
    ans = getAns("\nPlay again (Y/N)? ");
    } while (ans == 'Y');
    return;
}

void initCardsScreen(int cards[52], int playerPoints[2], int dealerPoints[2], int total[2], int *numCards)
{
    int sub, val=1; /* This function's Work variables */
    char firstName[15]; /* Holds user's first name */
    *numCards = 52; /* Holds running total of number of cards */

    for (sub = 0; sub <= 51; sub++) { /* Counts from 0 to 51 */
        val = (val == 14) ? 1 : val; /* If val is 14 reset to 1 */
        cards[sub] = val;
        val++; }
    for (sub = 0; sub <= 1; sub++) { /* Counts from 0 to 1 */
        playerPoints[sub] = dealerPoints[sub] = total[sub]=0; }
    dispTitle();
    if (askedForName ==0) { /* Name asked for nly once */
        printf("\nWhat is your first name? ");
        scanf_s(" %s", firstName);
        askedForName = 1; /* Don't ask prompt again */
        printf("Ok, %s, get ready for casino action!\n\n", firstName);
        getchar(); /* Discards newline. You can safely */
    }           /* ignore compiler warning here. */
    return;
}

/*** This function gets a card for the player and updates the player's points. ***/
void playerGetsCard(int *numCards, int cards[52], int playerPoints[2])
{
    int newCard;
    newCard = dealCard(numCards, cards);
    printf("You draw: ");
    dispCard(newCard, playerPoints);
}

/*** This function gets a card for the dealer and updates the dealer's poimts. ***/
void dealerGetsCard(int *numCards, int cards[52], int dealerPoints[2])
{
    int newCard;
    newCard = dealCard(numCards, cards);
    printf("The dealer draws: ");
    dispCard(newCard, dealerPoints);
}

/*** This function gets a card from the deck and stores it in either the dealer's or the player's hold of cards ***/
int dealCard(int * numCards, int cards[52])
{
    int cardDrawn, subDraw;
    time_t t; /* Gets time for a random value */
    srand((unsigned int)(time(&t)));  /* Seeds random-number generator */
    subDraw = (rand() % (*numCards)); /* From 0 to numcards */
    cardDrawn = cards[subDraw]; 
    cards[subDraw] = cards[*numCards -1]; /* Puts top card */
    (*numCards); /* in place of drawn one */
    return cardDrawn;
}

/*** Displays the last drawn card and updates points with it. ***/
void dispCard(int cardDrawn, int points[2])
{
    switch (cardDrawn) {
    case(11) : printf("%s\n", "Jack");
        points[ACELOW] += 10;
        points[ACEHIGH] += 10;
        break;
    case(12) : printf("%s\n", "Queen");
        points[ACELOW] += 10;
        points[ACEHIGH] += 10;
        break;
    case(13) : printf("%s\n", "King");
        points[ACELOW] += 10;
        points[ACEHIGH] += 10;
        break;
    default : points[ACELOW] += cardDrawn;
        if (cardDrawn == 1)
        { 
            printf("%s\n", "Ace");
            points[ACEHIGH] += 11;
        }
        else
        {
            points[ACEHIGH] += cardDrawn;
            printf("%d\n", cardDrawn); 
        }
    } return;
}

/*** Figure the total for player or dealer to see who won. This function takes into account the fact that Ace is either 1 or 11. ***/
void totalIt(int points[2], int total[2], int who)
{
    /* The following routine first looks to see if the total points counting Aces as 1 is equal to the total points couning Aces as 11. If so, 
    or if the total points counting Aces as 11 is more than 21, the program uses the total with Aces as 1 only */
    if ((points[ACELOW] == points[ACEHIGH]) || (points[ACEHIGH] > 21)) {
        total[who] = points[ACELOW]; /* Keeps all Aces as 1 */
    }
    else {
        total[who] = points[ACEHIGH]; /* Keeps all Aces as 11 */
    }
    if (who == PLAYER) /* Determines the message printed */ {
        printf("You have a total of %d\n\n", total[PLAYER]);
    }
    else {
        printf("The house stands with a total of %d\n\n", total[DEALER]);
    }
    return;
}

/*** Prints the winning player. ***/
void findWinner(int total[2])
{
    if (total[DEALER] == 21) {
        printf("The house wins.\n");
        return;
    }
    if ((total[DEALER] > 21) && (total[PLAYER] > 21)) { 
        printf("%s", "Nobody wins.\n");
        return;
    }
    if ((total[DEALER] >= total[PLAYER]) && (total[DEALER] < 21)) {
        printf("The house wins.\n");
        return;
    }
    if ((total[PLAYER] > 21) && (total[DEALER] < 21)) {
        printf("The house wins.\n");
        return;
    }
    printf("%s%c", "You win!\n", BELL);
    return;
}

/*** Gets the user's uppercase, single-character response. ***/
char getAns(char mesg[])
{
    char ans;
    printf("%s", mesg); /* Prints the prompt message passed */
    ans = getchar();
    getchar(); /* Discards newline. You can safely ignore compiler warning here. */
    return toupper(ans);
}

/*** Clears everything off the screen. ***/
void dispTitle(void)
{
    int i=0;
    while (i < 25) { /* Clears screen by printing 25 blank lines to 'push off' stuff that
                     might be left over on the screen before this program */
        printf("\n");
        i++;
    }
    printf("\n\n*Step right up to the Blackjack tables*\n\n");
    return;
}

【问题讨论】:

  • 这是您的全部代码吗?我问是因为ans 似乎没有在任何地方声明。
  • 我已经编辑了问题并添加了整个代码。
  • 请在修复问题之前发布相关代码。解决问题的代码应该作为答案(如果没有必要则省略,如本例所示)
  • 好的,我按照你的要求做了。

标签: c


【解决方案1】:

注意所有其他比较都有单引号吗?

while (ans == 'Y')

在这里,您正在比较单个字符(这是一个数字,因此可以与另一个数字进行比较)。

另一方面,在失败的代码中,您使用了双引号。

ans == "H"

所以你正在与一个字符串进行比较,它是一个字符数组。该数组有两个字符长以容纳null terminator

【讨论】:

  • 其实比较的是char*指针。 "H" 是一个数组表达式;在大多数情况下,它被隐式转换为指向数组第一个元素的指针,包括这个。
【解决方案2】:

"H"(双引号)是一个字符串,而不是一个字符。要获得包含字母H 的字符常量,您需要'H'(用单引号括起来。)因此,您的行应为if( ans == 'H' )

if( ans == "H"[0] ) 也可以使用。这会将ans 与字符串"H" 的第一个(第零个)字符进行比较。

我同意这是一个简单的类型不匹配错误的非常神秘的消息。归咎于 C 和 C 编译器。 (我可以建议你使用一些更现代的语言,比如 C# 或 Java 吗?)

编译器将您的ans 报告为int,而您可能已将其声明为char。 (我不知道你是如何声明它的,因为你似乎从你发布的源代码中省略了它的声明。)如果发生这种情况,那是因为编译器在尝试时隐式地将 char 转换为 int将其与其他事物进行比较。

编译器还将您的"H" 报告为char[2],原因可能不是很明显:C 使用以 null 结尾的字符串,因此文字“H”表示为 2 字符数组,其中第一个字符是'H',第二个字符是空字符。 ('\0')。

然后编译器会咕哝一些关于不同间接级别的东西,而不是告诉你你试图比较的类型是不兼容的。这是因为在尝试执行比较时,编译器认为"H" 不是字符数组,而是指向数组第一个字符的指针,但这仍然无济于事,因为它最终是指向一个字符,(一级间接),而它需要一个字符。 (零级间接。)

【讨论】:

  • 不,不能将数组视为指向其第一个元素的指针。在大多数情况下,数组表达式被隐式转换为指向其第一个元素的指针。阅读comp.lang.c FAQ 的第 6 部分
  • @KeithThompson 我完全赞成准确性和精确性,如果你这么说,你可能比我更了解,但是......你是认真的吗?你对此投了反对票?如何编辑我的答案并改进我的措辞? “[编译器] 试图解释”意味着“[编译器] 隐式转换”,不是吗?我的意思是,我认为我的措辞至少适合绝对的初学者,不是吗?
  • 我不喜欢编辑答案并更改其含义,即使该含义不正确。指针和数组等价的想法是关于 C 的最常见的误解之一,尤其是对于初学者而言。如果您编辑您的答案以纠正该错误(并发表评论让我知道),我很乐意撤回我的反对票。
  • @KeithThompson 好的,我改写了,如果您仍然发现它有问题,请告诉我。
  • 更好,我取消了我的反对票。我还有几个cmets。首先,"H"[0] 确实是合法的,但恕我直言,这是人为的,不值得一提。其次,编译器不会将"H" 转换为指针,因为它试图找到一种合法的方法来进行比较。在这种情况下,"H" 必须 转换为指针(因为它不是sizeof 或一元&amp; 的操作数,也不是用于初始化数组对象的初始化程序的一部分)。最后,我不会说编译器“认为”"H" 是一个指针。而是它转换它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-18
  • 2019-06-13
  • 2016-08-02
  • 2018-10-09
  • 1970-01-01
  • 2020-01-05
相关资源
最近更新 更多