C - Структурные строковые элементы объединяются - PullRequest
0 голосов
/ 13 марта 2019

в моей структуре два строковых элемента

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

Я что-то упустил?Вы можете мне помочь?Спасибо в andance!

  • РЕДАКТИРОВАНИЕ с дополнительной информацией
  • не работает, даже если я увеличу размер на один

Ответы [ 3 ]

4 голосов
/ 13 марта 2019

У вас неопределенное поведение, так как в mydate недостаточно места для размещения строк в формате "MM-DD-YYYY" - не забудьте неявный нулевой терминатор в конце.

Что вы конкретно наблюдаете, так это отсутствие нулевого терминатора, означающего, что функция вывода (puts, printf или что вы используете) продолжает читать символы после окончания строки. Так получилось, что в вашем случае нет никаких отступов между mydate и mytime, поэтому значение в mytime также является частью строки.

Помните, поскольку при передаче в функции массивы распадаются на указатели, функция с параметром массива не может узнать, когда она закончит чтение массива; для этой цели нулевой терминатор выступает в качестве дозорного значения.

Решение: Увеличьте размер как mydate, так и mytime, чтобы также разместить нулевой терминатор.

1 голос
/ 14 марта 2019

, так как вы жаловались, что ваш код не работает даже с увеличенными размерами, вот пример, который работает правильно:

#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);
}

Вышесказанное имеет смысл в некоторых ситуациях, когда вы действительно нехватаете памяти, но не должны использоваться в общих случаях.

0 голосов
/ 14 марта 2019

Как минимум две проблемы с кодом.

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 строковой копии.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...