【问题标题】:Having a problem with Field validation in Ncurses formNcurses 表单中的字段验证存在问题
【发布时间】:2020-09-14 10:50:31
【问题描述】:

我在 ncurses 表单中的字段验证方面遇到了一些问题,希望有人能解释一下。 问题在于以下附加代码。特别是在函数validateField() 中名为“AuthorityCode”的字段中。 ENUM Auth_codes 设置为三个值,当输入正确的值(枚举值之一)时,它工作正常。它还验证大多数不正确的值(不在 ENUM 中的值)。但是,由于某种原因,它在字段中接受单个数字“1”、“2”、“3”、“4”、“5”、“6”或“8”,但不接受“7”或“9” '。似乎没有任何一个字母被接受,也没有多个数字的任何组合,只有上述数字。 所有其他验证(包括其他枚举)似乎都在正常工作。

是否有人对此行为有解释或可以在我的代码中找到问题?

const char* Auth_codes[]
{ "Add", "Update", "Delete" };

const char* Return_codes[]
{ "Accepted", "Denied" };

const char* Priorities[]
{ "3", "5", "6", "8" };


void createForm(WINDOW *win_body, vector<string> &input, int selection)
{
    int rows;
    int cols;
    int i;
    int cury = 0;
    int curx = 1;
    int nb_fields;
    WINDOW *inner;

    formClose = false;

    getmaxyx(win_body, rows, cols);

    nb_fields = input.size()
    
    fields = (FIELD**) malloc(sizeof(FIELD *) * (nb_fields + 1));
    assert(fields);

    for (i = 0; i < nb_fields; i++)
    {
            fields[i] = new_field(1, 10, cury, curx, 0, 0);
            assert(fields[i] != NULL);
            set_field_buffer(fields[i], 0, "");
            field_opts_on(fields[i], O_ACTIVE);
            field_opts_on(fields[i], O_EDIT);
            field_opts_off(fields[i], O_AUTOSKIP);
            set_field_back(fields[i], A_UNDERLINE);
            validateField(fields[i], input[i].c_str()); // Set correct field validation based on label value
            curx = 1; // Set position for next label field
            cury = cury + 1; // Next line

    }
    
    fields[i] = NULL;
    form = new_form(fields);
    assert(form != NULL);
    win_form = derwin(win_body, rows - 10, cols - 4, 3, 2);
    box(win_form, 0, 0);
    assert(form != NULL && win_form != NULL);
    set_form_win(form, win_form);
    inner = derwin(win_form, form->rows + 1, form->cols + 1, 1, 1);
    assert(inner != NULL);
    set_form_sub(form, inner);

    assert(post_form(form) == E_OK);
    assert(post_menu(menu) == E_OK);

    refresh();
    wrefresh(win_body);
    wrefresh(win_form);

    while (formClose == false)
        process_input(getch());

    delete_form();

}


