silver-crow 发表于 2023-5-25 15:36:29

发牌程序问题

问题:.h文件的第48行总是报Segmentation fault   错误
代码清单:
.c文件如下:
#include "S1E31T0.h"
#define MAX 1024

int main()
{
    int i;
    char name1, name2, name3;
    int played_cards = {0};//初始化已消耗牌牌组
    int* playing_cards1;
    int* playing_cards2;
    int* playing_cards3;

    printf("请输入第一个参与打牌的人的名字:");
    fgets(name1, MAX, stdin);
    printf("请输入第二个参与打牌的人的名字:");
    fgets(name2, MAX, stdin);
    printf("请输入第三个参与打牌的人的名字:");
    fgets(name3, MAX, stdin);

    //发牌
    playing_cards1 = deal_cards(played_cards, 0);
    for(i = 0; i < 18; i++)
    {
      played_cards = playing_cards1;
    }

    playing_cards2 = deal_cards(played_cards, 1);
    for(i = 19; i < 37; i++)
    {
      played_cards = playing_cards1;
    }

    playing_cards3 = deal_cards(played_cards, 2);
   
    //打印每个人手上的牌
    printf("%s手里的牌为:\n", name1);
    printf_cards(playing_cards1);
    printf("\n");

    printf("%s手里的牌为:\n", name2);
    printf_cards(playing_cards2);
    printf("\n");

    printf("%s手里的牌为:\n", name3);
    printf_cards(playing_cards3);
    printf("\n");

    return 0;
}


.h文件如下:
#include "string.h"
#include "stdio.h"
#include "stdlib.h"
#include "time.h"   
//#define playing_cards = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54}
//其中1-13表示黑桃,14-26表示红桃,27-39表示梅花,40-52表示方片,51表示小王(joker),52表示大王(JOKER)

int random_num(int num);//用于生成随机数的函数
int* deal_cards(int sum, int played_cards);//用于发牌的函数
int judge(int num, int played_cards);//判断num是否是之前已经随机出来的数
void printf_cards(int played_cards);//用来输出每个人手牌
//int sum = 0;

int random_num(int num)
{
    int result;
    time_t t;//使用time函数返回标准计时点到当前时间的秒数用于作为初始化伪随机数的种子序列

    srand((unsigned int)time(&t));//使用当前时间值作为初始化伪随机数种子序列

    result = rand() % num + 1;//rand() % (n-m+1)+m --->   产生m到n之间的随机数
}

int judge(int num, int played_cards)
{
    int i;

    for(i = 0; i < 18; i++)
    {
      if(num == played_cards)
      {
            return 1;
      }
    }

    return 0;
}

int* deal_cards(int sum, int played_cards)
{
    int i, j,num, len;
    static int playing_cards;
    int played_card;

    len = 19;
    for(j = 0; j < 54; j++)
    {
      played_card = played_cards;
    }

    for(i = 0 + len * sum; i < (18 + len * sum); i++)
    {
      while(judge(num, played_card) == 1)
      {
            num = random_num(54);
      }
      played_card = num;
      playing_cards = num;
      sum++;
    }
   
    return playing_cards;
}

void printf_cards(int played_cards)
{
    int i;

    for(i = 0; i < 18; i++)
    {
      if(played_cards > 0 && played_cards < 14)
      {
            if(played_cards == 11)
            {
                printf("黑桃J ");
            }
            else if(played_cards == 12)
            {
                printf("黑桃Q ");
            }
            else if(played_cards == 13)
            {
                printf("黑桃K ");
            }
            else
            {
                printf("黑桃%d ", played_cards);
            }
      }
      else if(played_cards > 13 && played_cards < 27)
      {
            if(played_cards - 13 == 11)
            {
                printf("红桃J ");
            }
            else if(played_cards - 13 == 12)
            {
                printf("红桃Q ");
            }
            else if(played_cards - 13 == 13)
            {
                printf("红桃K ");
            }
            else
            {
                printf("红桃%d ", played_cards);
            }
      }
      else if(played_cards > 26 && played_cards < 40)
      {
            if(played_cards - 26 == 11)
            {
                printf("梅花J ");
            }
            else if(played_cards - 26 == 12)
            {
                printf("梅花Q ");
            }
            else if(played_cards - 26 == 13)
            {
                printf("梅花K ");
            }
            else
            {
                printf("梅花%d ", played_cards);
            }
      }
      else
      {
            if(played_cards - 39 == 11)
            {
                printf("方片J ");
            }
            else if(played_cards - 39 == 12)
            {
                printf("方片Q ");
            }
            else if(played_cards - 39 == 13)
            {
                printf("方片K ");
            }
            else
            {
                printf("方片%d ", played_cards);
            }
      }
    }
}

isdkz 发表于 2023-5-25 15:39:31

从你的代码来看,你在.h文件中声明了函数,并在.c文件中调用这些函数。然而,你并没有提供这些函数的实现,这可能导致程序在运行时出错。以下是我对你的代码中可能存在问题的地方的分析:

