Skip to main content

一些关于读入数据的问题

· 4 min read

1.逗号运算符

使用逗号运算符是为了把几个表达式放在一起。

整个逗号表达式的值为系列中最后一个表达式的值。

从本质上讲,逗号的作用是将一系列运算按顺序执行。

表达式1, 表达式2

求解过程是:先求解表达式 1,再求解表达式 2。整个逗号表达式的值是表达式 2 的值。

最右边的那个表达式的值将作为整个逗号表达式的值,其他表达式的值会被丢弃。

例如:

var = (count=19, incr=10, count+1);

在这里,首先把 count 赋值为 19,把 incr 赋值为 10,然后把 count 加 1,最后,把最右边表达式 count+1 的计算结果 20 赋给 var。上面表达式中的括号是必需的,因为逗号运算符的优先级低于赋值操作符。

2.scanf函数

scanf函数接收输入数据时,遇以下情况结束一个数据的输入:

  • 遇空格、“回车”、“跳格”键。
  • 遇输入结束符。
  • 遇非法输入。

例如:

char str[80]; 

scanf("%s",str);
printf("%s",str);

输入:I love you!
输出:I
原因:scanf遇空格结束读取。

解决方案:

char str[80]; 

scanf("%[^\n]",str); //读到'\n'结束读取
printf("%s",str);

3.cinscanf的返回值

cin

严格的说,cin的返回值是一个错误的说法。

下面两段文字引用自「C++ primer」,可直接跳过。

std::cin >> v1 >> v2

它(指输入运算符 >>)接受一个istream作为其左侧运算对象,接受一个对象作为其右侧对象。它从给定的istream读入数据,并存入给定对象中。与输出运算符类似,输入运算符返回其左侧运算对象作为其计算结果。

while (std::cin >> val)

当我们使用一个istream对象作为条件时,其效果时检测流的状态。如果流是有效的,即流未遇到错误,那么检测成功。当遇到文件结束符(end-of-file),或遇到一个无效输入时(例如读入的值不是一个整数),istream对象的状态会变为无效。处于无效状态的istream对象会使条件变为假。

while(cin >> x)
{
// do something
}

上面的程序会不断的读入值,赋给 xx,直到遇到错误或者结束符。

while (cin >> x, x)
{
// do something
}

上面的程序会不断读入值,赋给 xx,当遇到 xx 为0时结束。

scanf

scanf函数只有在第一个参数为NULL(空指针)的情况下,才可能返回EOF,否则,返回成功格式化并赋值的参数个数( 0 \ge 0)。

End Of File,在电脑的术语缩写通常为 EOF,在作业系统决定资料源无更多的资料可读取, 在stdio.h中 宏定义为-1

int a, b, c;
int m = scanf("%d%d%d", &a, &b, &c);
cout << m << endl;

我们输入 7 8 9 ,那么m=3m = 3
我们输入 7 8 a, 那么m=2m = 2
我们输入 7 a 8, 那么m=1m = 1
我们输入 a 7 8, 那么m=0m = 0
我们输入ctrl + z(同时按住CTRL键和z键),那么m=1m=-1

在竞赛中,我们常使用

while (scanf("%d%d", &a, &b) == 2)
{
// do something
}

或者

while (scanf("%d%d", &a, &b) != EOF)
{
// do something
}

来处理相关数据输入。

4.对于本题的数据

第一种办法

通过getchar函数读取每个数字后面的字符,当读到换行符时结束。

while (scanf("%d", &u, u)){
while (1){
scanf("%d", &v);
// do something
char c = getchar();
if (c == '\n') break;
}
}
第二种办法

使用istringstream

string line;
while (getline(cin, line) && line[0] != '0'){
istringstream data(line); // data 绑定到刚读入的行
data >> u; // 读取起点
while (data >> v){ // 读取指向的点
// do something
}
}

需包含头文件sstream