如何访问字符数组中的整数值?
char a = 'A';
int b = 90;
char * c = "A String";
snprintf(output_buffer, 1024, "%c%d%s, a,b,c);`%d格式说明符将有多少字节(我假设4字节?)在这个字符数组中,如何访问整数值b?
我试过:
int x = *((int *) &output_buffer[1]但没有成功。
short x;
sscanf(&output_buffer[1], "%d", &x);
printf("%d\n",x);`
char *buffer;
sscanf(&output_buffer[3], "%s", buffer);
printf("%s\n",buffer);`发布于 2019-01-09 00:58:09
在回答您最初的问题“"%d"将使用多少个字符?”时,您可以对snprintf使用一个技巧,方法是将缓冲区指定为NULL,将字符数指定为0,然后使用"%d"格式字符串和变量b,snprintf将返回转换所需的数字数。
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()宏,这使得这非常容易。要找到第一个数字,您可以这样做:
#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值。
#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中的值赋值给一个整数(使用适当的转换),并对您的最终值有信心。
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,您可以执行类似于以下操作):
#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()相同的条件中)
示例使用/输出
$ ./bin/snprintf_string
A90A String
int read from buffer: 90最后评论后的 'a,b&c‘Back
您已经拥有了从缓冲区获取a, b & c所需的全部内容。由于使用strtol和endptr将指向上一个数字转换后的下一个字符,您可以通过简单地输出值来从缓冲区中获取a, b & c。
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);
}修改后的示例使用/输出
$ ./bin/snprintf_string
A90A String
(a) 1st char in buffer : A
(b) int read from buffer : 90
(c) remaining chars in buffer : A String仔细考虑一下,如果你还有其他问题,请告诉我。
发布于 2019-01-09 00:15:32
存在一个%n修饰符,它将写入字节的实际数量存储到int中
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);
}但是这个修饰符被认为是危险的;有些实现要求格式字符串位于只读内存中。
为了使最后一句更清楚,举一个例子:
#include <stdio.h>
int main(void)
{
char fmt[] = "%n";
int pos;
printf("%n", &pos);
printf("ok\n");
printf(fmt, &pos);
printf("ok\n");
}然后
$ gcc x.c -D_FORTIFY_SOURCE=2 -O2
$ ./a.out
ok
*** %n in writable segment detected ***
Aborted (core dumped)发布于 2019-01-09 00:05:48
在您的示例中,假设您询问的字符数组是output_buffer,并且在您的体系结构中,char的大小为1字节,那么%d将占用2个字节,对于int的每一个数字(b = 90)都是一个字节。要返回值,请使用:
int x;
sscanf(&output_buffer[1], "%d", &x);
char buffer[255];
sscanf(&output_buffer[3], "%[^\n]", buffer);请检查缓冲区的大小以避免溢出。
https://stackoverflow.com/questions/54101479
复制相似问题