Преобразование int в char [] - PullRequest
       6

Преобразование int в char []

0 голосов
/ 08 ноября 2019

Поэтому я пытаюсь преобразовать две даты (сегодняшнюю дату и эту дату 10 лет назад) из целых чисел года, месяца и дня в две строки «ГГГГММДД \ n».

Везде, где яlook предлагает использовать sprintf, но у меня проблемы, и я почти уверен, что это как-то связано с буфером.

Вот мой код:

void main()
{

char today[9];
char ten_years[9];
int year, tenyear, month, day;

time(&timebuf);
tm = localtime(&timebuf);

year = (tm->tm_year%100)+2000;
tenyear = year-10;
month = tm->tm_mon+1;
day = tm->tm_mday;

sprintf( today, "%04d%02d%02d\n", year, month, day );
printf("today(first print)= %s\n",today); //This prints as expected

sprintf( ten_years, "%04d%02d%02d\n", year, month, day );

printf("today(second print)= %s\n",today);  //Now this prints null
printf("ten_years= %s\n",ten_years); //This prints fine

}

Так что, очевидно, ввызов sprintf во второй раз, по какой-то причине обнуляет массив «today []». Может ли кто-нибудь помочь мне понять, как это предотвратить? Есть ли лучший способ преобразовать эти даты в char []?

Мне нужны даты в формате char [], потому что они должны быть отправлены в функцию, которая принимает char [] в качестве параметра (у меня нетконтроль над принимающей функцией).

Редактировать: В соответствии с предложениями я использовал более простую структуру форматирования, но это не решает проблему.

Ответы [ 2 ]

3 голосов
/ 08 ноября 2019

Вам нужно место для нулевых терминаторов в ваших строках. Вы не выделяете для них достаточно места, поэтому следующая строка в памяти «стирается».

Чтобы исправить это, выделите 10 символов вместо 9:

char today[10];
char ten_years[10];

используйте snprintf и включите ширину поля:

snprintf( xxx, sizeof(xxx), "%04d%02d%02d\n", year, month, day );

Если, с другой стороны, вы не хотите включать новую строку в строку, вы можете сохранить размер ранее имеющихся массивов и удалить их. новые строки из ваших snprintf утверждений:

snprintf( xxx, sizeof(xxx) "%04d%02d%02d", year, month, day );

Не связанная с этим проблема;это исправит ошибку Y2.1K, присутствующую в вашем коде:

year = tm->tm_year + 1900;

Поскольку tm->tm_year относительно 1900 года, это должно исправить некоторые проблемы с вашим кодом в следующем столетии.

Я бы посоветовал сделать year, month и day unsigned и распечатать их с %u;это может исправить некоторые проблемы с отрицательными годами через несколько эонов:

snprintf( xxx, sizeof(xxx) "%04u%02u%02u", year, month, day );

Еще одна не связанная проблема;void main() недействительно. Вместо этого вы должны использовать int main(void) и ставить return 0; в конце вашей функции main.

Также обратите внимание, что вам не нужно вручную завершать нуль вручную. Это уже сделано автоматически в C.

2 голосов
/ 08 ноября 2019

Если вы попытаетесь точно вычислить размер адресата для вызова sprintf, вплоть до последнего байта, у вас будут постоянно такие проблемы. Попытка быть настолько скрупулезным по отношению к каждому последнему байту - это «ложная экономия» и, как правило, огромная трата времени.

Если вы не программируете для микроконтроллера 1960-х или чего-то еще, сделайте себе одолжение и выделитеНа 10-50% больше, чем нужно. Если бы вы объявили

char today[15];
char ten_years[15];

, большинство ваших проблем просто исчезло бы сразу.

Однако переполнение буфера - огромная проблема. Итак, есть второе, еще более важное исправление, которое вы должны сделать. Замените эти вызовы на sprintf гораздо более безопасными snprintf:

snprintf( today, sizeof(today), "%04d%02d%02d\n", year, month, day );

snprintf( ten_years, sizeof(ten_years), "%04d%02d%02d\n", tenyear, month, day );

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


Еще одна вещь: это не имеет никакого отношения к вашей проблеме переполнения буфера, но есть еще одна довольно серьезная проблема в вашем коде, а именно строка

year = (tm->tm_year%100)+2000;

Поле tm_year определено так, чтобы содержать год - 1900 . Это, по общему признанию, странное определение, но это означает, что правильный способ восстановить правильный четырехзначный год - это просто сделать

year = tm->tm_year + 1900;

Код, который вы использовали, будет вычислять неправильный год для дат 1900-х годов. или 2100-е, или любая дата не в 2000-х.

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