2012-02-25 1 views
0

Мне нужно, чтобы strncpy() (эффективно) от (Редактировать: MFC) Объект CString для строковой переменной C. Хорошо известно, что иногда strncpy() терпит неудачу (в зависимости от длины источника ** EDIT и длины, указанной в вызове), чтобы правильно завершить строку dest C. Чтобы избежать этого зла, я собираюсь хранить символ NUL внутри исходного объекта CString, а затем до strcpy() или memmove() того парня.Какова внутренняя структура объекта класса (EDIT: MFC) CString?

Действительно ли это разумный способ? Если да, то чем я должен манипулировать внутри объекта CString? Если нет, то какая альтернатива будет гарантировать правильную конечную строку C назначения?

+4

'CString' не существует в стандартной библиотеке C++. Вы говорите о 'std :: string' или что-то еще (возможно,' CString' из [MFC] (http://msdn.microsoft.com/en-us/library/5bzxfsea (v = vs.100) .aspx))? – spencercw

+0

Не можете ли вы просто преобразовать его в 'std :: string'? Например: 'std :: string cppString (yourCString);'. Если вам действительно нужна необработанная строка, получите ее из 'cppString.c_str()'. Просто будьте осторожны, некоторые конверсии Unicode не будут работать. – jweyrich

+2

Вы должны обязательно использовать std :: string в предпочтении CString почти во всех случаях. – 111111

ответ

1

strncpy() только «не может» обнулить-завершает строку назначения, когда исходная строка длиннее, чем предел длины вы укажете. Вы можете убедиться, что назначение завершено нулем, установив свой последний символ на нуль. Например:

#define DEST_STR_LEN 10 

char dest_str[DEST_STR_LEN + 1]; // +1 for the null 
strncpy(dest_str, src_str, DEST_STR_LEN); 
dest_str[DEST_STR_LEN] = '\0'; 

Если src_str длиной более DEST_STR_LEN символов, dest_str будет правильно завершающая строкой DEST_STR_LEN символов. Если src_str короче этого, strncpy() поместит нулевой ограничитель где-то в пределах dest_str, поэтому нуль в самом конце не имеет значения и безвреден.

+0

да, конечно, это ответ. Благодаря! –

+1

, но вопрос был о CString! Я не понимаю, как этот ответ, это немного актуально. – CapelliC

+0

@chac, я ответил на фактическую * проблему * (неправильное использование 'strncpy()'), а не на * вопрос * (как реализовать ошибочное обходное решение проблемы). – Wyzard

1

CSimpleStringT::GetString дает указатель на строку с нулевым завершением. Используйте это как soure для strncpy. Поскольку это C++, вы должны использовать только строки C-стиля при взаимодействии с устаревшими API-интерфейсами. Вместо этого используйте std::string.

1

Я надеюсь, что они не изменились с момента, когда я использовал их: что было много лет назад :)

Они использовали интересный симулировать ", чтобы справиться с RefCount и очень быстрое и эффективное автоматическое преобразование на символ * : то есть указатель на LPCSTR, но некоторый задний байт зарезервирован для сохранения состояния реализации.

Таким образом, структура может быть используется со старым API окон (LPCSTR без накладных расходов). В то время я нашел интересную идею!

Конечно, ключ - наличие распределителей: они просто смещают указатель при mallocing/freeing.

Я помню, что был запрошен буфер , чтобы (например) изменить доступные данные: GetBuffer (0), а затем ReleaseBuffer().

НТН

1

Одним из альтернативных способов было бы сначала выполнить нулевую строку, а затем лить или memcpy из CString.

1

Если вы не компилируете с включенным _UNICODE, вы можете легко получить const char * от CString. Просто бросить его в LPCTSTR:

CString myString("stuff"); 
const char *byteString = (LPCTSTR)myString; 

Это гарантированно будет нулем.

Если вы были построены с _UNICODE, то CString является UTF-16 закодированных строками. Вы ничего не можете сделать прямо с этим.

Если вам нужно скопировать данные из CString, это очень просто, даже с использованием кода стиля C. Просто убедитесь, что вы выделить достаточно памяти и копируют правильную длину:

CString myString("stuff"); 
char *outString = (char*)malloc(myString.Length() + 1); 
strncpy(outString, (LPCTSTR)myString, myString.Length()); 
1

CString заканчивается NULL так долго, как ваш текст правильно (не NULL символов внутри), то копирование должно быть безопасным. Вы можете написать:

char szStr[256]; 
strncpy(szStr, (LPCSTR) String, 3); 
szStr[3]='\0'; /// b-cos no null-character is implicitly appended to the end of destination 

если вы храните нулевой somehere внутри CString объект, который вы, вероятно, вызовет себе больше проблем, CString сохраняет свою длину внутри.

+0

Да, это отлично работает. Благодаря! –

0

Другое альтернативное решение скорее будет включать поддержку процессора или компилятора, так как это гораздо лучший подход - просто убедитесь, что при копировании памяти в «безопасном» режиме в любой момент после каждой атомной операции в конце добавляется нуль, поэтому, когда полный цикл завершается с ошибкой, строка назначения все равно будет прекращена, без необходимости полностью ее обнулить перед копированием. Может быть также поддержка быстрого нуля - просто отметьте начало и остановку обнуленной области, и она мгновенно очистится в ОЗУ, это упростит ситуацию.

 Смежные вопросы

  • Нет связанных вопросов^_^