在 C 函数中修改二维数组后程序挂起 [重复]

问题描述 投票:0回答:2

程序是一个井字游戏,取用户的X和Y值后就挂了

这是主文件:

#include <stdio.h>
#include <string.h>
#include "input.cpp"

int makeMove(char** board, char* moveX, char* moveY, char playerMove) {
    printf("Make your x move: ");
    int answerX = (int)getNum(moveX, 2);

    printf("Make your y move: ");
    int answerY = (int)getNum(moveY, 2);

    answerX--;
    answerY--;

    if ((answerX < 0) || (answerX > 2)) {
        return -1;
    }

    if ((answerY < 0) || (answerY > 2)) {
        return -1;
    }

    board[answerY][answerX] = playerMove;
    return 0;
}

int main()
{
    int turns = 0;
    const int MAX_TURNS = 9;
    char playerOneChar = 'X';
    char playerTwoChar = 'O';
    char currentChar = playerOneChar;

    while (turns <= MAX_TURNS) {
        char board[3][3];
        memset(board, ' ', 9);

        char moveX[2];
        memset(moveX, ' ', 2);

        char moveY[2];
        memset(moveY, ' ', 2);

        int result = makeMove(board, moveX, moveY, currentChar);
        
        if (result == 0) {
            if (currentChar == playerOneChar) {
                currentChar = playerTwoChar;
            }

            else {
                currentChar = playerOneChar;
            }

            turns++;
        }

        else {
            printf("Player move was out of bounds.");
        }
    }
}

这是 input.cpp,它旨在安全地从用户那里获取数字,而不允许 对于缓冲区溢出或其他问题:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>

long getNum(char* buffer, int bufferSize)
{
    long answer;
    int success = 0;

    while (!success)
    {
        // This gets the input from the user
        if (!fgets(buffer, bufferSize, stdin))
        {
            //If fgets fails, return with exit code 1.
            return 1;
        }

        char* endptr;

        errno = 0;
        answer = strtol(buffer, &endptr, 10);

        // If an error occurs, the user is told the number is too small or large.
        if (errno == ERANGE)
        {
            printf("Sorry, this number is too small or too large.\n");
            success = 0;
        }

        else if (endptr == buffer)
        {
            success = 0;
        }

        else if (*endptr && *endptr != '\n')
        {
            success = 0;
        }

        else
        {
            success = 1;
        }
    }

    return answer;
}

我尝试输入2个数字,但之后程序挂了。我试图在 Internet 上进行研究,但对于为什么函数无法正确写入 2D 数组的原因缺乏任何解释。我假设它挂起是因为 char** 是指向 char* 的指针,而不是指向二维字符数组的指针。

c multidimensional-array undefined-behavior implicit-conversion function-definition
2个回答
1
投票

makeMove()
的第一个参数需要是
char board[][3]
,这是一个固定的二维数组,行长为3,与您在
main()
中声明的相匹配。
char** board
是一个相当不同的东西,它是一个 pointers 数组,每个指针指向一个
char
s 的一维数组。


1
投票

这个函数声明

int makeMove(char** board, char* moveX, char* moveY, char playerMove) {

无效。

你正在传递给函数

int result = makeMove(board, moveX, moveY, currentChar);

二维数组

board
声明为

char board[3][3];

用作参数表达式,它被隐式转换为指向其类型

char ( * )[3]
的第一个元素的指针。但是函数参数的类型是
char **
char ( * )[3]
char **
指针类型的对象之间没有隐式转换。所以这个函数调用已经调用了未定义的行为。

你应该像这样声明函数

int makeMove(char board[][3], char* moveX, char* moveY, char playerMove) {

另一个问题是

fgets

的调用
if (!fgets(buffer, bufferSize, stdin))

由于

bufferSize
等于
2
那么换行符
'\n'
将不会存储在输入缓冲区中(只有当用户立即按下 Enter 键时才会存储。在这种情况下,数组看起来像
{ '\n', '\0' }
)。因此,后续调用
fgets
将读取一个空字符串,该字符串将仅包含换行符。

注意好像是因为文件的扩展名

#include "input.cpp"

您正在将程序编译为 C++ 程序。 C和C++是两种不同的语言。但无论如何,将模块作为标头包含在内是一个坏主意。你需要单独编译它。

© www.soinside.com 2019 - 2024. All rights reserved.