Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/cocoa/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C:fscanf和字符/字符串大小_C_Cocoa_Macos_Unix_Gnu - Fatal编程技术网

C:fscanf和字符/字符串大小

C:fscanf和字符/字符串大小,c,cocoa,macos,unix,gnu,C,Cocoa,Macos,Unix,Gnu,我正在使用fscanf解析一个文本(css)文件。基本目标很简单;我想找出任何符合此模式的内容: @导入“some/file/somewhere.css” 所以我使用fscanf,告诉它读取并丢弃所有字符,直到一个“@”字符,然后存储所有字符,直到它到达一个“;”性格以下是执行此操作的函数: char* readDelimitedSectionAsChar(FILE *file) { char buffer[4096]; int charsRead; do { fscanf(file,

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

@导入“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个字符。然而,我发现事实并非如此。如果我有一个文件包含一个匹配的长字符串,如下所示:

@导入“some/really/really/long/file/path/to/a/file”

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

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


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

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

所以,不要这样做

而且
scanf
可能不是适合这项工作的工具。我会尝试
getc
,或者
fgets

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

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

所以,不要这样做

而且
scanf
可能不是适合这项工作的工具。我会尝试
getc
,或者
fgets

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

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

其次,您有这个额外的选项来扫描,
&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;
}

这仍然是一个缺陷,因为如果内存不足,它会出现异常行为(如果您将一个巨大的格式错误的文件以@开头,没有;),那么很容易发生这种情况,

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

其次,您有这个额外的选项来扫描,
&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;
}
这仍然是一个缺陷,因为如果内存不足,它将表现不正常(如果您向它提供一个巨大的格式错误的文件,文件开头有@,没有;,则很容易发生这种情况)