分段错误 (C++)

Segmentation Fault (C++)

本文关键字:C++ 错误 分段      更新时间:2023-10-16

到目前为止,我的代码旨在创建一副牌,每个套件的值9 - ACE,并向 4 名玩家发 5 张牌。这些牌是发3-2-3-2牌,然后2-3-2-3,因此每个玩家总共有 5 张牌。稍后我将编写代码来洗牌,然后在euchre游戏中比较它们,但现在我只想发牌。无论如何,它并不完全有效,我愿意接受建议。我得到的错误是"分段错误:11">

#include <iostream>
#include <fstream>
#include <cstring>
#include <string>
using namespace std;
int cards[24]; //array filled with card values
char DECK[24][25] = 
{ //array filled with card names. Used for dealing //24elements long //25 characters in    each element
"Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
"Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
"Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
"Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};
int main (void)
{
char P1[5][25];
char P2[5][25];
char P3[5][25];
char P4[5][25];
for( int i = 0 ; i < 24 ; ++i) // for the total amount of cards
{
  for(int j = 0; j < 25; j++)
  {
      //1st deal 3-2-3-2
      if(i < 3) // 0 - 2 // 3 cards
      {
        P1[i][j] = DECK[i][j];
      }
  if((i > 2) && (i < 5))// 3 - 4 // 2 cards
  {
    P2[i][j] = DECK[i][j];
  }
  if((i > 4) && (i < 8)) // 5 - 7 // 3 cards
  {
    P3[i][j] = DECK[i][j];
  }
  if((i > 7) && (i < 10))// 8 - 9 // 2 cards
  {
    P4[i][j] = DECK[i][j];
  }
  //2nd deal 2-3-2-3
  if((i > 9) && (i < 12)) // 10 - 11 // 2 cards
  {
    P1[i][j] = DECK[i][j];
  }
  if((i > 11) && (i < 15))// 12 - 14 // 3 cards
  {
    P2[i][j] = DECK[i][j];
  }
  if((i > 14) && (i < 17)) // 15 - 16 // 2 cards
  {
    P3[i][j] = DECK[i][j];
  }
  if((i > 16) && (i < 20))// 17 - 19 // 3 cards
  {
    P4[i][j] = DECK[i][j];
  }
  }
}
for(int q = 0; q < 5; ++q)
{
  cout << "P1 has the card " << P1[q]<< endl;
}
for(int q = 0; q < 5; ++q)
{
  cout << "P2 has the card " << P2[q]<< endl;
}
//for(int q = 0; q < 5; ++q)
{
  //cout << "P3 has the card " << P3[q]<< endl;
}
//for(int q = 0; q < 5; ++q)
{
 //cout << "P4 has the card " << P4[q]<< endl;
}
return 0;
}

让我"授你钓鱼":

调试器将告诉您故障的确切位置。如果你使用的是IDE(Xcode,Eclipse,VS(,它有一个很好的界面,你应该使用它。如果没有:

$ gdb my_executable
...
> run
...
Segmentation fault
> where

这将为您提供确切的位置(哪个功能在哪个行号上(。

你有这样的数组

char P1[5][25];

然而,在您的代码中,您将值分配给i索引大于 5 的元素。必须将索引限制为有效且在范围内的元素。仅对 0 到 4 之间的i和 0 到 24 之间的j赋值 P1[i][j] 值才有效。如果偏离这一点,则存在分段错误的风险,因为不应分配给阵列边界之外的内存位置。

 if((i > 4) && (i < 8)) // 5 - 7 // 3 cards
  {
    P3[i][j] = DECK[i][j];

您正在分配给 P3[5]...P3[6]...P3[7]...不存在的。稍后,您将对更大的索引执行相同的操作。您必须使用 i=[0,4] j=[0,24]

请允许我也从一个稍微不同的角度"教你钓鱼"。

代码使用两个常量数字:24 和 25。我很难阅读您的代码,因为您似乎将 25 用于不同的目的两次。

不要使用原始常量数字,而是为它们指定有意义的名称。这将帮助您记录代码,但也将帮助您避免愚蠢的错误。有三种方法可以做到这一点。

C 样式:

#define NUM_CARDS_IN_DECK 24

优点:在此之后,无论您在哪里编写"NUM_CARDS_IN_DECK",编译器都会看到常量"24"并进行适当的类型转换。缺点:您无法在调试器中判断值的来源。

枚举:

enum { NumCardsInDeck = 24 };

优点:出现在某些调试器中, 缺点:有时您可能需要强制转换。

枚举:

static const size_t NumCardsInDeck = 24;
优点:强类型,

通常出现在调试器中,强类型,缺点:强类型。

但是,让我们看看这如何更改您的代码:

static const size_t NumCardsInDeck = 24;
static const size_t MaxCardNameLength = 25;
int cards[NumCardsInDeck];
char DECK[NumCardsInDeck][MaxCardNameLength] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};
int main()
{
    char P1[5][MaxCardNameLength];
    char P2[5][MaxCardNameLength];
    char P3[5][MaxCardNameLength];
    char P4[5][MaxCardNameLength];
    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        for(int j = 0; j < 25; j++)

在这里,我们遇到了可能是错误的内容。你在这里用了数字25,我怀疑你不是故意的。

        for(size_t j = 0; j < MaxCardNameLength; j++)

这就是你想写的吗?您将根据外部循环的值复制每个单独的字符,i?代码看起来不起作用,因为您的代码说

0 <= i

但是你对P1的定义说

0 <= 索引 P1 <5

5 显然小于 25,因此您将溢出 P1 的第一个索引,P2 等也是如此。

猜测,"P"代表玩家,5是手掌大小。看起来您实际上是将整个牌名从套牌复制到手中。您可以通过使用"const char*"指向名称来简化此操作:

static const size_t NumCardsInDeck = 24;
static const size_t NumCardsPerHand = 5;
int cards[NumCardsInDeck];
const char* DECK[NumCardsInDeck] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};
int main()
{
    const char* P1[NumCardsPerHand];
    const char* P2[NumCardsPerHand];
    const char* P3[NumCardsPerHand];
    const char* P4[NumCardsPerHand];
    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        if(i < 3)
        {
            P1[0] = DECK[i];
        }
        else if(i < 6)  // it's an else, so i > 2 is already implied.
        {
            P1[1] = DECK[i];
        }
        ...

好的 - 我们在这里取得了进展,但你仍然会遇到一个问题,让我们通过使用一些更常量的名称来简化它,并使玩家成为一个实体。并将其修剪成一个单一的、可运行的阶段。

#include <iostream>
static const size_t NumCardsInDeck = 24;
static const size_t NumCardsPerHand = 5;
static const size_t NumPlayers = 4;
// removed 'cards' because we aren't using it.
const char* DECK[NumCardsInDeck] =
{
    "Ace of Spades", "Nine of Spades", "Ten of Spades", "Jack of Spades", "Queen of Spades", "King of Spades",
    "Ace of Hearts", "Nine of Hearts", "Ten of Hearts", "Jack of Hearts", "Queen of Hearts", "King of Hearts",
    "Ace of Clubs", "Nine of Clubs", "Ten of Clubs", "Jack of Clubs", "Queen of Clubs", "King of Clubs",
    "Ace of Diamonds", "Nine of Diamonds", "Ten of Diamonds", "Jack of Diamonds", "Queen of Diamonds", "King of Diamonds" 
};
int main()
{
    const char* hands[NumPlayers][NumCardsPerHand];
    enum { Player1, Player2, Player3, Player4 }; // For indexing the hands.
    std::cout << "We have " << NumPlayers << " hands of " << NumCardsPerHand << " cards." << std::endl;
    std::cout << "Total cards that will be dealt: " << NumPlayers * NumCardsPerHand << std::endl;
    for(size_t i = 0 ; i < NumCardsInDeck; ++i) // for the total amount of cards
    {
        if(i < 3)
        {
            hands[Player1][0] = DECK[i];
        }
        else if(i < 6)  // it's an else, so i > 2 is already implied.
        {
            hands[Player2][0] = DECK[i];
        }
        else
        {
            break;
        }
    }
    std::cout << "hands[0][0] = " << hands[0][0] << std::endl;
    std::cout << "hands[1][0] = " << hands[1][0] << std::endl;
    return 0;
}

您可以在此处看到以下代码运行:http://ideone.com/8MUOCt