mvwprintw 在 for 循环中意外执行
mvwprintw acting unexpectedly in for loop
我目前正在编写一个函数来创建一个菜单 window,其中的文本根据参数以各种方式定位。水平打印数组内容时,第一次调用 menu() 正常(单词水平打印,中间有空格)但是如果再次调用该函数,则 printf 的 x 位置不会改变,导致 mvwprintw 覆盖前一个词。这表明我的 for 循环有问题,至少对我来说是这样,但是创建垂直菜单按预期工作,每个单词都打印在最后一个单词下面。
nmenu.c
#include "nmenu.h"
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
int menu(char title[], char description[], char *choices[], int choicesSize, bool vertical, bool centered)
{
int menuXMax = 0;
int highlight = 0;
int menuHeight = 9;
int menuWidth = 30;
int choicesLength = 0;
int yMax, xMax;
getmaxyx(stdscr, yMax, xMax);
for(int i; i < choicesSize; i++)
{
if(strlen(choices[i]) > choicesLength)
{
choicesLength = strlen(choices[i]);
}
}
if(vertical)
{
menuHeight = choicesSize+8;
menuWidth = choicesLength+4;
} else
{
menuWidth = choicesLength*choicesSize+choicesSize;
}
if(strlen(description) > menuWidth)
{
menuWidth = strlen(description)+4;
}
WINDOW *menu = newwin(menuHeight, menuWidth, yMax/2-menuHeight/2, xMax/2-menuWidth/2);
box(menu, 0, 0);
refresh();
wrefresh(menu);
keypad(menu, true);
wattron(menu, A_REVERSE);
mvwprintw(menu, 0, 2, title);
wattroff(menu, A_REVERSE);
mvwprintw(menu, 2, menuWidth/2-strlen(description)/2, description);
mvwprintw(menu, menuHeight-3, menuWidth/2-4, "[C]ancel");
menuXMax = getmaxx(menu);
while(true)
{
for(int i = 0; i < choicesSize; i++)
{
if(i == highlight)
{
wattron(menu, A_REVERSE);
}
if(vertical)
{
if(centered)
{
mvwprintw(menu, i+4, menuXMax/2-strlen(choices[i])/2, choices[i]);
} else
{
mvwprintw(menu, i+4, 2, choices[i]);
}
} else
{
if(centered)
{
mvwprintw(menu, 4, (menuXMax/2-choicesLength*choicesSize/2)+choicesLength*i, choices[i]);
} else
{
mvwprintw(menu, 4, 2+choicesLength*i, choices[i]);
}
}
wattroff(menu, A_REVERSE);
}
switch(wgetch(menu))
{
... // User input
}
}
MenuBreak: ;
return 0;
}
test.c
#include "nmenu.h"
#include <ncurses.h>
char *choices[4] = {"Yes", "No", "Maybe", "Sometimes"};
int main()
{
// Start ncurses
initscr();
noecho();
cbreak();
curs_set(0);
menu("Ver 1", "Choices should be uncentered and presented vertically", choices, 4, true, false);
menu("Ver 2", "Choices should be centered and presented vertically", choices, 4, true, true);
// End ncurses
getch();
endwin();
return 0;
}
test.c 将正常输出第一个菜单,第二个菜单有重叠文本。当调用的顺序被切换时,也会发生这种情况。我只是不明白为什么当函数再次为 运行 时 for 循环将无法正确迭代。
在下一行中:
for(int i; i < choicesSize; i++)
变量i没有初始化。它应该设置为零,因此它看起来像:
for(int i = 0; i < choicesSize; i++)
然后 choicesLength 将被正确计算并且水平布局也有效。
演示
结果的屏幕截图如下所示:
未定义的行为
未初始化的变量在 C 中会导致 undefined behavior,因此无论如何都应该避免。
打开编译器警告很有帮助,例如使用
时
gcc -Wextra -Wall main.c nmenu.c -o tst -lncurses
显示这条有用的信息:
nmenu.c:16:16: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
for(int i; i < choicesSize; i++)
^
我目前正在编写一个函数来创建一个菜单 window,其中的文本根据参数以各种方式定位。水平打印数组内容时,第一次调用 menu() 正常(单词水平打印,中间有空格)但是如果再次调用该函数,则 printf 的 x 位置不会改变,导致 mvwprintw 覆盖前一个词。这表明我的 for 循环有问题,至少对我来说是这样,但是创建垂直菜单按预期工作,每个单词都打印在最后一个单词下面。
nmenu.c
#include "nmenu.h"
#include <ncurses.h>
#include <stdlib.h>
#include <string.h>
int menu(char title[], char description[], char *choices[], int choicesSize, bool vertical, bool centered)
{
int menuXMax = 0;
int highlight = 0;
int menuHeight = 9;
int menuWidth = 30;
int choicesLength = 0;
int yMax, xMax;
getmaxyx(stdscr, yMax, xMax);
for(int i; i < choicesSize; i++)
{
if(strlen(choices[i]) > choicesLength)
{
choicesLength = strlen(choices[i]);
}
}
if(vertical)
{
menuHeight = choicesSize+8;
menuWidth = choicesLength+4;
} else
{
menuWidth = choicesLength*choicesSize+choicesSize;
}
if(strlen(description) > menuWidth)
{
menuWidth = strlen(description)+4;
}
WINDOW *menu = newwin(menuHeight, menuWidth, yMax/2-menuHeight/2, xMax/2-menuWidth/2);
box(menu, 0, 0);
refresh();
wrefresh(menu);
keypad(menu, true);
wattron(menu, A_REVERSE);
mvwprintw(menu, 0, 2, title);
wattroff(menu, A_REVERSE);
mvwprintw(menu, 2, menuWidth/2-strlen(description)/2, description);
mvwprintw(menu, menuHeight-3, menuWidth/2-4, "[C]ancel");
menuXMax = getmaxx(menu);
while(true)
{
for(int i = 0; i < choicesSize; i++)
{
if(i == highlight)
{
wattron(menu, A_REVERSE);
}
if(vertical)
{
if(centered)
{
mvwprintw(menu, i+4, menuXMax/2-strlen(choices[i])/2, choices[i]);
} else
{
mvwprintw(menu, i+4, 2, choices[i]);
}
} else
{
if(centered)
{
mvwprintw(menu, 4, (menuXMax/2-choicesLength*choicesSize/2)+choicesLength*i, choices[i]);
} else
{
mvwprintw(menu, 4, 2+choicesLength*i, choices[i]);
}
}
wattroff(menu, A_REVERSE);
}
switch(wgetch(menu))
{
... // User input
}
}
MenuBreak: ;
return 0;
}
test.c
#include "nmenu.h"
#include <ncurses.h>
char *choices[4] = {"Yes", "No", "Maybe", "Sometimes"};
int main()
{
// Start ncurses
initscr();
noecho();
cbreak();
curs_set(0);
menu("Ver 1", "Choices should be uncentered and presented vertically", choices, 4, true, false);
menu("Ver 2", "Choices should be centered and presented vertically", choices, 4, true, true);
// End ncurses
getch();
endwin();
return 0;
}
test.c 将正常输出第一个菜单,第二个菜单有重叠文本。当调用的顺序被切换时,也会发生这种情况。我只是不明白为什么当函数再次为 运行 时 for 循环将无法正确迭代。
在下一行中:
for(int i; i < choicesSize; i++)
变量i没有初始化。它应该设置为零,因此它看起来像:
for(int i = 0; i < choicesSize; i++)
然后 choicesLength 将被正确计算并且水平布局也有效。
演示
结果的屏幕截图如下所示:
未定义的行为
未初始化的变量在 C 中会导致 undefined behavior,因此无论如何都应该避免。
打开编译器警告很有帮助,例如使用
时gcc -Wextra -Wall main.c nmenu.c -o tst -lncurses
显示这条有用的信息:
nmenu.c:16:16: warning: variable 'i' is uninitialized when used here [-Wuninitialized]
for(int i; i < choicesSize; i++)
^