当数据行具有不同的有效格式时,如何在C++中使用 sscanf
How to use sscanf in C++ when data lines have different valid formats?
如何扫描以下格式的字符串: 名称 id str1 num1 str2 num2
笔记:
- 如果 str1 = "NO",则 num1 有一个值,
- 如果 str1 = "YES",则 num1 没有值
阿里 1 NO 200 NO 100
示例 2:阿里 1 是,否 100
char name [10];
char str1 [4];
char str2 [4];
int id, num1, num2;
sscanf(inputString, "%s %d %s %d %s %d",
name, &id, str1, &num1, str2, &num2 );
当 str1="YES" 时,我有一个问题,str2 没有取正确的值!!
更改为:
char str1 [4];
char str2 [4];
允许 3 个字符加上一个 NULL 终止符。
示例 2 的格式与示例 1 不同,问题来了。您可以将 sscanf 分成两部分,并检查 str1 是否为是。
将输入读取到字符数组时,应始终指定可用空间量!读取字符数组的默认行为是不施加任何限制。这显然是错误的默认值,因为它使缓冲区溢出非常相似。
此外,在读取数据时,应始终验证读取操作是否确实成功:您的第二行与您正在读取的格式不匹配!YES
后,根据格式需要一个整数。也就是说,你想要
if (6 == sscanf(inputString, "%10s %d %3s %d %3s %d",
name, &id, str1, num1, str2, num2)) {
// process the input upon success
}
当然,就个人而言,我宁愿使用std::istringstream
:
if (std::istringstream(inputString) >> std::setw(10) >> name >> id
>> std::setw(3) >> str1 >> num1 >> std::setw(3) >> str2 >> num2) {
// process the input upon success
}
要处理可选值,创建合适的conditional
类型并创建合适的输入运算符会相当容易,例如:
template <int Size>
struct conditional_t {
char* buffer;
int* value;
conditional_t(char* buffer, int& value): buffer(buffer), value(&value) {}
};
template <int Size>
conditional_t<Size> conditional(char (&buffer)[Size], int& value) {
return conditional_t<Size>(buffer, value);
}
template <int Size>
std::istream& operator>> (std::istream& in, conditional_t<Size> value) {
if (in >> std::setw(Size) >> value.buffer && !strcmp(buffer, "NO")) {
in >> *value.value;
}
return in;
}
// ...
if (std::istringstream(inputStream) >> std::skipws >> conditional(name, id)
>> conditional(str1, num1) >> conditional(str2, num2)) {
// ...
}
我认为这很甜蜜。
您无法在
一次调用中可靠地完成工作 sscanf()
. 您必须适应第三列中的值。 因此,您需要执行以下操作:
char name [10];
char str1 [4];
char str2 [4];
int id, num1, num2;
int offset;
// %n conversion specifications do not count towards the return value
if (sscanf(inputString, "%9s %d %3s %n", name, &id, str1, &offset) != 3)
...report problem...
else
{
if (strcmp(str1, "YES") == 0)
{
num1 = 0; // Or other appropriate value
if (sscanf(inputString+offset, "%3s %d", &str2, &num2) != 2)
...report problem...
}
else
{
if (sscanf(inputString+offset, "%d %3s %d", &num1, &str2, &num2) != 3)
...report problem...
}
}
%n
转换报告它出现的字符串中的偏移量。 它不计入 sscanf()
的返回值。
说你有很多变化要处理。 也许您的输入格式设计得不好,或者您可能需要一个更复杂的系统来识别数据的不同格式以及适用的格式。
相关文章:
- 用C++中的sscanf赋值
- 为什么 sscanf 无法从一个字符串中读取uint64_t和字符?
- 具有结构成员char数组的sscanf
- 在 Arduino 上使用 sscanf 会导致与 const char * 不匹配,并且返回值始终相同,尽管输入值不同
- sscanf() 有两个字符串参数
- SSCANF 进入 uint8 阵列失败
- Arduino使用sscanf读取浮点数
- 使用 sscanf 设置结构引用的值
- 如何使用 sscanf 提取浮点数?
- 使用 sprintf 和 sscanf 将给定数字中的所有 0 替换为 5
- SSCANF 无法读取双十六进制
- 切换到新编译器后,SSCANF 的工作方式有所不同
- sscanf 格式参数不起作用
- 具有十六进制值的SSCANF
- 扫描字符 [] 和 int 时 sscanf 中出现错误
- 用C 中的SSCANF解析消息
- C SSCANF实现问题(从文件中读取)
- sscanf(s、"%u" 和 v) 匹配有符号整数
- SSCANF读取1而不是3个浮点
- 从中加载字符串时出现 sscanf 问题