2010-02-09 4 views
0

Я работаю над проектом, где у меня есть класс Time, и мне нужно отформатировать время.C++, truncate a char array

void Time::FormatTime(char *string, unsigned int max_string_len) { 
    ostrstream fd; 
    ft << hour << ":" << minutes; 
    cout << ft.str() << endl;  
} 

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

Я бы не хотел использовать STL, если это возможно.

Благодаря

+0

Если вы более или менее знаете, что время займет 5 символов, почему бы не утверждать, что длины достаточно? Какая польза от укороченного представления времени? – UncleBens

+0

Практика при переполнении строк, по-видимому ... – Potatoswatter

ответ

2

Всегда используйте strncpy(), чтобы безопасно усекать строку в char[N].

void Time::FormatTime(char *str, unsigned int max_string_len) { 
    if (max_string_len == 0) return; 
    ostringstream ft; // strstream is obsolete, use stringstream 
    ft << hour << ":" << minutes; 
    strncpy(str, ft.str().c_str(), max_string_len); 
    str[ max_string_len - 1 ] = 0; 
} 
+0

Downvoted, потому что max_string_len может быть 0 – Manuel

+0

@ Manuel: Отлично, хотя я думаю, что это глупо. Обратите внимание, что 'snprintf' не включает завершающий байт в своем предельном аргументе, поэтому передача 0 в эту функцию будет как передача -1 в' snprintf'. – Potatoswatter

+0

упс, поцарапать что о 'snprintf'. – Potatoswatter

1

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

2

Это делает то, что вы хотите:

void Time::FormatTime(char *string, unsigned int max_string_len) { 
     ostrstream fd; 
     ft << hour << ":" << minutes; 
     std::string str = ft.str(); 
     str.resize(max_string_len); 
     strcpy(string, str.c_str()); 
} 

EDIT: Я обновил мой код, благодаря полезной обратной связи potatoswatter и quanmrana.

+0

Это самый простой способ сделать это. Короткие и простые. –

+0

-1: Вы проверяете, произошло ли переполнение * уже *. – Potatoswatter

+0

-1: strlen (string) может быть undefined, если max_string_len равно 0. – quamrana

2
if(str.length() > max_string_len) 
{ 
    str = str.substr(0, max_string_len); 
} 

strncpy(string, str.c_str(), max_string_len); 
0

Из ваших требований вы, похоже, намерены писать C вместо C++, но я думаю, это ваше дело. Однако для вашей спецификации кажется, что правильный ответ strftime().

1

Я наполовину угадывая, что вы хотите, но я думаю, что это что-то вроде следующего, где я предполагающей или изменяющегося:

  • ft действительно должен быть fd
  • Я использовал ostringstream объект вместо ostrstream
  • max_string_len является размер целевого буфера в символах (включая символ, который будет содержать «\ 0»)
  • вы действительно не Inte отлаивается в отформатированной строке, отправляемой в std::cout, но хочу ее в предоставленном буфере вызывающего абонента
  • Я изменил имя параметра string на s, поэтому его не путают с типом std:string.

Код:

void Time::FormatTime(char *s, unsigned int max_string_len) { 
    if (max_string_len == 0) { 
     return; // no buffer, bail out 
    } 

    std::ostringstream fd; 

    fd << hour << ":" << minutes; 

    size_t len = fd.str().copy(s, max_string_len - 1); // leave room for the null terminator 

    s[len] = '\0'; 
} 

Если вы действительно не хотите какой-либо части STL, то следующий C-стиле кода следует сделать трюк:

void Time::FormatTime(char *s, unsigned int max_string_len) { 

    snprintf(s, max_string_len, "%02u:%02u", hour, minutes); 
} 

Это проще , но разработчикам на C++ не нравится использовать семейство printf(), потому что он не является типичным.

+0

Crud - я просто заметил желание не использовать STL - я использую STL здесь, потому что пример, заданный в вопросе, использует его, а тег говорит «C++» ... Опубликуйте комментарий, если я должен удалить этот ответ , и если вы хотите использовать чистую функцию C, давайте рассмотрим вопрос как вопрос C. –

+0

Мне нравится ваш первый маленький фрагмент, но я продолжаю получать эту ошибку: «left of .copy» должен иметь класс/struct/union » – Joe

+0

Первый фрагмент кода компилируется просто на VS2008 после добавления' #include ', объявлений для' час' и 'минуты' и исправление' max_string_len'. – quamrana