【发布时间】:2017-11-19 02:06:16
【问题描述】:
我正在尝试了解在 terminfo 的参数化字符串解析器中 %d 编码的行为。相关的手册页是 here 并指出 -
%[[:]flags][width[.precision]][doxXs]
as in printf, flags are [-+#] and space. Use a ":" to allow the
next character to be a "-" flag, avoiding interpreting "%-" as an
operator.
但没有说明从哪里打印值以及如何处理边缘情况。它们是来自堆栈还是来自传递给参数化字符串的参数?另外,当传递额外的参数(参数化字符串中不等于%d)或存在额外的%d(参数化字符串不正确?)时会发生什么?那是未定义的行为或实现定义或在某处定义定义?
我试图通过手动编写一些有效和无效的字符串并验证输出来检查某些情况,但到目前为止一切都有些不一致,所以我在这里看不到模式 -
#include <iostream>
#include <curses.h>
#include <term.h>
using namespace std;
int main() {
// single %d prints single argument
// => 2
auto res = tparm("[%d]", 2);
cout << res << endl;
// single %d prints single argument and ignores additional
// => 2
res = tparm("[%d]", 2, 3, 4);
cout << res << endl;
// multiple %d prints 0 for absent additional arguments
// => 2-0-0-0
res = tparm("[%d-%d-%d-%d]", 2);
cout << res << endl;
// multiple %d prints with equal number of arguments prints
// first two correctly and rest 0
// => 2-3-0-0-0
res = tparm("[%d-%d-%d-%d-%d]", 2,3,4,5,6);
cout << res << endl;
// single value pushed to stack prints from stack
// => 2
res = tparm("[%p1%d]", 2);
cout << res << endl;
// single value pushed to stack prints from stack and ignores extra arguments
// => 2
res = tparm("[%p1%d]", 2,3,4);
cout << res << endl;
// single value pushed to stack prints from stack and additional prints are 0
// if no arguments are provided
// => 2-0-0
res = tparm("[%p1%d-%d-%d]", 2);
cout << res << endl;
// single value pushed to stack prints from stack and additional prints 0
// even if equal arguments are provided
// => 2-0-0
res = tparm("[%p1%d-%d-%d]", 2,3,4);
cout << res << endl;
// single value pushed to stack prints from stack after pop()?
// => 100-<garbage>
res = tparm("[%p1%d-%c]", 100);
cout << res << endl;
// pushed to stack via {} and equal arguments provided, prints all
// => 2-1-100-200
res = tparm("[%{1}%{2}%d-%d-%d-%d]", 100, 200);
cout << res << endl;
// pushed to stack via {} and %p1 equal arguments provided
// prints only stack and rest 0
// => 100-2-1-0
res = tparm("[%{1}%{2}%p1%d-%d-%d-%d]", 100, 200);
cout << res << endl;
}
【问题讨论】:
-
它是C还是C++?
-
“未定义的行为”和“实现定义的行为”有什么区别?
-
@ScottHunter 无关紧要,因为两种语言都可以使用 tparm()。我写了未定义的行为,因为我在某些参数组合上遇到了 ncurses 的分段错误.. 字符串但是当我在其他一些实现(其他语言的另一个库)上尝试相同的事情时,它给出了完全不同的结果(因此它可能是错误的或正在使其实现定义的行为)。
标签: c++ c ncurses curses terminfo