我编写了一个简单的小程序,使用snprintf
读取具有以下格式的文件skip first 15 chars , next 9 chars are sequence number, next 2 char is message and so on.
我对序列号和消息感兴趣,即来自char no 16到26;
以下是该计划。它不会读取每个字段的最后一个字符。对于序列号,它读取8个字符而不是9个字符,而对于消息,它读取1个字节而不是2个字节。
#include<stdio.h>
typedef struct
{
char seqno[9];
char msg[2];
}Header_T;
int main()
{
char buf[64]={'\0'};
FILE *fp;
int i = 0;
Header_T hdr1;
int skipbytes = 15;
fp=fopen("asdf", "r");
if (fp == NULL)
{
printf("FILE OPEN ERROR\n");
}
printf("--sequence--msg--\n");
while( fgets( buf, sizeof(buf), fp ) != NULL )
{
i=skipbytes;
snprintf(hdr1.seqno, 9, "%s", (buf+i));
i+=sizeof(hdr1.seqno);
snprintf(hdr1.msg, 2, "%s", (buf+i));
i=0;
printf("--%s--%s--\n", hdr1.seqno, hdr1.msg);
memset(buf, '\0', 64 );
}
fclose(fp);
return 0 ;
}
部分文件内容如下
201301082323458000000001H QB234
201301082323558000000002J QB234
201301082323658000000003N QB234
201301082323758000000004JRQB234
201301082333458000000010JSQB234
所以期望的输出是
--sequence--msg--
--000000001--H --
--000000002--J --
--000000003--N --
--000000004--JR--
--000000010--JS--
但相反,我得到输出
--seqno--msgtype--
--00000000--H--
--00000000--J--
--00000000--N--
--00000000--J--
--00000001--J--
任何人都可以解释这种行为以及如何解决这个问题吗?
而不是 snprintf 我使用 for循环逐个字符分配尝试相同的程序,程序运行正常;但为此,我需要在结构中添加一些填充字节对齐。
我也尝试过使用 pragma pack(),但也没有区别。
我在ubuntu 64位机器上使用gcc 4.4.3
答案 0 :(得分:3)
int snprintf ( char * s, size_t n, const char * format, ... );
n:缓冲区中使用的最大字节数。
生成的字符串的长度最多为n-1 ,为额外的终止空字符留出空间。
因此,如果您需要9个字符,则应将n
作为10
而不是9
传递:
snprintf(hdr1.seqno, 10, "%s", (buf+i));
Header_T
需要相应更改:
typedef struct
{
char seqno[10];
char msg[3];
}Header_T;
答案 1 :(得分:1)
你需要有一个额外的字符来存储尾随的'\0'
字符,所以你的结构应该看起来像
typedef struct
{ char seqno[10];
char msg[3];
}Header_T;
编辑:由于这是一个简单的数据传输,为什么不使用memcpy
,例如:
memset(hdr1, 0, sizeof(hdr1));
memcpy(hdr1.seqno, &buf[skipbytes], 9);
memcpy(hdr1.msg, &buf[skipbytes + 9], 2);
答案 2 :(得分:1)
#include<stdio.h>
typedef struct {
char seqno[9+1];//+1 for EOS('\0')
char msg[2+1];
} Header_T;
int main(void){
char buf[64]={'\0'};
FILE *fp;
Header_T hdr1;
fp=fopen("asdf", "r");
if (fp == NULL) {
printf("FILE OPEN ERROR\n");
return 1;
}
printf("--sequence--msg--\n");
while( fgets( buf, sizeof(buf), fp ) != NULL ){
sscanf(buf, "%*15c%9c%2c", hdr1.seqno, hdr1.msg);
hdr1.seqno[sizeof(hdr1.seqno)-1] = hdr1.msg[sizeof(hdr1.msg)-1] = '\0';
printf("--%s--%s--\n", hdr1.seqno, hdr1.msg);
//memset(buf, '\0', 64 );
}
fclose(fp);
return 0 ;
}
答案 3 :(得分:0)
这个答案是在上面的两个答案之后。他们都提出了一些正确的建议。我把它们拼接在一起。
首先,使用:
typedef struct
{ char seqno[10];
char msg[3];
}Header_T; //so we have the memory for '\0'
然后,使用:
while( fgets( buf, sizeof(buf), fp ) != NULL )
{
i=skipbytes;
snprintf(hdr1.seqno, 10, "%s", (buf+i));//here we read 9 number and a '\0'
i+=sizeof(hdr1.seqno) -1; //the '\0' is not part of buffer.
snprintf(hdr1.msg, 3, "%s", (buf+i)); //also for '\0'
i=0;
printf("--%s--%s--\n", hdr1.seqno, hdr1.msg);
memset(buf, '\0', 64 );
}