[英]Segmentation fault while accessing an array of WINDOW structures in ncurses
我正在使用 ncurses 制作一個小益智游戲,該游戲允許用戶點擊任何箭頭鍵來移動包含每個數字的框,所有框都在一個大框內,以升序排列數字。 它是一個 4x4 的盒子,一個子盒子是空白的,以便其他子盒子可以移動。
現在我在訪問我在函數中創建的 WINDOW 數組(不是指針)時遇到問題,以便我可以銷毀所有 sub_boxes,更改數字數組,並根據數組重新創建子框。
#include <stdio.h>
#include <ncurses.h>
#include <math.h>
#include <string.h>
#define HEIGHT 16
#define WIDTH 32
#define STARTY ((LINES - HEIGHT) / 2)
#define STARTX ((COLS - WIDTH) / 2)
#define QEXIT 81
#define qEXIT 113
WINDOW *create_win(int height, int width, int starty, int startx){
WINDOW *local_win;
local_win = newwin(height, width, starty, startx);
box(local_win, 0, 0);
wrefresh(local_win);
return local_win;
};
void destroy_win(WINDOW *local_win){
wborder(local_win, ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh(local_win);
delwin(local_win);
};
void draw_list(WINDOW *local_win, WINDOW *num_wins, int arr[][4], int length){
for(int i=0; i < length; i++){
for(int j=0; j < length; j++){
refresh();
WINDOW *sub_win;
int height = HEIGHT / length, width = WIDTH / length, starty = STARTY + i*height, startx = STARTX + j*width;
sub_win = create_win(height, width, starty, startx);
//wprintw(stdscr, "%d |", sizeof(*sub_win));
*(num_wins + i*4+j) = *sub_win;
//wprintw(stdscr, "%d - ", i*4+j);
//overwrite(sub_win, (num_wins + i*4+j));
//memcpy(num_wins + i*4+j, sub_win, sizeof(*sub_win));
int digity = height / 2, digitx = width / 2 - 1;
if(arr[i][j])
mvwprintw(sub_win, digity, digitx, "%d ", arr[i][j]);
else
mvwprintw(sub_win, digity, digitx, "X ");
wrefresh(sub_win);
};
};
};
void destroy_list(WINDOW *num_wins){
int length = 16;
for(int i=0; i < length; i++){
wprintw(stdscr, "%d ", i);
wborder((num_wins + i), ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh((num_wins + i));
delwin((num_wins + i));
};
};
void play(){
int arr[4][4] = {1,4,15,7,8,10,2,11,14,3,6,13,12,9,5,0};
int length = 4;
WINDOW *win;
int starty, startx;
//Placement
starty = STARTY;
startx = STARTX;
printw("Press Q or q to exit\n");
//printw("%d - %d\n%d - %d\n", LINES, COLS, HEIGHT, WIDTH);
printw("\n");
refresh();
// Create original window (Maybe it is useless)
win = create_win(HEIGHT, WIDTH, starty, startx);
// Create sub windows for numbers
WINDOW sub_wins[16];
draw_list(win, sub_wins, arr, length);
refresh();
getch();
destroy_win(&sub_wins[0]);
refresh();
//for(int i=0; i < 16; i++){
// wprintw(stdscr, "%d -", sizeof(sub_wins[i]));
//destroy_win(sub_wins + i);
//};
wrefresh(win);
int ch = getch();
while(ch != QEXIT && ch != qEXIT){
switch(ch){
case KEY_UP:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, --starty, startx);
//destroy_list(sub_wins);
break;
case KEY_RIGHT:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, starty, ++startx);
break;
case KEY_DOWN:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, ++starty, startx);
break;
case KEY_LEFT:
destroy_win(win);
win = create_win(HEIGHT, WIDTH, starty, --startx);
break;
};
ch = getch();
};
};
int main(void){
//printList(arr, length);
printf("\n");
// Init ncurses
initscr();
cbreak();
noecho();
keypad(stdscr, TRUE);
// Game mechanics
play();
endwin();
return 0;
};
我在代碼中提出了多個問題,有些部分與我的主要問題並不完全相關。 對不起。 但我想主要解決有關銷毀子窗口的問題。
先感謝您。
您不能將一個窗口拆分為兩個窗口。 如果復制窗口結構,則需要使用一個且僅一個實例來引用窗口。
*(num_wins + i*4+j) = *sub_win;
在這里你復制一個窗口。 該窗口現在位於兩個位置, sub_win
和num_wins
數組中。 你沒有兩個窗口,你只有一個。 所以你需要選擇其中之一。
if(arr[i][j])
mvwprintw(sub_win, digity, digitx, "%d ", arr[i][j]);
else
mvwprintw(sub_win, digity, digitx, "X ");
wrefresh(sub_win);
好的,所以你修改sub_win
。 這意味着您制作的副本不是窗口。 請記住,只有一個窗口。 由於您修改了sub_win
,因此它是窗口。 那么在修改窗口之前復制窗口有什么意義,那不再是窗口了。
void destroy_list(WINDOW *num_wins){
int length = 16;
for(int i=0; i < length; i++){
wprintw(stdscr, "%d ", i);
wborder((num_wins + i), ' ', ' ', ' ', ' ', ' ', ' ', ' ', ' ');
wrefresh((num_wins + i));
delwin((num_wins + i));
};
};
你在這里做什么? 您正在操作修改窗口之前的窗口副本。 但是你修改了它——所以那個窗口不再存在。 這段代碼沒有意義。
窗戶是一個,而且只有一個。 如果制作WINDOW
結構的副本,則可以使用任一副WINDOW
表示窗口。 但是你不能同時使用兩者——只有一個窗口。 您的代碼同時使用兩者。 那是無效的。
總之:您制作了窗口的副本,然后修改了窗口(不是副本)。 這意味着該副本的窗口,是你修改了它,這東西已經不存在,因為你修改你復制的東西之前的副本。 所以嘗試訪問副本是一個錯誤,因為它是一個不再存在的東西的副本。
這有點像這樣做:
復制后,您可以將任一面視為原件,因為它們在這一點上是相同的。 但是你也不能惹別人,否則你會非常困惑。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.