1.random_num 函数在声明时返回值为 int 类型,但实现时没有明确的 return 语句。应该将 result 的值返回。

2. 在 deal_cards 函数中, played_card] = played_cards[i]; 这一行代码使用了 i 作为索引,但 i 在此时并未被初始化,这可能会引起未定义的行为,包括段错误。你可能想使用 j 作为索引。

3. 在 deal_cards 函数中, num 变量在 while 循环中被使用前并未被初始化,这可能导致随机出现的数字无法预测。

4. 在.c文件中,当你在第二次和第三次调用 deal_cards 函数时,你试图将 playing_cards2 和 playing_cards3 的值赋给 played_cards ,但你使用的索引可能出了问题。第二次你应该从索引18开始,而不是19,第三次你应该从索引36开始。

在修改这些问题后,你的代码可能会看起来像这样:

.h文件
// 其他的代码保持不变

int random_num(int num)
{
    int result;
    time_t t;//使用time函数返回标准计时点到当前时间的秒数用于作为初始化伪随机数的种子序列

    srand((unsigned int)time(&t));//使用当前时间值作为初始化伪随机数种子序列

    result = rand() % num + 1;//rand() % (n-m+1)+m --->   产生m到n之间的随机数
    return result;
}

int* deal_cards(int sum, int played_cards)
{
    int i, j,num = 0, len;
    static int playing_cards;
    int played_card;

    len = 18;
    for(j = 0; j < 54; j++)
    {
      played_card = played_cards;
    }

    for(i = 0 + len * sum; i < (18 + len * sum); i++)
    {
      while(judge(num, played_card) == 1)
      {
            num = random_num(54);
      }
      played_card = num;
      playing_cards = num;
      sum++;
    }
   
    return playing_cards;
}


.c文件
// 其他的代码保持不变

    //发牌
    playing_cards1 = deal_cards(played_cards, 0);
    for(i = 0; i < 18; i++)
    {
      played_cards = playing_cards1;
    }

    playing_cards2 = deal_cards(played_cards, 1);
    for(i = 18; i < 36; i++)
    {
      played_cards = playing_cards2;
    }

    playing_cards3 = deal_cards

(played_cards, 2);
    for(i = 36; i < 54; i++)
    {
      played_cards = playing_cards3;
    }


请注意,这些修改只解决了一部分问题,还有其他的问题可能会影响到程序的正确性。例如,在发牌的算法中,你可能会遇到同一张牌被发给多个玩家的情况。

silver-crow 发表于 2023-5-25 15:49:12

isdkz 发表于 2023-5-25 15:39
从你的代码来看,你在.h文件中声明了函数,并在.c文件中调用这些函数。然而,你并没有提供这些函数的实现, ...

按照您的意见修改了代码,但是依然在同样的位置报Segmentation fault错误

sfqxx 发表于 2023-5-25 20:59:12

本帖最后由 sfqxx 于 2023-5-25 21:02 编辑

问题解答:

根据代码,可以看出第48行没有代码,应该是注释掉了。但是在不注释的情况下,可能会发生段错误,因为 `playing_cards1`数组、`playing_cards2`数组和`playing_cards3`数组都是通过`deal_cards`函数返回的指针,而这个指针指向的内存空间是在函数中动态分配的。但是,在函数中并没有释放这些动态分配的内存空间,所以可能会导致内存泄漏和段错误等问题。建议在使用完这些指针之后,再通过`free`函数释放掉这些内存空间,以避免内存泄漏和其他问题的发生。

另外,`random_num`函数没有声明返回类型,应该将其返回类型设为`int`类型。另外,在`deal_cards`函数中,定义了一个`played_card`数组,但是在赋值的时候,使用了不存在的变量`i`作为下标,应该改为使用`j`作为下标,即将`played_card[ i] = played_cards[ i];`改为`played_card = played_cards;`。

代码清单如下:
#include "S1E31T0.h"
#include <stdlib.h> // 添加头文件
#define MAX 1024

int main()
{
    int i;
    char name1, name2, name3;
    int played_cards = {0};
    int* playing_cards1;
    int* playing_cards2;
    int* playing_cards3;

    printf("请输入第一个参与打牌的人的名字:");
    fgets(name1, MAX, stdin);
    printf("请输入第二个参与打牌的人的名字:");
    fgets(name2, MAX, stdin);
    printf("请输入第三个参与打牌的人的名字:");
    fgets(name3, MAX, stdin);

    playing_cards1 = deal_cards(played_cards, 0);
    for(i = 0; i < 18; i++)
    {
      played_cards = playing_cards1;
    }

    playing_cards2 = deal_cards(played_cards, 1);
    for(i = 19; i < 37; i++)
    {
      played_cards = playing_cards2; // 修改下标
    }

    playing_cards3 = deal_cards(played_cards, 2);

    printf("%s手里的牌为:\n", name1);
    printf_cards(playing_cards1);
    printf("\n");

    printf("%s手里的牌为:\n", name2);
    printf_cards(playing_cards2);
    printf("\n");

    printf("%s手里的牌为:\n", name3);
    printf_cards(playing_cards3);
    printf("\n");

    free(playing_cards1); // 释放动态分配的内存空间
    free(playing_cards2);
    free(playing_cards3);

    return 0;
}

