c - 如何使用 fgets() 来避免转换它的第二个 int 类型的参数?

标签 c casting

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< 来避免 lenint 转换,那太浪费了。强制转换是正确的做法。

与其使用 (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/

相关文章:

java - 如何在java中动态创建类的实例?

C动态加载文件太短?

c - 这是什么意思?

c++ - 没有 typedef 的结构 - 不能在指向成员的指针中使用

string - 在 Swift 中将 Int 转换为 String

c++ - 当我们进行向下转型时内部会发生什么?

c - 从目录读取图像,同时将图像复制到同一目录

c - 我将如何编写只接受某些字符的 scanf() 语句?

c - 错误 : undeclared function

c++ - 将尾调用 void (i32, ...) bitcast 转换为 llvm::Function 以获取 FnAttribute