2012-06-13 4 views
5

Мне нужно выполнить поиск по куску памяти для строки символов, но некоторые из этих строк разделяют каждый символ, например:
«I. .am. a. .string "
со всеми символами '.', являющимися нулевыми. Моя проблема возникает из-за того, что она попадает в память. Я попробовал несколько способов, например:Манипулирование C-строками с несколькими нулевыми символами в памяти

char* str2; 
str2 = (char*)malloc(sizeof(char)*40); 
memcpy((void*)str2, "123\0567\09abc", 12);  

поместим следующее в памяти, что str2 указывает на: 123.7.9abc..
Что-то вроде
str2 = "123456789\0abcde\054321";
будет иметь str2, указывающий на блок памяти, который выглядит например, 123456789.abcde,321, где '.' является нулевым символом, а ',' является фактической запятой.

Значительная вставка нулевых символов в cstrings не работает так же легко, как я думал, это так, как вставка символа новой строки. Я столкнулся с подобными трудностями, пытаясь это и с библиотекой строк. Я мог бы сделать отдельные задания, что-то вроде:

char* str;  
str = (char*)malloc(sizeof(char)*40); 
strcpy(str, "123"); 
strcpy(str+4, "abc"); 
strcpy(str+8, "ABC"); 

Но это, безусловно, не является предпочтительным, и я считаю, что проблема заключается в моем понимании того, как строки с стиля сохраняются в памяти. Очевидно, что «abc \ 0123» фактически не входит в память как 61 62 63 00 31 32 33 (в шестнадцатеричном формате). Как он хранится и как я могу хранить то, что мне нужно?

(Я также извиняюсь за то, были необходимы.)

+0

Используйте кнопку {} над окном редактирования или ctrl-K, чтобы создать блоки кода. –

ответ

6

Если каждый другой char содержит нуль, то почти наверняка у вас на самом деле есть кодированные строки UTF-16. Обработайте их соответственно, и ваши проблемы исчезнут.

Предполагая, что вы находитесь в Windows, где используется UTF-16, вы должны использовать wchar_t* вместо char* для хранения таких строк. И вы должны использовать широкие функции строковой обработки символов для работы с такими данными. Например, используйте wcscpy, а не strcpy и так далее.

+0

Это определенно решило мою практическую проблему и позволяет мне легко выполнять поиск. Это первый раз, когда я программировал окна, и раньше я не встречал широких символов, поэтому, глядя на двоичные дампы, которые мне никогда не приходило в голову. И я продолжал думать о том, как странно было обнулить конец каждого персонажа ... = P Refp ниже также помог мне разобраться, что вызвало проблему, которую я делал по-старому. – Fulluphigh

2

Прежде всего, каждый второй символ, являющийся NULL, является четким признаком расширения - строка, состоящая из двухбайтовых символов, действительно массив из unsigned short. В зависимости от вашего компилятора и настроек вам может быть лучше использовать тип данных wchar_t вместо char и wcsxxx() семейство функций вместо strxxx().

В Windows, 2-байтные широты (UTF-16, технически) является родным строковым форматом ОС, поэтому они все вокруг.

Тем не менее, функции strxxx() все предполагают, что строка имеет нулевое завершение. Поэтому планируйте соответственно. Иногда memxxx() придет на помощь.

«abc \ 0123» не попадает в память так, как вы ожидаете, потому что \ 012 интерпретируется компилятором как одна восьмеричная escape-последовательность - символ с восьмеричным кодом 12 (это 0a hex). Для того, чтобы избежать, используйте один из следующих литералов:

"abc\000123" 
"abc\x00123" 
"abc\0""123" 

Сниппет, где вы создаете строку из кусков в основном правильно.Это просто, что я предпочел бы использовать

strcpy(str+strlen(str)+1, "123"); 

, который гарантирует, что следующий фрагмент будет записан мимо пустого символа предыдущего фрагмента.

+2

\ 054 интерпретируется компилятором как одна восьмеричная escape-последовательность. Октал 54 - это гекса 2с. Чтобы создать истинную строку со встроенным нулем, используйте следующий литерал: «abcde \ 00054321» или «abcde \ 0» «54321» или «abcde \ x0054321». Очевидно, что синтаксический анализатор escape-последовательности согласуется с жадностью. Придерживайтесь строковых литералов, которые не допускают двусмысленной интерпретации. –

+0

@ Roddy: редактирование занимает время :) –

0

Я немного смущен вашим вопросом. Но позвольте мне угадать, что происходит. Вы смотрите на 16-битную строку wchat_t, а не на обычную строку c. wchar Получение символов ascii может выглядеть как нуль, разделенный между буквами, но на самом деле это нормально.

simple (wchar_t *) XXX где XXX является указателем на эту область памяти и выполняет поиск wchar_t-операций, таких как wcscpy и т. Д. ... что касается нулей между строками, это может быть известный метод передачи нескольких строковых конструкций. Вы можете просто итерации после чтения каждой строки до тех пор, пока вы не столкнетесь с двумя последовательными нулями.

Надеюсь, что я ответил на ваш вопрос. Удачи!

3

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


Самый простой способ определить строку, содержащую нуль-символ а затем что-то, что также можно рассматривать как часть беглого characer в октета (например, «\ 012» ), чтобы разделить его с помощью этого признака ниже C:

char const * p = "123456789" "\0" "abcde" "\0" "54321"; 

1. «\ 012» приведет к символу с эквивалентным шестнадцатеричным значением 0x0A, не три символа; 0x00, '1' и '2'.

+0

Отличный ответ. Ответ Дэвида выше отлично работает для того, что мне нужно делать, но я все еще не знал, что вызывает такое поведение. Я не знал, что октеты - это то, что вы могли бы избежать таким образом. Спасибо, отличный ответ. Мне не хватает репутации, но да. – Fulluphigh

+0

@ Joshua Это хорошая идея, чтобы ознакомиться с основным синтаксисом вашего языка программирования. Вот полезная ссылка для C: http://ieng9.ucsd.edu/~cs30x/Std.C/syntax.html –

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