C-连接结构字符串元素

时间:2019-03-13 20:18:35

标签: c string struct

我的结构中有两个字符串元素

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

我缺少什么?你能帮助我吗?谢谢安迪斯!

  • 编辑了更多信息
  • 即使我将尺寸增加一倍也不起作用

3 个答案:

答案 0 :(得分:4)

您的行为不确定,因为mydate中没有足够的空间来容纳格式为“ MM-DD-YYYY”的字符串-不要忘记最后的隐式空终止符。

您要特别注意的是,缺少空终止符意味着输出函数(putsprintf或您正在使用的任何内容)在字符串结束后仍继续读取字符。碰巧在您的情况下,mydatemytime之间没有任何填充,因此mytime中的值也似乎是字符串的一部分。

请记住,由于数组在传递给函数时会衰减为指针,因此带有数组参数的函数无法知道何时完成读取数组。为此,空终止符充当标记值。

解决方案:增加mydatemytime的大小以同时容纳空终止符。

答案 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而不是strcpyprintf也不能直接使用。所以这是另一个例子:

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)您在mydatemytime中写的太多了。解决方法是在结构中分配更多内存,即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字符串副本的空终止符覆盖。