为什么在GCC(9.3.0)中仍未实现`gets_s()`? [英] Why `gets_s()` still isn't implemented in GCC (9.3.0)?

查看:288
本文介绍了为什么在GCC(9.3.0)中仍未实现`gets_s()`?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我知道fgets()是用于字符串输入的更常见和更广泛的选择,但是C11已经存在了9年.为什么gets_s()仍然无法工作?

I know fgets() is a more common and widespread option for string input, but C11 has been around for 9 years. Why is gets_s() still out of work?

即使我添加了-std=c11,即使gets_s()应该位于stdio.h中,它也仍然无法正常工作.

Even when I add -std=c11, it still doesn't work, even though gets_s() should be in stdio.h.

推荐答案

因为它是可选的.而gcc背后的人似乎认为包含它是一个坏主意.我不知道它们是如何推理的,但是可以在C标准中找到提示:

Because it's optional. And the persons behind gcc seems to think it is a bad idea to include it. I don't know how they reasoned, but hints can be found in the C standard:

推荐做法

fgets函数允许正确编写的程序安全地处理太长而无法存储在结果数组中的输入行.通常,这要求fgets的调用者注意结果数组中是否存在换行符.考虑使用fgets(以及基于换行符的所有必要处理),而不是gets_s.

The fgets function allows properly-written programs to safely process input lines too long to store in the result array. In general this requires that callers of fgets pay attention to the presence or absence of a new-line character in the result array. Consider using fgets (along with any needed processing based on new-line characters) instead of gets_s.

https://port70.net/~nsz /c/c11/n1570.html#K.3.5.4.1

如果要使用gets_s,请使用另一个编译器.或编写您自己的包装器,但不要称其为gets_s,因为要使其与规格完全相同是非常棘手的.

If you want to use gets_s, then use another compiler. Or write your own wrapper, but don't call it gets_s because it's quite tricky to get it completely identical to the specs.

C标准这样说:

运行时约束

s不得为空指针. n不得等于零,也不得大于RSIZE_MAX.从stdin读取n-1字符时,将出现换行符,文件结尾或读取错误.

s shall not be a null pointer. n shall neither be equal to zero nor be greater than RSIZE_MAX. A new-line character, end-of-file, or read error shall occur within reading n-1 characters from stdin.

如果存在运行时约束冲突,则将s [0]设置为空字符,并从stdin读取并丢弃字符,直到读取换行符,文件结尾或读取错误为止发生.

If there is a runtime-constraint violation, s[0] is set to the null character, and characters are read and discarded from stdin until a new-line character is read, or end-of-file or a read error occurs.

说明

gets_s函数从stdin指向的流中读取最多少于n指定的字符数的一位,并将其读入s指向的数组.在换行符(已被丢弃)之后或文件结尾之后,不会再读取其他字符.丢弃的换行符不计入读取的字符数.在将最后一个字符读入数组之后,立即将空字符写入.

The gets_s function reads at most one less than the number of characters specified by n from the stream pointed to by stdin, into the array pointed to by s. No additional characters are read after a new-line character (which is discarded) or after end-of-file. The discarded new-line character does not count towards number of characters read. A null character is written immediately after the last character read into the array.

如果遇到文件结尾并且没有字符读取到数组中,或者如果在操作过程中发生读取错误,则将s[0]设置为空字符,并且s的其他元素为未指定值.

If end-of-file is encountered and no characters have been read into the array, or if a read error occurs during the operation, then s[0] is set to the null character, and the other elements of s take unspecified values.

这里有一件事根本没有道理.运行时约束是s不应为空指针.在运行时约束违规时,应将s[0]设置为零.但是,如果s是空指针,则操作s[0] = '\0'具有未定义的行为.

There is one thing here that does not make sense at all. A runtime constraint is that s should not be a null pointer. On runtime constraint violoations, s[0] should be set to zero. But the operation s[0] = '\0' has undefined behavior if s is a null pointer.

这是我尝试实现的观点,但是IMO的规范很烂,我不相信这一点.正确处理是很棘手的.

Here is my take on trying to implement it, but IMO the specs are a mess, and I would not trust this. It was tricky to get it right.

char *my_gets_s(char *s, size_t n)
{
    if(!s) return NULL;

    size_t i=0;
    int ch;

    for(i=0; i<n-1; i++) {
        ch = fgetc(stdin);

        // If end-of-file is encountered and no characters have been read into the array,                          
        // or if a read error occurs during the operation, then s[0] is set to the null character                  
        if(ferror(stdin) || (ch == EOF && i == 0)) {
            s[0] = '\0';
            return NULL;
        }

        // If EOF and we have read at least one character                                                          
        if(ch == EOF) {
            s[0] = '\0';
            return s;
        }

        s[i] = ch;

        if(ch == '\n') {
            s[i] = '\0';
            return s;
        }
    }

    while ((ch = getchar()) != '\n' && ch != EOF);
    s[0] = '\0';
    return NULL;
}

这篇关于为什么在GCC(9.3.0)中仍未实现`gets_s()`?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