【问题标题】:C: fscanf and character/string sizeC: fscanf 和字符/字符串大小
【发布时间】:2010-09-25 00:09:13
【问题描述】:

我正在使用 fscanf 解析一个文本 (css) 文件。基本目标很简单;我想抽出任何符合这个模式的东西:

@import "some/file/somewhere.css";

所以我使用 fscanf,告诉它读取并丢弃直到 '@' 字符的所有内容,然后存储所有内容直到它达到 ';'特点。这是执行此操作的函数:

char* readDelimitedSectionAsChar(FILE *file)
{
char buffer[4096];

int charsRead;
do
{
    fscanf(file, "%*[^@] %[^;]", buffer, &charsRead);

} while(charsRead == 4095);

char *ptr = buffer;
return ptr;
}

据我所知,我已经创建了一个可以容纳 4095 个字符的缓冲区。但是,我发现事实并非如此。如果我有一个文件包含一个很长的匹配字符串,如下所示:

@import "some/really/really/really/long/file/path/to/a/file";

使用 char[4096] 缓冲区将其截断为 31 个字符。 (如果我用printf检查buffer的值,我发现字符串被剪短了。)

如果我增加缓冲区大小,则会包含更多字符串。我的印象是一个字符占用一个字节(尽管我知道这会受到编码的影响)。我试图了解这里发生了什么。

理想情况下,我希望能够将缓冲区设置为“即时”所需的大小——也就是说,让 fscanf 创建一个足够大的缓冲区来存储字符串。这可以做到吗? (我知道 GNU 的 %as 标志,但这是一个适用于 OS 10.5/10.6 的 Mac 应用程序,我不确定它是否可以在这个平台上运行。)

【问题讨论】:

    标签: c cocoa macos unix gnu


    【解决方案1】:

    您遇到的主要问题是您正在返回一个指向堆栈上本地缓冲区的指针,该缓冲区是悬空的(因此被您进行的下一次调用覆盖)。您还有一个潜在的缓冲区溢出。 您提到了 'a' 选项,这会很有帮助,但不幸的是,它是一个 GNU 扩展,通常不可用。

    其次,你有这个额外的 scanf 选项,&charsRead,因为格式字符串中没有 %,所以它永远不会被写入。所以 charsRead 将永远是随机垃圾——这意味着你循环将(可能)只运行一次,或者(很少)永远循环。尝试类似

    char* readDelimitedSectionAsChar(FILE *file)
    {
        char buffer[4096], term[2] = "", *rv = 0;
        int len = 0;
    
        fscanf(file, "%*[^@]");
        while (term[0] != ';' && !feof(file)) {
            if (fscanf(file, "%4095[^;]%1[;]", buffer, term) > 0) {
                int read = strlen(buffer);
                rv = rv ? realloc(rv, len+read+1) : malloc(read+1);
                strcpy(rv+len, buffer);
                len += read;
            }
        }
        return rv;
    }
    

    这仍然存在问题,因为如果您的内存不足,它会出现异常行为(如果您向它提供一个开头带有 @ 而没有的巨大格式错误的文件,很容易发生这种情况;),

    【讨论】:

      【解决方案2】:

      您的缓冲区是函数的本地缓冲区。您为其分配了一个指针,但是当调用者访问该指针时,缓冲区不再存在。任何事情都有可能发生。

      所以,不要那样做。

      scanf 可能不是适合这项工作的工具。我会改用getcfgets

      char *readDelimitedSectionAsChar(char *buf, size_t n, char firstChar, char lastChar, FILE *f);
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2022-12-17
        • 2014-04-24
        • 2017-01-14
        • 1970-01-01
        • 2015-07-14
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多