我的结构中有两个字符串元素
struct mystruct{
char mydate[10];
char mytime[5];
};
它们将分别存储类型为“ XX:YY”和“ XX-YY-ZZZZ”的字符串。
但是当我为这些变量赋值时
struct mystruct *mystruct = (struct mystruct*)malloc(sizeof(struct mystruct));
strcpy(mystruct->mydate, "01-01-1970");
strcpy(mystruct->mytime, "00:01");
mydate 变量正在打印此内容:
01-01-197000:01
我缺少什么?你能帮助我吗?谢谢安迪斯!
答案 0 :(得分:4)
您的行为不确定,因为mydate
中没有足够的空间来容纳格式为“ MM-DD-YYYY”的字符串-不要忘记最后的隐式空终止符。
您要特别注意的是,缺少空终止符意味着输出函数(puts
,printf
或您正在使用的任何内容)在字符串结束后仍继续读取字符。碰巧在您的情况下,mydate
和mytime
之间没有任何填充,因此mytime
中的值也似乎是字符串的一部分。
请记住,由于数组在传递给函数时会衰减为指针,因此带有数组参数的函数无法知道何时完成读取数组。为此,空终止符充当标记值。
解决方案:增加mydate
和mytime
的大小以同时容纳空终止符。
答案 1 :(得分:1)
由于您抱怨代码即使增加大小也无法正常工作,因此以下示例可以正常工作:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct mystruct1 {
char mydate[11];
char mytime[6];
};
void main() {
struct mystruct1 *mystruct1 = (struct mystruct1*)malloc(sizeof(struct mystruct1));
strcpy(mystruct1->mydate, "01-01-1970");
strcpy(mystruct1->mytime, "00:01");
printf("date: %s, time: %s\n", mystruct1->mydate, mystruct1->mytime);
}
在此示例中,每个数组都有足够的空间来将字符串保留为空终止符。因此,您可以将其与您的代码进行比较。
通常,也可以像示例中那样保留大小。但是您需要始终记住,字符串的结尾无法自动确定,并且需要您使用特定的功能,例如strncpy
而不是strcpy
。 printf
也不能直接使用。所以这是另一个例子:
struct mystruct2 {
char mydate[10];
char mytime[5];
};
void main() {
struct mystruct2 *mystruct2 = (struct mystruct2*)malloc(sizeof(struct mystruct2));
strncpy(mystruct2->mydate, "02-02-2970", 10);
strncpy(mystruct2->mytime, "00:02", 5);
// need top prepare standard strings with terminator for printf
char mydate[11]; // still need [11] for printf to work
char mytime[6];
strncpy(mydate, mystruct2->mydate, 10);
mydate[10] = 0; // make sure to put a string terminator here
strncpy(mytime, mystruct2->mytime, 10);
mytime[5] = 0;
printf("date: %s, time: %s\n", mydate, mytime);
}
在某些情况下,上面的内容是有意义的,在这种情况下,您确实会紧紧占用内存,但在一般情况下不应使用。
答案 2 :(得分:0)
代码至少有两个问题。
1)您在mydate
和mytime
中写的太多了。解决方法是在结构中分配更多内存,即char mydate[10+1];
和char mytime[5+1];
。或者只是不写NULL
终止符。一种解决方案,因为您事先知道大小,所以请使用memcpy(mystruct->mydate, "01-01-1970", sizeof(mystruct->mydate));
或类似的memcpy(mystruct->mytime, "00:01", 5);
。
2)第二部分,打印出来,您没有显示(提示)。因此,如果您不存储NULL
终止符,则打印输出需要更加精细,如下面的示例所示。
// Possible dynamic max size
printf("date: %.*stime: %.*sThe\n",
(int) sizeof(mystruct->mydate), mystruct->mydate,
(int) sizeof(mystruct->mytime), mystruct->mytime);
// Fixed max size
printf("date: %.10stime: %.5sEnd\n",
mystruct->mydate,
mystruct->mytime);
无论哪种方式,打印输出都将是:
date: 01-01-1970time: 00:01The
date: 01-01-1970time: 00:01End
使用的printf
语法可最大程度地延长打印字符串的长度。
顺便说一句,您的打印输出01-01-197000:01
可能是编译器将struct mystruct
的内存布局直接紧挨着放置在内存中的结果。生成的内存布局等效于
struct mystruct {
char my[15];
}
编译器知道mydate
从偏移量0开始,而mytime
从偏移量10开始。如果按示例顺序填充结构,则首先得到"01-01-1970\0"
后跟"01-01-197000:01\0"
(最后一次写入超出该结构的范围)。因此,使用printf("%s", mystruct->mydate);
打印日期会为您提供序列输出。
另一方面,您是否决定以相反的顺序写数据,
strcpy(mystruct->mytime, "00:01");
strcpy(mystruct->mydate, "01-01-1970");
的输出
printf("date: %s, time: %sEnd\n", mystruct->mydate, mystruct->mytime);
将会
date: 01-01-1970, time: End
由于您的时间已被mydate
字符串副本的空终止符覆盖。