简体   繁体   English

在fscanf中使用=作为分隔符匹配两个字符串

[英]Match two strings with = as separator in fscanf

My aim is to extract the value and a key separated by an = . 我的目的是提取值和由=分隔的键。 My initial idea was to use something like %s=%s , but unfortunately it doesn't work. 我最初的想法是使用%s=%s%s=%s东西,但是不幸的是它不起作用。

So I have a file: 所以我有一个文件:

A=1
B=2

So I open the file: 所以我打开文件:

char *key;
char *value;

FILE* file = fopen("./file", "r");
do {
  fscanf(file, "%[^'=']=%[^'\n']\n", key, value);
  printf("key:%s value:%s\n", key, value);
} while(!feof(file));

However both key and value return: 但是键和值都返回:

key:1 value:1
key:2 value:2

Any idea why my expression is not matching?. 知道我的表情为什么不匹配吗?

key and value variables must be allocated, eg 必须分配keyvalue变量,例如

char key[100];
char value[1000];

Then use them. 然后使用它们。

char key[16];//char *key;//not point to memory for store.
char value[16];

FILE *file = fopen("./file", "r");
while(2==fscanf(file, " %[^=]=%[^\n]", key, value)){
  printf ("key:%s value:%s\n", key, value);
}

Your pointers are uninitialized. 您的指针未初始化。 Reading them is undefined in C. You can use arrays (if you know the maximal lengths at compile-time) or allocate memory with malloc . 读取它们在C中是未定义的。您可以使用数组(如果知道编译时的最大长度)或使用malloc分配内存。

Read the *scanf documentation carefully, these functions are a little tricky. 仔细阅读*scanf文档,这些功能有些棘手。

"%s=%s" cannot match, %s consumes all = signs so the following = is always a matching failure (the next character after %s is always a whitespace or EOF). "%s=%s"无法匹配, %s消耗了所有=符号,因此以下=始终是匹配失败( %s之后的下一个字符始终是空格或EOF)。

When reading strings, always use a maximum field width (in some cases, it can be omitted safely, but only for sscanf ). 读取字符串时,请始终使用最大字段宽度(在某些情况下,可以安全地将其省略,但仅适用于sscanf )。 Unfortunately, you have to hard-code that value (or build up the format string at run-time, but I wouldn't advise you to do so). 不幸的是,您必须对该值进行硬编码(或在运行时构建格式字符串,但我不建议您这样做)。

I'm not sure what the ' in the scan sets are supposed to do, %[^'='] is equivalent to %[^'=] and matches everything but ' and = . 我不确定扫描集中的'应该做什么, %[^'=']等同于%[^'=]并匹配'=所有内容。 You've probably meant %[^=] . 您可能是说%[^=]

Every white-space character in the format string (outside a scan set) is treated equally as "skip any white-space", that is, a space ( 格式字符串中(扫描集之外)的每个空格字符均被视为“跳过任何空格”,即空格( ) is the same as a newline. )与换行符相同。 The whole format string is equivalent to 整个格式字符串等效于

"%[^'=]=%[^'\n] " // Note the space at the end

To match a literal newline, you need to use a scanset (with a length). 要匹配文字换行符,您需要使用扫描集(具有长度)。

Always check the return value of *scanf (also for fopen and any other function which can fail). 始终检查*scanf的返回值(也用于fopen和任何其他可能失败的函数)。

char key[64];   // Or whatever is appropriate for you,
char value[64]; // remember the 0-terminator needs one byte

FILE *file = fopen("./file", "r");
if(!file) {
    perror("./file");
    exit(1);
}
for(;;) {
    int e = fscanf(file, "%63[^=]=%63[^\n]%1[\n]", key, value, (char[2]){ 0 });
    if(e == -1) {
        if(ferror(file)) {
            perror("reading from ./file");
            // handle read error
        } else { // EOF reached on first character of line
            break;
        }
    } else if(e < 3) {
        // handle invalid input
    } else {
        printf("key:%s value:%s\n", key, value);
    }
}

Alternatively, you could use assignment-suppression for the last newline as in "%63[^=]=%63[^\\n]%*1[\\n]" and omit the last argument to fscanf . 或者,您可以对最后一个换行符使用赋值抑制,如"%63[^=]=%63[^\\n]%*1[\\n]"并省略fscanf的最后一个参数。 By doing so, you can no longer detect if the last line ended in a newline. 这样,您将无法再检测最后一行是否以换行符结尾。

My initial idea was to use something like %s=%s , but unfortunately it doesn't work. 我最初的想法是使用%s=%s%s=%s东西,但是不幸的是它不起作用。

Thats simply because *scanf does not respect non-whitespace delimiters as you suspected. 那仅仅是因为*scanf 不像您怀疑的那样尊重非空白定界符。 Furthermore, it does not support real regular expressions. 此外,它不支持真正的正则表达式。 Only a certain simple type of character classes [..] are supported. 仅支持某些简单类型的字符类[..]

To your problem: 给你的问题:

key and value have to be allocated static or dynamic, the rest can be simplified and written without fscanf (your input is obviously line-oriented), which might get you into trouble at some point : keyvalue必须静态或动态分配,其余的可以简化和编写而无需fscanf (您的输入显然是面向行的),这可能会在某些时候给您带来麻烦

  ...
  FILE* fh = fopen("file", "r");
  char buffer[1024]; /* line buffer for reading file if file is line-oriented */

  while( fgets(buffer, sizeof(buffer), fh) ) {
     char key[256], val[256];
     sscanf(buffer, "%[^=]=%[^\n]", key, val);
     printf("key:%s val:%s\n", key, val);
  } 
  fclose(fh);
  ...

Edit the length of the scan buffers ( key[256] , val[256] ) depending on your input. 根据您的输入,编辑扫描缓冲区的长度( key[256]val[256] )。

// sample working code
#include<stdio.h>
#include<stdlib.h>

int main(void) {

    FILE* file = fopen("./file", "r");

    if(NULL == file) {
        printf("Failed to open file\n");
        return EXIT_FAILURE;
    }

    do {
        char key[256];
        char value[256];
        fscanf(file, "%[^'=']=%[^'\n']\n", key, value);
        printf("key:%s value:%s\n", key, value);
    }while(!feof(file));

    fclose(file);

    return EXIT_SUCCESS;
} // End of main()

Sample Output: 样本输出:

key:A value:1
key:B value:2
key:C value:3

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM