C 语言 scanf 函数输入结束标志及注意事项

在 C 语言里,scanf 函数是一个常用的输入函数。不过呢,它在读取输入时会因为一些情况而停止录入,这可能会让输入缓冲区残留一些字符,进而影响后续的输入操作。 scanf 停止录入的情况以及相关注意事项。

1. 数组名作为地址传递给 scanf

在使用 scanf 读取字符串时,我们常常会用到字符数组。要注意啦,数组名本身就代表数组首元素的地址,所以在 scanf 里不需要再加取地址符 &

#include <stdio.h>

int main() {
    char password[19] = {0};
    // 这里 password 本身就是地址,无需加 &
    scanf("%s", password); 
    printf("你输入的密码是:%s\n", password);
    return 0;
}
2. 遇到空白字符停止读取

scanf 在读取 %s 格式的字符串时,会把空白字符(像空格、制表符 \t、换行符 \n 等)当作字符串的结束标志。

#include <stdio.h>

int main() {
    char str[20];
    printf("请输入一个包含空格的字符串:");
    scanf("%s", str);
    // 输入 "hello world",scanf 遇到空格停止,str 只存 "hello"
    printf("你输入的字符串是:%s\n", str); 
    return 0;
}

在这个例子中,当你输入 hello world 时,scanf 遇到空格就不再继续读取了,str 数组里只会存储 hello,而 world 以及后面可能的内容会留在输入缓冲区中。

3. 达到指定的最大宽度停止读取

要是在格式控制字符串里指定了最大宽度,scanf 读取到指定宽度的字符后就会停止。

#include <stdio.h>

int main() {
    char str[20];
    printf("请输入一个字符串:");
    // 指定最大宽度为 5
    scanf("%5s", str); 
    // 输入 "abcdefg",scanf 只读前 5 个字符 "abcde"
    printf("你输入的字符串是:%s\n", str); 
    return 0;
}

这里,如果你输入 abcdefgscanf 只会读取前 5 个字符 abcde 存到 str 数组中,剩下的字符 fg 会留在输入缓冲区。

4. 无法匹配格式控制字符串停止读取

如果输入的内容没办法和格式控制字符串匹配,scanf 也会停止读取。

#include <stdio.h>

int main() {
    int num;
    printf("请输入一个整数:");
    scanf("%d", &num);
    // 输入 "abc",无法转换为整数,scanf 停止
    printf("你输入的整数是:%d\n", num); 
    return 0;
}

当你输入 abc 时,因为 abc 没办法转换成整数,scanf 就会停止读取,并且 abc 会留在输入缓冲区。要是后续还有输入操作,就可能会受到这些残留字符的影响。

5. 遇到文件结束符(EOF)停止读取

在某些情形下,当输入流到达文件结束符时,scanf 也会停止读取。在 Windows 系统中,按下 Ctrl + Z 会产生文件结束符;在 Unix/Linux 系统中,按下 Ctrl + D 会产生文件结束符。

#include <stdio.h>

int main() {
    char ch;
    printf("请输入字符,按 Ctrl+Z(Windows)或 Ctrl+D(Unix/Linux)结束输入:");
    while ((ch = getchar()) != EOF) {
        // 这里可以对输入的字符进行处理
    }
    printf("输入结束\n");
    return 0;
}

在这个例子里,当你按下对应的组合键产生文件结束符时,scanf 或者 getchar 等输入函数就会停止读取。

6. 缓冲区残留字符影响后续输入

由于 scanf 存在上述这些停止录入的情况,可能会让输入缓冲区残留一些字符,从而影响后续的输入操作。

#include <stdio.h>

int main() {
    char str[20];
    int num;
    printf("请输入一个字符串:");
    scanf("%s", str);
    // 这里可能残留换行符在缓冲区
    printf("请输入一个整数:");
    scanf("%d", &num); 
    printf("你输入的字符串是:%s,整数是:%d\n", str, num);
    return 0;
}

在这个例子中,第一个 scanf 读取字符串后,输入缓冲区可能会残留换行符。当执行第二个 scanf 读取整数时,这个换行符可能会对输入造成影响。

7. 清理输入缓冲区

为了保证后续输入的准确性,在需要连续进行输入操作时,通常要清理输入缓冲区。

#include <stdio.h>

int main() {
    char str[20];
    int num;
    printf("请输入一个字符串:");
    scanf("%s", str);
    // 清理输入缓冲区
    while (getchar() != '\n'); 
    printf("请输入一个整数:");
    scanf("%d", &num);
    printf("你输入的字符串是:%s,整数是:%d\n", str, num);
    return 0;
}

这里使用 while (getchar() != '\n'); 来清理输入缓冲区,把缓冲区里的字符一直读取到换行符为止。

8. scanf 的返回值

scanf 函数会返回成功匹配并赋值的输入项的数量。可以通过检查 scanf 的返回值来判断输入是否成功。

#include <stdio.h>

int main() {
    int num;
    int result = scanf("%d", &num);
    if (result == 1) {
        printf("成功输入一个整数:%d\n", num);
    } else {
        printf("输入失败,请输入一个有效的整数。\n");
    }
    return 0;
}

在这个例子中,如果 scanf 成功读取一个整数,它会返回 1;如果输入不匹配,返回值就不是 1。

9. 读取多个输入项

scanf 可以同时读取多个输入项,用空格分隔不同的格式控制符。

#include <stdio.h>

int main() {
    int a, b;
    printf("请输入两个整数,用空格分隔:");
    scanf("%d %d", &a, &b);
    printf("你输入的两个整数是:%d 和 %d\n", a, b);
    return 0;
}

这里 scanf 会依次读取两个整数,分别赋值给 a 和 b

10. 格式控制字符串中的非格式字符

在格式控制字符串中可以包含非格式字符,输入时必须按原样输入这些字符。

#include <stdio.h>

int main() {
    int day, month, year;
    printf("请按 日/月/年 的格式输入日期:");
    // 这里的 / 是非格式字符,输入时要原样输入
    scanf("%d/%d/%d", &day, &month, &year); 
    printf("你输入的日期是:%d 年 %d 月 %d 日\n", year, month, day);
    return 0;
}

在这个例子中,输入时必须按照 日/月/年 的格式,输入对应的数字和 / 字符。

11. 读取字符时的注意事项

在读取字符时,要特别注意输入缓冲区里的换行符等空白字符。

#include <stdio.h>

int main() {
    char ch1, ch2;
    printf("请输入第一个字符:");
    scanf("%c", &ch1);
    // 清理缓冲区的换行符
    while (getchar() != '\n'); 
    printf("请输入第二个字符:");
    scanf("%c", &ch2);
    printf("你输入的两个字符是:%c 和 %c\n", ch1, ch2);
    return 0;
}

这里在读取第二个字符前,先清理了缓冲区的换行符,避免它被当作第二个字符读取。

12. 避免缓冲区溢出

在使用 scanf 读取字符串时,要确保数组有足够的空间,避免缓冲区溢出。

#include <stdio.h>

int main() {
    // 定义一个长度为 10 的字符数组
    char str[10]; 
    printf("请输入一个字符串:");
    // 限制输入长度为 9,留一个位置给字符串结束符 \0
    scanf("%9s", str); 
    printf("你输入的字符串是:%s\n", str);
    return 0;
}

在这个例子中,使用 %9s 限制输入的长度,避免输入的字符串超出数组的大小。

通过以上这些内容,相信你对 scanf 函数的输入结束标志和注意事项有了解。在实际编程中,要注意这些细节,才能让程序更加稳定和健壮。