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++)
           ^