【问题标题】:sscanf to scan particular size of stringsscanf 扫描特定大小的字符串
【发布时间】:2023-04-05 10:18:01
【问题描述】:

我只想在下面的代码中扫描“sizeof(out)”字符串“out”。 'input' 字符串可以超过 out,因此 out 会造成溢出。格式字符串也可以用 sprintf/snprintf 完成。

#include<stdio.h>
#define BUFSZ 4

int main()
{
  char input[16]="#123 abcdefg";
  int k;
  char out[BUFSZ];

  sscanf(input,"#%d %s",&k,out);
  /* Something like %ns where n is the size of out in above line */ 

  printf("%d\n",k);
  printf("%s\n",out);
  return 0;
}

【问题讨论】:

标签: c overflow printf scanf


【解决方案1】:
#include<stdio.h>

#define BUFSZ 4

#define _S(x) #x
#define S(x) _S(x)

int main(void){
    char input[16]="#123 abcdefg";
    int k;
    char out[BUFSZ+1];

    sscanf(input,"#%d %" S(BUFSZ) "s",&k,out);//field size -1 for End Of String(\0)

    printf("%d\n",k);
    printf("%s\n",out);
    return 0;
}

【讨论】:

    【解决方案2】:

    您需要创建另一个字符串,用作 sscanf 的格式字符串。这允许您将字符串大小 (BUFSZ) 插入到格式字符串中。

      char format_str[20];
    
      sprintf(format_str, "#%%d %%%ds", BUFSZ - 1);
      sscanf(input,format_str,&k,out);
    

    【讨论】:

      【解决方案3】:

      我对上面的解释做了一些扩展,并提供了一些测试用例的可执行解释,以便您查看验证选项。

      #include<stdio.h>
      #define BUFSZ 4
      
      void PrintLine() { printf("---------------------------\n"); }
      
      int MyIntegerScan(const char* input, int * integer, char * outbuf, size_t outbufSize)
      {
          char format_str[20];
          sprintf(format_str, "%s%d%s", "#%d %n%", outbufSize -1 ,"s%n%*s%n");
          //"#%d %n%4s%n%*[^]%n"
          // ^----------------'#'   Character
          //    ^-------------' '   Any ammoutn of whitespace
          //   ^--------------%d    Decimal
          //        ^---------%4s   String Limited to 4 charcters, leave space for terminating zero
          //      ^---^-----^-%n    how many characters were read
          //             ^----%*[^] match anything without storing it
      
          int check0 = 0, check1 = 0, check2 = 0;
      
          printf("input: '%s'\n", input);
          *integer = 0;
          *outbuf = 0;
      
          int count = sscanf(input, format_str, integer, &check0, outbuf, &check1, &check2);
      
          switch (count)
          {
              case 0: printf("did not find number and string\n"); break;
              case 1: printf("did not find string\n"); break;
              case 2: printf("found both\n"); break;
              default: printf("unexpected error during scanf\n"); break;
          }
      
          if (check1 < check2)
              printf("unmatched rest: '%s'\n", input + check1);
      
          if (check1 == check2 && count == 2) 
              printf("length exactly as expected\n");
      
          if (check1 == check2 && count != 2)
              printf("did not fully match\n");
      
          if ((check1 - check0) < (outbufSize - 1) && count >= 2)
              printf("length shorter than expected\n");
      
          printf("matched: '%d' '%s'\n", *integer, outbuf);
          PrintLine();
          return 0;
      }
      
      int main()
      {
          char out[BUFSZ];
          int k;
      
          //I want to have only "sizeof(out)" string 'out' to be scanned in the below code. 
          PrintLine();
          MyIntegerScan("#123 abc", &k, out, BUFSZ); //Happy Path
          MyIntegerScan("#123      abc", &k, out, BUFSZ); //A lot of whitespace
          MyIntegerScan("#123 a", &k, out, BUFSZ); //Input Very Short
          MyIntegerScan("#123 a noise", &k, out, BUFSZ); //Input Very Short Followed by noise
          MyIntegerScan("#123 abcdefg", &k, out, BUFSZ); //Input Too Long
          MyIntegerScan("#123", &k, out, BUFSZ); //Missing Text
          MyIntegerScan("# asdf", &k, out, BUFSZ); //Missing Number
      
          return 0;
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-24
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多