简体   繁体   English

scanf()中的缓冲区溢出

[英]Buffer overflow in scanf()

I was looking online for solution for this problem with no result. 我在网上寻找解决此问题的方法,但没有结果。 I'm trying to do while loop to read only characters using scanf(). 我正在尝试使用whilef循环使用scanf()仅读取字符。 If user type more than 3 characters than it will display error. 如果用户键入的字符超过3个,则会显示错误。

However, my code works partially if I type 3 characters and press enter it works without executing loop this is what I want. 但是,如果我键入3个字符并按Enter,则我的代码将部分起作用,而无需执行循环,这就是我想要的。 If I type 4 characters and press enter also works it executes loop and says "too long" same for 5 char + enter also what I want. 如果我键入4个字符并按Enter也可以执行循环,并说“太长”(与5个字符相同),请输入我想要的内容。

However, if I type 7 characters and enter it executes loop and exits program right away. 但是,如果我键入7个字符并输入,则会执行循环并立即退出程序。 Any advice? 有什么建议吗?

Ps. 附言 I apologize for any grammar error but English is my second language. 对于任何语法错误,我深表歉意,但英语是我的第二语言。

#include<stdio.h>
int main(){
char alo;
char alo1; 
char alo2; 
char alo3;

printf("enter 3 characters: ");
scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 

while(alo3!='\r' && alo3!='\n'){
    printf("too long \n");
    printf("enter ");       
    scanf(" %c %c %c%c", &alo, &alo1, &alo2, &alo3); 
}   
return 0;
}

Using scanf() only 仅使用scanf()

Using just scanf() to achieve this requires a certain amount of jiggery-pokery. 仅使用scanf()即可实现这一目标,需要一定量的拼图游戏。 It isn't the best way to code it, but… 这不是最好的编码方式,但是…

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;

    printf("enter 3 characters: ");

    while (scanf(" %c %c %c%c", &alo0, &alo1, &alo2, &alo3) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;
        printf("too long\n");
        printf("enter 3 characters: ");
    }

    printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    return 0;
}

The while() condition uses scanf() to read four characters, skipping white space before the first three. while()条件使用scanf()读取四个字符,在前三个字符之前跳过空格。 Note that it is OK to put newlines in between characters; 注意,可以在字符之间插入换行符。 scanf() doesn't care. scanf()不在乎。 If you want line-based input, scanf() is simply the wrong tool for the job! 如果您需要基于行的输入,那么scanf()就是该工作的错误工具! However, assuming that 4 characters are read and the fourth is neither carriage return nor newline, then the code uses: 但是,假设读取了4个字符,而第四个字符既不是回车也不是换行符,则代码使用:

        char buffer[4096];
        if (scanf("%4095[^\n]", buffer) == EOF)
            break;

to read any characters up to, but not including, a newline. 读取直到但不包括换行符的任何字符。 It doesn't mind if there are no such characters so scanf() returns 0. The code then prompts you to enter the correct data and goes around to the main scanf() . 不介意是否没有这样的字符,所以scanf()返回0。然后代码提示您输入正确的数据并转到主scanf() This skips the newline that was left behind and then looks for three characters again. 这将跳过留下的换行符,然后再次查找三个字符。

When the while loop exits, it could be because it got three characters and a newline, or because it got fewer characters and EOF, or because the clean-up scanf() detected EOF. while循环退出时,可能是因为它具有三个字符和一个换行符,或者是因为它具有较少的字符和EOF,或者是由于清理scanf()检测到了EOF。 The code doesn't attempt to distinguish between these (but it should) and simply prints out three values. 该代码不会尝试区分这些(但应该),而只是打印出三个值。 Fixing that is not dreadfully hard; 修复并不困难; simply assign the return from each scanf() to a variable and then test that after the loop: 只需将每个scanf()的返回值分配给一个变量,然后在循环后进行测试:

int rc;
while ((rc = scanf(…)) == 4 && …)
{
    …
    if ((rc = scanf(…)) == EOF) 
        break;
    …
}

if (rc == 4)
    printf(…);
else
    printf("Didn't get 3 characters as requested\n");

Using fgets() for line input 使用fgets()进行行输入

Personally, I think it is easier/better to use fgets() and sscanf() like this: 就个人而言,我认为使用fgets()sscanf()这样更容易/更好:

#include <stdio.h>

int main(void)
{
    char alo0;
    char alo1;
    char alo2;
    char alo3;
    char buffer[4096];
    int rc = 0;

    printf("enter 3 characters: ");

    while (fgets(buffer, sizeof(buffer), stdin) != 0 &&
           (rc = sscanf(buffer, " %c %c %c%c", &alo0, &alo1, &alo2, &alo3)) == 4 &&
           alo3 != '\r' && alo3 != '\n')
    {
        printf("too long\n");
        printf("enter 3 characters: ");
        // In case you get 4 characters but the 4th was not a newline
        // and then you get EOF
        rc = 0;
    }

    if (rc == 4)
        printf("Got [%c][%c][%c]\n", alo0, alo1, alo2);
    else
        printf("Didn't get 3 characters as requested\n");
    return 0;
}

This could report the string that was too long, or otherwise incorrect. 这可能会报告字符串太长或不正确的字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM