2015-05-15 3 views
1

Как я могу определить массив символов для strftime без проб и ошибок? Используя mktime, размер метки N в этом примере должен быть больше 86, иначе я получаю произвольные даты назад. , например.Что такое интеллектуальный способ определения максимального размера массива символов strftime?

N = 86: 2013-07-13 02:41

N = 82: 1979-05-18 13:23

Как эффективно масштабировать N без предварительного знания даты? Проверка> 0 не помогает.

#include <iostream> 
#include <cstring> 
#include <ctime> 

#define N 86 

using namespace std; 

int main(void) 
{ 
time_t t; 
struct tm ts; 
char timestamp[N] ; 

ts.tm_min = 41;  
ts.tm_hour = 2;  
ts.tm_mday = 13; 
ts.tm_mon = 7 - 1;  
ts.tm_year = 13 - 1900 + 2000;   

t = mktime(&ts); 

if (strftime(timestamp, sizeof(timestamp)-1, "%Y-%m-%d %H:%M", &ts) > 0) 
    cout << timestamp; 
else { 
    cerr << "strftime failed." <<endl; 
    return 1; 
} 

return 0; 
} 
+2

Это, вероятно, имеет больше общего с неинициализированными членов в 'ts', которые запутывают' mktime'. Попытайтесь «memset (& ts, 0, sizeof (ts));' перед установкой членов, которые вы хотите, так что 'tm_sec' и др. Гарантированно будут' 0'. – Wintermute

+0

... или просто инициализировать его - 'tm ​​ts {};' (Это C++, поэтому нет необходимости в 'struct') –

+0

Не знаете, почему вы думаете, что вам нужна переменная длина для этого. На основе вашей строки формата все даты/время будут иметь одинаковую длину. –

ответ

0

Из документации STRFTIME:

Если длина результирующей строки C, включая завершающий нулевой символ, не превышает MAXSIZE, функция возвращает общее число символов, скопированное на ptr (не включая завершающий нулевой символ). В противном случае он возвращает ноль, а содержимое массива, на которое указывает ptr, является неопределенным.

Это означает, что если вы не знаете размер и может динамически выделять строку, которую вы можете сделать что-то вдоль линий:

int size = N; // Some starting size 
char *timestamp = malloc(size); 

// Your time stuff 

int result = strftime(timestamp, size - 1, "%Y-%m-%d %H:%M", &ts); 

// While there isn't enough room to store the result 
while (result == 0) 
{ 
    free(timestamp); // Free old data 
    size *= 2;  // Double the size (should be more than enough) 
    timestamp = malloc(size); // Allocate the new size. You can check for failed allocations here as well. 

    // Retry 
    result = strftime(timestamp, size - 1, "%Y-%m-%d %H:%M", &ts); 
} 

std::cout << timestamp; 
+0

'malloc' вместо' std :: string'? Tsk. –

+0

Я придерживаюсь использования OP 'char []'. Использование 'std :: string' - это другой ответ, который вы можете публиковать. Поскольку OP использует C++, он может оценить этот ответ больше. – ozdrgnaDiies

0

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

-> Обратите внимание, что здесь нет борьбы с размером строки.


// function to create a timestamp style string 
std::string yyDmmDdd_hhCmmGet(time_t tt) 
{ 
    std::stringstream ss; 
    // goal - something like: "%Y-%m-%d %H:%M" 
    { 
     struct tm mybdtod; // linux api: my broken down time of day 

     // the following is a relatively slow function 
     ::localtime_r (&tt, &mybdtod); 
     // linux api - convert time_t to tm as local time 

     ss << std::setw(4) << (mybdtod.tm_year+1900) 
     << "-" 
     << std::setfill('0') << std::setw(2) << mybdtod.tm_mon+1 
     << "-" 
     << std::setfill('0') << std::setw(2) << mybdtod.tm_mday 
     << " "; 

     ss << std::dec << std::setfill('0') << std::setw(2) 
     << mybdtod.tm_hour 
     << ":" 
     << std::setfill('0') << std::setw(2) 
     << mybdtod.tm_min; 
    } 
    return(ss.str()); 
} 


int t186(void) 
{ 
    struct tm ts; // linux api: time struct 
    ::memset(&ts, 0, sizeof(tm)); 

    ts.tm_min = 41; 
    ts.tm_hour = 3-1; 
    ts.tm_mday = 13; 
    ts.tm_mon = 7 - 1; 
    ts.tm_year = 13 - 1900 + 2000; 

    time_t tt = mktime(&ts); // linux api: Convert tm struct to time_t 

    // format time_t to string 
    std::string s = yyDmmDdd_hhCmmGet(tt); // timestamp style 

    std::cout << "\n" << s 
      << "\n   s.size(): " 
      << s.size() << " chars" << std::endl; 

    // now we know how many chars timestamp needs 

    // add 1 to size because ?strftime seems to need it? 
    char timestamp[s.size()+1]; 

    (void)strftime(timestamp, sizeof(timestamp), "%Y-%m-%d %H:%M", &ts); 
    // linux api: format time_t to string 

    std::cout << "\n" << timestamp << std::endl; 
    std::cout << " sizeof(timestamp): " 
      << sizeof(timestamp) << " chars" << std::endl; 

    return(0); 
} 
Смежные вопросы