int random_num(int num)
{
    int result;
    time_t t;

    srand((unsigned int)time(&t));

    result = rand() % num + 1;
    return result; // 添加返回类型
}

int judge(int num, int played_cards)
{
    int i;

    for(i = 0; i < 18; i++)
    {
      if(num == played_cards)
      {
            return 1;
      }
    }

    return 0;
}

int* deal_cards(int sum, int played_cards)
{
    int i, j,num, len;
    int* playing_cards = (int*)malloc(sizeof(int) * 18); // 动态分配内存空间
    int played_card;

    len = 19;
    for(j = 0; j < 54; j++)
    {
      played_card = played_cards; // 修改下标
    }

    for(i = 0 + len * sum; i < (18 + len * sum); i++)
    {
      while(judge(num, played_card) == 1)
      {
            num = random_num(54);
      }
      played_card = num;
      playing_cards = num;
      sum++;
    }

    return playing_cards;
}

void printf_cards(int played_cards)
{
    int i;

    for(i = 0; i < 18; i++)
    {
      if(played_cards > 0 && played_cards < 14)
      {
            if(played_cards == 11)
            {
                printf("黑桃J ");
            }
            else if(played_cards == 12)
            {
                printf("黑桃Q ");
            }
            else if(played_cards == 13)
            {
                printf("黑桃K ");
            }
            else
            {
                printf("黑桃%d ", played_cards);
            }
      }
      else if(played_cards > 13 && played_cards < 27)
      {
            if(played_cards - 13 == 11)
            {
                printf("红桃J ");
            }
            else if(played_cards - 13 == 12)
            {
                printf("红桃Q ");
            }
            else if(played_cards - 13 == 13)
            {
                printf("红桃K ");
            }
            else
            {
                printf("红桃%d ", played_cards);
            }
      }
      else if(played_cards > 26 && played_cards < 40)
      {
            if(played_cards - 26 == 11)
            {
                printf("梅花J ");
            }
            else if(played_cards - 26 == 12)
            {
                printf("梅花Q ");
            }
            else if(played_cards - 26 == 13)
            {
                printf("梅花K ");
            }
            else
            {
                printf("梅花%d ", played_cards);
            }
      }
      else
      {
            if(played_cards - 39 == 11)
            {
                printf("方片J ");
            }
            else if(played_cards - 39 == 12)
            {
                printf("方片Q ");
            }
            else if(played_cards - 39 == 13)
            {
                printf("方片K ");
            }
            else
            {
                printf("方片%d ", played_cards);
            }
      }
    }
}

有用请设置最佳答案{:10_254:}

silver-crow 发表于 2023-5-29 10:16:01

sfqxx 发表于 2023-5-25 20:59
问题解答:

根据代码,可以看出第48行没有代码,应该是注释掉了。但是在不注释的情况下,可能会发生段错 ...

谢谢您的回复,但是还是在您代码的第99行报了Segentation fault 的错误

天地丶良心 发表于 2023-5-29 16:31:50

在函数deal_cards中,数组played_card在复制时使用了错误的变量名i,正确的应该是j:
```
for(j = 0; j < 54; j++)
{
    played_card = played_cards;
}
```
另外,在函数random_num中,虽然生成了随机数,但是没有返回结果,应该加入返回语句:
```
int random_num(int num)
{
    int result;
    time_t t;

    srand((unsigned int)time(&t));

    result = rand() % num + 1;

    return result;//加入返回语句
}
```

天地丶良心 发表于 2023-5-29 16:34:14

sfqxx 发表于 2023-5-25 20:59
问题解答:

根据代码,可以看出第48行没有代码,应该是注释掉了。但是在不注释的情况下,可能会发生段错 ...

使用动态分配内存空间来存储每个人手里的牌。其中,使用了随机数函数来模拟洗牌和发牌的过程,同时也使用了函数来进行多个操作。代码的错误主要集中在数组下标的处理上,特别是使用了循环变量来代替数组下标,导致程序无法正确处理数组内元素的顺序。

针对这些问题,本文主要对代码进行如下改进:

1. 添加头文件#include ;

2. 修正函数random_num的返回类型,应该是int而不是void;

3. 修改变量名played_cards的定义,应该是一个指向int的指针int* played_cards;

4. 修改deal_cards函数中的循环体,将循环变量i作为数组下标修改为i-len*sum,同时对played_cards数组的下标也进行调整;

5. 在函数deal_cards中增加变量的定义num,用于代替i作为洗牌过程中产生的随机数;

6. 在主函数中增加对动态分配内存空间的释放,使用free()函数进行释放。
页: [1]
查看完整版本: 发牌程序问题