【问题标题】:How fscanf know this is the end of the line?fscanf 如何知道这是行尾?
【发布时间】:2013-12-21 16:46:28
【问题描述】:

如果文件中的字符串是,我从文件中读取字符串:

 "User1 User2 User3 User4 User5"
 "test1"

我只想读取文件的第一行,我的代码是:

 if (in_fp != NULL)
 {
   while (fscanf(in_fp, "%s", &user)!=EOF)
    {
      temp = (char*)malloc(sizeof user);
      strcpy(temp,user);
     }
 fclose (in_fp);
 }

但问题是 fscanf 还从文本文件中读取了“test1”,我需要知道如何让他知道这是行尾,我需要在我的代码中修复什么? 我知道 fgets,但我想分别阅读每个用户

【问题讨论】:

  • fscanf 函数不知道行尾。阅读fgets
  • 哦,你的代码中有很多内存泄漏。
  • 我现在正在编辑我的帖子,我知道 fgets,我想分别读取每个用户的临时权限
  • 你可以结合例如fgetssscanf.

标签: c


【解决方案1】:

一种方式

    if (in_fp != NULL){
        while (fscanf(in_fp, "%s%c", user, &ch)==2){
            temp = (char*)malloc(sizeof user);
            strcpy(temp, user);
            //do something
            printf("%s\n", user);
            free(temp);
            if(ch == '\n')
                break;
        }
        fclose (in_fp);
    }

【讨论】:

  • @BLUEPIXY 不错。我打算修改关于使用 %c%[] 来实现 OP 目标的帖子,但我看到你已经很好地得到了这样的答案。
【解决方案2】:

使用fscanf("%s") 和变体格式是解决此任务的艰难方法。

%s 不分青红皂白地使用包括' ''\n' 在内的前导空格,但OP 将这两个明确地用作用户名 分隔符和记录 分隔符。更好地读取一行,使用fgets(),然后解析读取的缓冲区。

OP 担心未知的行长。虽然最好不要将代码限制为仅使用短行,但将代码设计为使用无休止的行也有问题。过长的行增加了错误数据或恶意黑客攻击的迹象。如果数据文件试图超过它,最好分配一个大缓冲区并优雅地抱怨。

size_t N = 4096;
char *buffer = malloc(N);
if (buffer == NULL) ...
while (fgets(buffer, N, in_fp) != NULL) {
  size_t Len = strlen(buffer);
  if (Len == 0 || buffer[Len-1] != '\n) {
    HandleUnacceptbaleBuffer();
  }
  // parse buffer via sscanf, strtok, etc.
  char *p = buffer;
  int n
  while (1 == sscanf(p, "%s%n", &user, &n)) {
    Handle(user);
    p += n;
  }
}
free (buffer);

【讨论】:

    【解决方案3】:

    你没有。

    你也不想使用scanf()。像瘟疫一样避免它。

    如果你想读行,那么使用fgets()。 (即使不想读行也可以使用,还是比scanf()好很多)。


    我看到“但我想分别阅读每个单词”的问题。所以,你来了:

    char buf[LINE_MAX];
    if (!fgets(buf, sizeof buf, stdin)) {
        // handle error
    }
    
    char *p = buf, *s = p;
    while (p) {
        p = strtok_r(s, " ", &s);
        // do stuff with `p` if it's not NULL
    }
    

    另外,do NOT cast the return value of malloc()!

    【讨论】:

    • 感谢您的链接。我不知道第一行的最大长度,这就是我在 fscanf 中使用的原因,我需要从文件中读取并在我需要知道的文本中的第二行时停止
    • @user2976686 如果该行长于MAX_LINE(理论上不可能这样),那么要么使用fread()将整个文件读入内存并替换第一个'\n'使用 NUL 字符,或使用动态内存分配、指数存储扩展和fgetc()
    • ,嗨,我的问题是我不知道最大线的长度是多少!
    • 对不起,我还是不明白你的回答:(
    • @H2CO3 getline() 由 POSIX 指定,虽然是 glibc 的一部分
    猜你喜欢
    • 2010-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-28
    • 2012-04-30
    • 1970-01-01
    • 2015-09-14
    • 1970-01-01
    相关资源
    最近更新 更多