首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C格式规范尺寸

C格式规范尺寸
EN

Stack Overflow用户
提问于 2019-01-09 00:02:00
回答 3查看 292关注 0票数 0

如何访问字符数组中的整数值?

代码语言:javascript
复制
char a = 'A';
int b = 90;
char * c = "A String";
snprintf(output_buffer, 1024, "%c%d%s, a,b,c);`

%d格式说明符将有多少字节(我假设4字节?)在这个字符数组中,如何访问整数值b?

我试过:

代码语言:javascript
复制
int x = *((int *) &output_buffer[1]

但没有成功。

代码语言:javascript
复制
short x; 
sscanf(&output_buffer[1], "%d", &x);
printf("%d\n",x);`

char *buffer; 
sscanf(&output_buffer[3], "%s", buffer);
printf("%s\n",buffer);`
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-01-09 00:58:09

在回答您最初的问题“"%d"将使用多少个字符?”时,您可以对snprintf使用一个技巧,方法是将缓冲区指定为NULL,将字符数指定为0,然后使用"%d"格式字符串和变量bsnprintf将返回转换所需的数字数。

代码语言:javascript
复制
    req = snprintf (NULL, 0, "%d", b);
    printf ("required digits: %d\n", req);

它将输出"required digits: 2"。(“如果有足够的空间,将被写入最终字符串的字符数(不包括终止空字节)”)。这在为buffer动态分配存储时非常有用。实际上,您只需提供完整的格式字符串,所有变量和snprintf都将返回所需的字符总数(向该字符中添加nul终止字符的+1 )。

从最后几条评论来看,我认为您希望从90内部将int读入buffer中。这样做很简单。

与其简单地尝试使用buffer中的第二个字符(例如,buffer[1])进行转换,不如从缓冲区中的第一个字符开始,然后向前扫描直到找到第一个数字。(如果有显式有符号值,也可以检查'+/-' )。

要在buffer中向前扫描以找到第一个数字,您可以遍历buffer中的字符(使用索引,例如buffer[x],或者使用指针,例如,char *p = buffer;和递增p++),并检查每个字符是否是数字。虽然您可以简单地使用if ('0' <= *p && *p <= '9'),但ctype.h头提供了isdigit()宏,这使得这非常容易。要找到第一个数字,您可以这样做:

代码语言:javascript
复制
#include <ctype.h>  /* for isdigit */
...
char buffer[MAXC] = "",  /* buffer to hold a, b, c */
    *p = buffer;
...
    while (*p && !isdigit(*p))  /* scan forward in buffer to 1st digit */
        p++;

一旦找到了第一个数字,就可以使用long (提供完全错误检查)将数字序列转换为一个strtol值。

代码语言:javascript
复制
#include <stdlib.h>
#include <errno.h>  /* for errno   */
#include <limits.h> /* for INT_MIN/INT_MAX */
...
    char *endptr;           /* end pointer to use with strtol */
    long tmp;               /* long value for return of strtol */
    ...
    errno = 0;                      /* reset errno - to check after strtol */
    tmp = strtol (p, &endptr, 0);   /* save conversion result in tmp */

(注意:避免atoi()是提供转换错误检查的)

现在,tmp保存strtol的返回,该返回将包含从p (on p)开始的buffer中找到的数字到long的转换。但是,在使用作为int返回的值之前,必须验证,即数字已转换,转换过程中没有发生错误,tmp中的值在int的范围内。你可以用一些有条件的支票来做所有的事情。如果您的所有检查都满足了,那么您可以将tmp中的值赋值给一个整数(使用适当的转换),并对您的最终值有信心。

代码语言:javascript
复制
    if (p == endptr)                /* check if pointer == end pointer */
        fputs ("error: no digits converted.\n", stderr);
    else if (errno)             /* if errno set, over/underflow occurred */
        fputs ("error: invalid conversion to long.\n", stderr);
    else if (tmp < INT_MIN || INT_MAX < tmp)    /* will fit in int? */
        fputs ("error: value exceeds range of int.\n", stderr);
    else {      /* good value, assign to b_from_buf, output */
        b_from_buf = (int)tmp;
        printf ("\nint read from buffer: %d\n", b_from_buf);
    }

将您的示例放在一起(包括使用buffer验证您的原始写入snprintf,您可以执行类似于以下操作):

代码语言:javascript
复制
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>  /* for isdigit */
#include <errno.h>  /* for errno   */
#include <limits.h> /* for INT_MIN/INT_MAX */

#define MAXC 1024

int main (void) {

    char a = 'A',
        *c = "A String",
        buffer[MAXC] = "",  /* buffer to hold a, b, c */
        *p = buffer,        /* pointer to buffer */
        *endptr;            /* end pointer to use with strtol */
    int b = 90,
        b_from_buf,         /* int to read from filled buffer */
        rtn;                /* return for snprintf to validate */
    long tmp;               /* long value for return of strtol */

    rtn = snprintf (buffer, MAXC, "%c%d%s", a, b, c);
    if (rtn < 0) {  /* if < 0, error occurred */
        fputs ("error: writing to buffer.\n", stderr);
        return 1;
    }
    else if (rtn >= MAXC)   /* if > size, truncation occurred */
        fputs ("warning: buffer contains truncated string.\n", stderr);

    printf ("%s\n", buffer);    /* output buffer */

    while (*p && !isdigit(*p))  /* scan forward in buffer to 1st digit */
        p++;

    errno = 0;                      /* reset errno - to check after strtol */
    tmp = strtol (p, &endptr, 0);   /* save conversion result in tmp */
    if (p == endptr)                /* check if pointer == end pointer */
        fputs ("error: no digits converted.\n", stderr);
    else if (errno)             /* if errno set, over/underflow occurred */
        fputs ("error: invalid conversion to long.\n", stderr);
    else if (tmp < INT_MIN || INT_MAX < tmp)    /* will fit in int? */
        fputs ("error: value exceeds range of int.\n", stderr);
    else {      /* good value, assign to b_from_buf, output */
        b_from_buf = (int)tmp;
        printf ("\nint read from buffer: %d\n", b_from_buf);
    }
}

(注意:如果buffer中的值可以在其前面有一个显式符号,例如'-''+',则将它们添加到与isdigit()相同的条件中)

示例使用/输出

代码语言:javascript
复制
$ ./bin/snprintf_string
A90A String

int read from buffer: 90

最后评论后的 'a,b&c‘Back

您已经拥有了从缓冲区获取a, b & c所需的全部内容。由于使用strtolendptr将指向上一个数字转换后的下一个字符,您可以通过简单地输出值来从缓冲区中获取a, b & c

代码语言:javascript
复制
    else {      /* good value, assign to b_from_buf, output */
        b_from_buf = (int)tmp;
        printf ("\n(a) 1st char in buffer        : %c\n"
                "(b) int read from buffer      : %d\n"
                "(c) remaining chars in buffer : %s\n", 
                *buffer, b_from_buf, endptr);
    }

修改后的示例使用/输出

代码语言:javascript
复制
$ ./bin/snprintf_string
A90A String

(a) 1st char in buffer        : A
(b) int read from buffer      : 90
(c) remaining chars in buffer : A String

仔细考虑一下,如果你还有其他问题,请告诉我。

票数 3
EN

Stack Overflow用户

发布于 2019-01-09 00:15:32

存在一个%n修饰符,它将写入字节的实际数量存储到int

代码语言:javascript
复制
int main(int argc, char *argv[])
{
    int p0;
    int p1;
    char    buf[128];

    sprintf(buf, "%c%n%d%n%s", argv[0][0], &p0, atoi(argv[1]), &p1, argv[1]);
    printf("'%s' -> %d, %d\n", buf, p0, p1);
}

但是这个修饰符被认为是危险的;有些实现要求格式字符串位于只读内存中。

为了使最后一句更清楚,举一个例子:

代码语言:javascript
复制
#include <stdio.h>

int main(void)
{
        char    fmt[] = "%n";
        int     pos;

        printf("%n", &pos);
        printf("ok\n");

        printf(fmt, &pos);
        printf("ok\n");
}

然后

代码语言:javascript
复制
$ gcc x.c -D_FORTIFY_SOURCE=2 -O2
$ ./a.out 
ok
*** %n in writable segment detected ***
Aborted (core dumped)
票数 2
EN

Stack Overflow用户

发布于 2019-01-09 00:05:48

在您的示例中,假设您询问的字符数组是output_buffer,并且在您的体系结构中,char的大小为1字节,那么%d将占用2个字节,对于int的每一个数字(b = 90)都是一个字节。要返回值,请使用:

代码语言:javascript
复制
int x; 
sscanf(&output_buffer[1], "%d", &x);
char buffer[255]; 
sscanf(&output_buffer[3], "%[^\n]", buffer);

请检查缓冲区的大小以避免溢出。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54101479

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档