fgets函数的声明如下所示:
char *fgets(char *str, int n, FILE *stream);
Run Code Online (Sandbox Code Playgroud)
这意味着第二个参数应该是一个int.
在以下程序中哪种方法可以避免这种转换?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
const char *buffer = "Michi";
size_t len = strlen(buffer) + 1;
char arr[len];
printf("Type your Input:> ");
if (fgets(arr, (int)len, stdin) == NULL) {
printf("Error, fgets\n");
exit(1);
} else {
printf("Arr = %s\n", arr);
}
}
Run Code Online (Sandbox Code Playgroud)
在这里,我使用(int)len哪个看起来很好,但如果buffer存储一个很长的字符串会发生什么?
让我们说:
const char *buffer = "Very long long ..."; /* where length is beyond the range of the `int` type */
Run Code Online (Sandbox Code Playgroud)
我已经声明了这种类型的长度size_t,但是如果我将它传递给fgets不好,因为:
conversion to ‘int’ from ‘size_t {aka long unsigned int}’ may alter its value
Run Code Online (Sandbox Code Playgroud)
如果我把它投射到int不适合因为它的大小int小于大小,length一些信息将丢失.
也许我在这里遗漏了一些东西......
我怎么能避免这种情况?
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
Run Code Online (Sandbox Code Playgroud)
使用时fgets(),s[INT_MAX]无法使用输入缓冲区和更高版本.
OP的size_t len代码可能避免int的投len通过转换为字符串,并转换回一个int,那就是浪费.演员表演是正确的.
而不是乱丢代码(int),减少/控制其使用并将强制转换包装在限制辅助函数中.
int fgets_len(size_t len) {
return (len < INT_MAX) ? (int) len : INT_MAX;
}
size_t len = something_big;
char *arr = malloc(len);
...
if ( fgets(arr, fgets_len(len), stdin) == NULL){
printf("Error, Fgets\n");
exit(1);
}else{
printf("Arr = '%s'\n", arr);
}
Run Code Online (Sandbox Code Playgroud)
如果代码确实需要读取长行,请考虑此处ssize_t getline(char **lineptr, size_t *n, FILE *stream);定义的.请注意,这是一个非标准的C库函数,但其源代码随时可用.
关于迂腐使用fgets(),至少有两个原因fgets()要归还NULL:文件结束和输入错误.现在考虑使用OP代码的角落情况
size_t len = strlen("") + 1;
char arr[len];
if ( fgets(arr, (int)len, stdin) == NULL){
Run Code Online (Sandbox Code Playgroud)
和病理情况一样
if ( fgets(arr, 0, stdin) == NULL){
if ( fgets(arr, -1, stdin) == NULL){
Run Code Online (Sandbox Code Playgroud)
在fgets()中讨论两者都返回NULL并且符合短缓冲器吗?