void validateField(FIELD *field, const char *name)
{
    if (strcmp(name, "AdviceNoteNumber") == 0)
    {
        set_field_type(field,   // Field to alter
                TYPE_ALNUM,     // Type to associate
                0);             // Minimum field width
    }
    else if (strcmp(name, "AssignmentId") == 0 || strcmp(name, "AssignmentReferenceId") == 0
            || strcmp(name, "TransportAssignmentId") == 0)
    {
        set_field_type(field,   // Field to alter
                TYPE_INTEGER,   // Type to associate
                0,              // Number of padding zeroes
                10000,          // Min value
                99999);         // Max value
    }
    else if (strcmp(name, "AuthorityCode") == 0)
    {
        set_field_type(field,   // Field to alter
                TYPE_ENUM,      // Type to associate
                Auth_codes,     // List of values
                0,              // Not case sensitive
                1);             // Unique prefix
    }
    else if (strcmp(name, "ReturnCode") == 0)
    {
        set_field_type(field,   // Field to alter
                TYPE_ENUM,      // Type to associate
                Return_codes,   // List of values
                0,              // Not case sensitive
                1);             // Unique prefix

    }
    else if (strcmp(name, "Priority") == 0)
    {
        set_field_type(field,   // Field to alter
                TYPE_ENUM,      // Type to associate
                Priorities,     // List of values
                0,              // Not case sensitive
                1);             // Unique prefix
    }

【问题讨论】:

  • 如果你专注于一个简单的问题,激光锐利,问题应该很明显。您如何期望set_field_type 准确知道枚举字段中有多少个值?根据set_field_type 的文档,该参数只是char **set_field_type 怎么可能知道您正在传递四个值。还是三个?还是一百亿?一旦你弄清楚缺少什么,你就会确切地知道该怎么做。
  • @SamVarshavchik 不确定我是否遵循您的推理。根据link,set_field_type 和 TYPE_ENUM 的文档明确指出:“接受一组指定字符串中的一个。”。我看不出枚举中有多少值的重要性,如果输入的值不在枚举中,它不应该验证。我还没有检查 curses 库在指定时如何处理枚举,但据我所知,预期结果是输入的值应该存在于枚举中以便能够验证,而不管值的数量是多少?
  • 是的,但是库当然需要知道有多少个值。它需要检查三个枚举值吗?还是十个?还是一千万?如果您只有一个char **,而没有其他信息,您如何解释库如何知道这个char ** 参数正好指向四个字符串?请将您的手指指向代码中执行此操作的行。这就是“枚举中有多少值的重要性”。这是图书馆必须知道的一条非常重要的信息,并且您没有告诉图书馆有多少枚举。没有它,就会产生欢闹。
  • @SamVarshavchik 好的,必须去获取 ncurses (v.5.9) 的源代码来检查 char** 中的值的数量是如何解决的:kp = kwds; while (kp &amp;&amp; (*kp++)) cnt++; argp-&gt;count = cnt; 这就是为什么在调用set_field_type 时没有选项来指定值的数量,它是在被调用的库函数中计算出来的。
  • @SamVarshavchik 我在某种程度上理解您的观点,必须有一种方法让被调用函数知道要评估多少个值,但这不是问题所在。另外,文档中没有提到关于值数量的参数(因为它是在库中计算的),只有 char** keywordsbool checkcasebool checkunique 指定为这种类型的参数。所以你的评论真的不是很有帮助。

标签: c++ ncurses curses


【解决方案1】:
 set_field_type(field,   // Field to alter
            TYPE_ENUM,      // Type to associate
            Priorities,     // List of values
            0,            
            1);             // Unique prefix

set_field_type 的第三个参数是可接受的枚举值列表,指定为 char **

这不能是一些未指定大小的指针列表。显然,可接受的枚举值的数量,这里的指针数量,必须以某种形式或方式定义。 set_field_types 文档中没有明确指出如何定义可接受的枚举值的 number,这只是一个 char ** 参数。但在 C 和 C++ 中,假定指针列表由 NULL 指针终止是公认的做法;教科书对NULL 指针含义的典型定义的一部分在某种程度上落在了这些范围内。 set_field_type 的文档暗示了这一点。

const char* Priorities[]=
{ "3", "5", "6", "8" };

参数是四个char *s 的列表,按原样传递。当它进入set_field_type 时,它只是一些char ** 值。这里没有什么明确定义它为四个指针,所以set_field_type 试图找出有多少枚举值,开始看这里,计数四个指针,然后继续计数,不断计数,进入随机内存,试图解释每个值都是一个接一个的char *,直到它在某个地方遇到它认为是NULL 值的东西,同时尝试将每个中间值解释为char *,指向某个地方。

如果它现在没有崩溃,它将开始看到幻像有效枚举值,导致demons flying out of your nose

【讨论】:

  • 喜欢 Nasal Deamons 的链接!顺便感谢您的帮助,即使我一开始有点慢。它现在就像一个魅力!
  • 没关系。我不介意。如果我只是站出来说,哦,只需在列表末尾添加一个 NULL 指针,您就会认为它是理所当然的,并且对事物的工作原理没有更深入的了解。好吧,现在你知道了,我认为你从这个 excersize 中获得的额外见解将在未来有所帮助。这是我的意图。我不喜欢直接给出答案。我更喜欢帮助其他人自己思考并自己解决所有问题。
猜你喜欢
  • 1970-01-01
  • 2020-06-14
  • 1970-01-01
  • 2011-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-16
相关资源
最近更新 更多