fgets
函数的声明如下所示:
char *fgets(char *str, int n, FILE *stream);
这意味着第二个参数应该是一个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);
}
}
这里我使用了 (int)len
看起来不错,但是如果 buffer
存储了一个很长的字符串会怎样?
让我们说:
const char *buffer = "Very long long ..."; /* where length is beyond the range of the `int` type */
我已经声明了 size_t
类型的长度,这在这里没问题,但是如果我将它传递给 fgets
则不行,因为:
conversion to ‘int’ from ‘size_t {aka long unsigned int}’ may alter its value
如果我将它转换为 int
将不适合,因为 int
的大小小于 length
的大小和一些信息将丢失。
也许我在这里遗漏了什么......
我应该如何避免这种情况?
最佳答案
#include <stdio.h>
char *fgets(char * restrict s, int n, FILE * restrict stream);
对于 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);
}
如果代码确实需要读取长 行,考虑ssize_t getline(char **lineptr, size_t *n, FILE *stream);
as defined here .请注意,这是一个非标准的 C 库函数,但它的源代码很容易获得。
关于 fgets()
的迂腐使用,fgets()
返回 NULL
至少有两个原因: End-of-文件和输入错误。现在考虑使用 OP 代码的极端情况
size_t len = strlen("") + 1;
char arr[len];
if ( fgets(arr, (int)len, stdin) == NULL){
和病理情况如
if ( fgets(arr, 0, stdin) == NULL){
if ( fgets(arr, -1, stdin) == NULL){
两者都在 Is fgets() returning NULL with a short bufffer compliant? 进行了讨论
关于c - 如何使用 fgets() 来避免转换它的第二个 int 类型的参数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38434623/