Home PAT 1032 Sharing
Post
Cancel

PAT 1032 Sharing

Link

这道题本身很简单, 但是这里需要记录一下 scanf 读入数字和字符时会出现的问题.

The Secret of scanf

Read Numbers and Characters

使用 scanf 输入时, 输入的字符是送到键盘缓冲区, 然后才根据 scanf 指定的格式读取. 例如 %d 要求读取数字, 那么当遇到不是数字的内容时, 扫描终止. 但是没有接收到的部分并不是被抛弃了, 而是继续保留在缓冲区中, 直到下一次使用 scanf 从缓冲区读数据. 例如输入的是 5s5555, 那么只有第一个 5 能被接收; 如果输入8 555, 那么也只有第一个 8 能被收到.

例如, 下面的代码:

1
2
3
4
5
6
7
8
int main(){
    int num;
    char ch;
    scanf("%d", &num);
    scanf("%c", &ch);
    //or, scanf("%d%c",&num,&ch);
    return 0;
}

当输入一个数字 7 时, 按下回车, 会发现程序立即终止了. 这是因为回车符仍然留在缓冲区中, 然后被 scanf 扫描给 ch.

因此, 最后读入的结果分别是 7\n. 同理, 如果输入是 7 a, 那么读入的结果是 7 和空格 ` `.

解决方法是: scanf("%d %c",&num,&ch) 或者 scanf("%d\n%c",&num,&ch) (分别对应于空格和换行符作为分隔符).

Read C string

scanf 在接收字符串时遇到空格也会终止, 解决方法是限定扫描集合 scanf("%[^\n]",str), 或者用 gets 函数.

例如下面这个程序就可以读取 abcd efg 并且将其完整输出: (其实就是在 %s 中加入 [^\n])

1
2
3
4
5
6
int main(){
    char str[10];
    scanf("%[^\n]s",str);
    printf("%s\n", str);
    return 0;
}

scanf("%*[^\n]%*c", &x):

  • %c: it reads the next character.
  • Asterisk *: is used to indicate that the next character is discarded
  • [^\n] is regular expression that will exclude \n i.e in other words scanf will read all char until you hit enter button.
  • %*[^\n] scans everything until a newline \n (Doesn’t scan \n) and discards it, i.e, doesn’t store the scanned data anywhere. (\n doesn’t get scanned so it still stays in the input buffer to wait for the next scan)
  • %*c then scans and discards the \n character, upto which the first format specifier has scanned. (because %c scans one character, i.e. the first character waiting in the input buffer, that is \n)

So, the above statement will read the data till a newline(\n) is encountered and discard it without saving it anywhere.

scanf("%[^\n]",str) 的例子:

1
2
3
4
5
6
7
8
int main(){
    char str[10];
    int a;
    scanf("%[^\n]s",str);
    scanf("%d",&a);
    printf("%snext%d",str,a);
    return 0;
}

Input:

1
2
abcd e f
12

Output:

1
abcd e fnext12

scanf("%*[^\n]%*c",str) 的例子:

1
2
3
4
5
6
7
8
int main(){
    char str[10];
    int a;
    scanf("%*[^\n]%*c",str); //不会存储str和\n
    scanf("%d",&a);
    printf("%snext%d",str,a);
    return;
}

Input:

1
2
abcd efg
12

Output:

1
next12

scanf("%*[^\n]%*c") 表示跳过一行字符串, 其中 %c 可以把 \n 吸收掉, 防止影响后续输入. 上面的例子就是跳过读入的 str, 只存储 a 的值.

其他的方法还有: 使用 getcharfflush(stdin), 后者是将缓冲区清空.

参考1 参考2

Accepted Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
#include <cmath>
using namespace std;
int head1,head2,n,ans=-1;
struct node{
    int addr,next;
}nodes[100010];
bool v[100010];
int main() {
    scanf("%d%d%d",&head1,&head2,&n);
    int i;
    for(i=1;i<=n;++i){
        int addr,next;
        char data;
        //注意这里!必须加上空格!不然读取会出错!
        scanf("%d %c %d",&addr,&data,&next);
        nodes[addr]={addr,next};
    }
    i=head1;
    while(i!=-1){
        v[i]=true;
        i=nodes[i].next;
    }
    i=head2;
    while(i!=-1){
        if(v[i]){
            ans=i;
            break;
        }
        i=nodes[i].next;
    }
    if(ans==-1) printf("%d\n",ans);
    else printf("%05d\n",ans);
    return 0;
}
This post is licensed under CC BY 4.0 by the author.