terminfo参数化字符串%d的编码行为
terminfo parameterized string %d encoding behavior
我正在尝试理解terminfo的参数化字符串解析器中%d
编码的行为。相关的手册页在这里,并指出-
%[[:]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;
}
在您的示例中注意到的一个问题是,它们执行未定义的行为。terminfo的定义的行为使用显式参数令牌(如%p1
)将推送参数传递到堆栈上,在堆栈中可以由运算符(如%d
)弹出推送参数。由于缺乏这一点,您将依赖于ncurses的termcap解决方案(它没有参数标记),而这将立即生成类似的表达式
res = tparm("[%d-%d-%d-%d]", 2);
尝试从参数列表中读取多个参数。您的示例给出了一个,因此您处于C语言未定义行为的领域(即,可变长度参数列表中的参数数量错误)。如果您的调用传递了额外的参数,则可能可以(例如,请参阅Visual C接受错误数量的参数?),但如果传递的参数较少,则结果可能是访问参数列表之外的内存。
回应评论:ncurses允许在没有%p1
的情况下使用%d
。但它会计算参数的数量,在进行实际替换之前列出这些参数。由于它将这些参数作为可变长度的参数列表进行处理,因此无法确定应用程序是否为给定字符串传递了错误数量的参数。
进一步阅读:
tiparm
、tparm
和tputs
等,诅咒数据库终端的接口tparm
的源,例如
/**分析字符串以查看我们需要从varargs列表中获得多少参数,*以及它们的类型。只有当字符串参数*在显式参数引用(例如。,*%p2%s)。所有其他参数都是数字。**"number"粗略地计算我们在字符串中看到的pop的数量,并且*"popcount"显示字符串中的最高参数编号。我们希望*简单地使用后一个计数,但如果我们正在读取termcap字符串*可能是我们看不到显式参数数字的情况。*/
以及tc_BUMP等功能,这些功能适应了termcap缺少参数令牌的情况。
相关文章:
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- 在卡萨布兰卡形成编码参数的列表
- 如何对要用于模板参数的类型列表进行编码
- 如何在 C/C++ 中使用用户定义的参数对库进行编码
- terminfo参数化字符串%d的编码行为
- 通过c++主字符**参数处理不同字符串编码的正确方法是什么
- 硬编码参数与从文件加载
- 如何判断参数何时来自硬编码数字
- constexpr 函数和硬编码参数
- 获取url参数值以某种格式编码
- 将命令行参数从Java传递到c++编码
- 面试编码-将指向节点结构的指针作为参数,并返回传入数据结构的完整副本
- 通过输出参数返回结果,c++编码标准
- 是否有任何语法硬编码向量作为参数
- 删除函数定义中未使用的参数名称(编码标准)
- 我怎么能得到QT主函数argv参数作为unicode编码格式