我正在开发三角形计算,并尝试调整sscanf
以忽略空格,换行符\n
和制表符\t
。我该怎么办?
我有:
if(sscanf(str, "{ [ %lf ; %lf ] , [ %lf ; %lf ] , [ %lf ; %lf ] }", &x_1, &y_1, &x_2, &y_2, &x_3, &y_3) == 6)
非常适合以下输入:
1) {[0;0],[19;10],[0;10]}
2) { [ 0 ; 0], [12;0],[0 ;10] }
但不适用于这样的事情
1) {
[
0
;
15
]
, [ 112 ; 0 ] ,[112;15]}
我需要解决什么?
答案 0 :(得分:2)
请注意,sscanf()
默认情况下会忽略空白。格式字符串中的空格与零个或多个空格字符(空格,制表符,换行符)匹配。除了三个转换规范外,所有转换规范都会忽略前导空白-%c
,%[…]
(扫描集)和%n
这三个例外-因此,对于格式字符串中的所有空白,空格和制表符都不会影响转换,除非第一个{
之前有空格(您可以通过在{
之前的格式字符串中添加空格来进行管理)。因此,问题可能不在sscanf()
中,而是在数据中的字符中。
如果要使用fgets()
读取数据,则需要将多行累积到单个字符串缓冲区中。如果您将sscanf()
替换为scanf()
或fscanf()
,则格式字符串将根据需要读取换行符(但是两者都会在右括号}
之后保留任何换行符)由将来的输入操作读取)。当sscanf()
处理数据时,字符串必须包含所有必需的字符,名义上直到}
为止,尽管直到第六个数字的最后一位就足够了。
给出此代码-第三个字符串表示您在第三个多行数据中所说的内容(我假设开头的1)
和2)
加上空格在问题中都是噪音,因为格式字符串不会尝试解析那些字符串):
#include <stdio.h>
static char *data[] =
{
"{[0;0],[19;10],[0;10]}",
"{ [ 0 ; 0], [12;0],[0 ;10] }",
"{\n[\n0\n;\n15\n]\n, [ 112 ; 0 ] ,[112;15]}\n",
};
enum { NUM_DATA = sizeof(data) / sizeof(data[0]) };
int main(void)
{
for (int i = 0; i < NUM_DATA; i++)
{
printf("String: @@%s@@@\n", data[i]);
double x_1 = -9.9, y_1 = -9.9;
double x_2 = -9.9, y_2 = -9.9;
double x_3 = -9.9, y_3 = -9.9;
int rc = sscanf(data[i], "{ [ %lf ; %lf ] , [ %lf ; %lf ] , [ %lf ; %lf ] }",
&x_1, &y_1, &x_2, &y_2, &x_3, &y_3);
printf("rc = %d: ", rc);
printf(" 1 = (%.1lf,%.1lf)", x_1, y_1);
printf(" 2 = (%.1lf,%.1lf)", x_2, y_2);
printf(" 3 = (%.1lf,%.1lf)", x_3, y_3);
putchar('\n');
}
return 0;
}
我得到输出:
String: @@{[0;0],[19;10],[0;10]}@@@
rc = 6 1 = (0.0,0.0) 2 = (19.0,10.0) 3 = (0.0,10.0)
String: @@{ [ 0 ; 0], [12;0],[0 ;10] }@@@
rc = 6 1 = (0.0,0.0) 2 = (12.0,0.0) 3 = (0.0,10.0)
String: @@{
[
0
;
15
]
, [ 112 ; 0 ] ,[112;15]}
@@@
rc = 6 1 = (0.0,15.0) 2 = (112.0,0.0) 3 = (112.0,15.0)
如您所见,所有三个扫描操作均成功。这表明您认为您作为第三(多行)字符串所拥有的并不是您真正拥有的。
我建议对失败的数据进行逐字节转储,以查看问题出在哪里。另请注意,我捕获并打印了sscanf()
的返回值;这将帮助您确定错误字符的位置。另外请注意,sscanf()
无法告诉您它未能与格式字符串中的最后]
或}
匹配-您永远不会知道它们是否与当前匹配格式。
答案 1 :(得分:0)
如评论中所述,fgets
并不能使您获得全部收益,而一次只能获得一行收益。作为连接多个fgets
的替代方法,如何按字符处理输入的char并使用}
作为终止:
#include <stdio.h>
size_t get_tuple(char s[], size_t sz)
{
int c;
size_t i = 0;
while (i < sz-1) {
c = getchar();
if (c == EOF) {
break;
}
else {
if (c != ' ' && c != '\t' && c != '\n') {
s[i] = (char) c;
++i;
if (c == '}') {
break;
}
}
}
}
if (i < sz) {
s[i] = '\0';
}
return i;
}
int main(void)
{
char s[512];
double x_1, x_2, x_3, y_1, y_2, y_3;
size_t len;
len = get_tuple(s, 512);
while (len > 0) {
printf("%s\n",s);
if(sscanf(s, "{ [ %lf ; %lf ] , [ %lf ; %lf ] , [ %lf ; %lf ] }", &x_1, &y_1, &x_2, &y_2, &x_3, &y_3) == 6) {
printf("read: x_1=%f, y_1=%f, x_2=%f, y_2=%f, x_3=%f, y_3=%f\n", x_1, y_1, x_2, y_2, x_3, y_3);
}
else {
printf("scanf failed\n"); /* error */
}
len = get_tuple(s, 512);
}
return 0;
}
{[0;0],[19;10],[0;10]}
{ [ 0 ; 0], [12;0],[0 ;10] }
{
[
0
;
15
]
, [ 112 ; 0 ] ,[112;15]}
$ ./main<test.txt
{[0;0],[19;10],[0;10]}
read: x_1=0.000000, y_1=0.000000, x_2=19.000000, y_2=10.000000, x_3=0.000000, y_3=10.000000
{[0;0],[12;0],[0;10]}
read: x_1=0.000000, y_1=0.000000, x_2=12.000000, y_2=0.000000, x_3=0.000000, y_3=10.000000
{[0;15],[112;0],[112;15]}
read: x_1=0.000000, y_1=15.000000, x_2=112.000000, y_2=0.000000, x_3=112.000000, y_3=15.000000