What does %[^\n] mean in a scanf() format string

时光毁灭记忆、已成空白 提交于 2021-02-08 08:21:27

问题


I saw on this website that this: fscanf(fin, "%[^\n]", &p); could be used for reading from my input file(fin) into that char type pointer(*p) all the characters until the first enter hit. At some inputs it works properly, but at others it doesn't.

This is the input I should process and I cannot:

(((zahar 100 ou 3) 5 unt 100 nuca 200) 4 (lapte 200 cacao 50 zahar 100)3)20

This is my whole code:

#include <string.h>
#include <stdio.h>
FILE *fin, *fout;
int main()
{
    fin =  fopen("reteta.in", "r");
    fout = fopen("reteta.out", "w");
    char *p;
    p = new char[1001]();
    fscanf(fin, "%[^\n]", &p);
    fprintf(fout, "%s", &p);
    return 0;
}

回答1:


The %[ notation introduces something called a "scanset" which is somewhat like a regular expression (but not as powerful).

In your specific example it means the format specifier instructs scanf to keep scanning characters that match anything except an \n (encountering a non-matching character will terminate the scan).

From the C11 standard:

The conversion specifier includes all subsequent characters in the format string, up to and including the matching right bracket (]). The characters between the brackets (the scanlist) compose the scanset, unless the character after the left bracket is a circumflex (^), in which case the scanset contains all characters that do not appear in the scanlist between the circumflex and the right bracket.


Even comparing it to a regular expression is stretching it: the standard simply says it: "Matches a nonempty sequence of characters from a set of expected characters".


The real problem with your code, spotted by Jonathan Leffler is this:

fscanf(fin, "%[^\n]", &p);
                      ^

Drop the & since you want to pass p, not "the address of p".




回答2:


% introduces a format-specifier, [ means it's a scan-set and opens it, ^ at the first position in the scan set reverses from "match all in" to "match all not in", \n is the new-line character, and ] closes the scan-set.

Thus, it means: Match indefinitely many characters which are not \n and put them into the char[] pointed to by the argument.

That argument thus must have type char*.
&p is exactly one address-of too much, and the buffer pointed to by it (new char[1001]) is infinite orders of magnitude too small.

Restrict the length of the match (by putting 1000 between the scanset and the %).
Alternatively, and far better, use fgets.


Other points:

  1. Your buffer should be stack-allocated, as it is small enough:

    char buf[1001];
    
  2. Alternatively, at least use a smart-pointer so you don't forget to delete [] it:

    std::unique_ptr<char> p = new char[1001];
    
  3. Why do you value-initialize it? That's superfluous. Use new char[1001] instead of new char[1001]().
  4. Don't forget to check the return-value of fscanf, it should be the number of assignments on success.
  5. C++ (and C99) has an implicit return 0; at the end of main.
  6. You really should close all files you opened (fopen->fclose).


来源:https://stackoverflow.com/questions/26597624/what-does-n-mean-in-a-scanf-format-string

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!