В C++ можно использовать оператор потоковой передачи для упрощения вещей:
#if defined _DEBUG
class Trace
{
public:
static Trace &GetTrace () { static Trace trace; return trace; }
Trace &operator << (int value) { /* output int */ return *this; }
Trace &operator << (short value) { /* output short */ return *this; }
Trace &operator << (Trace &(*function)(Trace &trace)) { return function (*this); }
static Trace &Endl (Trace &trace) { /* write newline and flush output */ return trace; }
// and so on
};
#define TRACE(message) Trace::GetTrace () << message << Trace::Endl
#else
#define TRACE(message)
#endif
и использование это как:
void Function (int param1, short param2)
{
TRACE ("param1 = " << param1 << ", param2 = " << param2);
}
можно тогда реализовать настроенный вывод трассировки для классов почти таким же способом, которым Вы сделали бы это для вывода к std::cout
.
Если вы не хотите изменять строки, вы можете просто сделать
const char *a[2];
a[0] = "blah";
a[1] = "hmm";
. Когда вы сделаете это так, вы выделите массив из двух указателей на const char
. Затем эти указатели будут установлены на адреса статических строк «бла»
и «хмм»
.
Если вы действительно хотите иметь возможность изменять фактическое содержимое строки, вам нужно сделать что-то вроде
char a[2][14];
strcpy(a[0], "blah");
strcpy(a[1], "hmm");
. Это выделит два последовательных массива по 14 char
s каждый, после чего содержимое статических строк будет скопировано в них.
Ваш код создает массив указателей на функции. Попробуйте вместо этого
char* a[size];
или
char a[size1][size2];
.
См. Вики-книги для массивов и указателей
Строковые литералы имеют вид const char *
s.
И вы используете круглые скобки странно. Вы, вероятно, имеете в виду
const char *a[2] = {"blah", "hmm"};
, который объявляет массив из двух указателей на постоянные символы и инициализирует их так, чтобы они указывали на две жестко заданные строковые константы.
В ANSI C:
char* strings[3];
strings[0] = "foo";
strings[1] = "bar";
strings[2] = "baz";
Вот некоторые из ваших вариантов:
char a1[][14] = { "blah", "hmm" };
char* a2[] = { "blah", "hmm" };
char (*a3[])[] = { &"blah", &"hmm" }; // only since you brought up the syntax -
printf(a1[0]); // prints blah
printf(a2[0]); // prints blah
printf(*a3[0]); // prints blah
Преимущество a2
заключается в том, что затем вы можете сделать следующее с строковые литералы
a2[0] = "hmm";
a2[1] = "blah";
А для a3
вы можете сделать следующее:
a3[0] = &"hmm";
a3[1] = &"blah";
Для a1
вам нужно будет использовать strcpy ()
(еще лучше ] strncpy ()
) даже при назначении строковых литералов. Причина в том, что a2
и a3
являются массивами указателей, и вы можете сделать так, чтобы их элементы (то есть указатели) указывали на любое хранилище, тогда как a1
- это массив из 'массива символов'
Есть несколько способов создать массив строк в C. Если все строки будут одинаковой длины (или, по крайней мере, иметь одинаковую максимальную длину), вы просто объявляете 2 -d массив символов и присвоить при необходимости:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1];
...
strcpy(strs[0], aString); // where aString is either an array or pointer to char
strcpy(strs[1], "foo");
Вы также можете добавить список инициализаторов:
char strs[NUMBER_OF_STRINGS][STRING_LENGTH+1] = {"foo", "bar", "bletch", ...};
Это предполагает, что размер и количество строк в инициализаторе совпадают с размерами вашего массива. В этом случае содержимое каждого строкового литерала (который сам является массивом символов с завершающим нулем) копируется в память, выделенную для strs. Проблема с этим подходом - возможность внутренней фрагментации; если у вас 99 строк длиной 5 или менее символов, но 1 строка длиной 20 символов, 99 строк будут содержать не менее 15 неиспользуемых символов; это пустая трата места.
Вместо использования двумерного массива символов, вы можете сохранить одномерный массив указателей на char:
char *strs[NUMBER_OF_STRINGS];
Обратите внимание, что в этом случае вы выделили только память для хранения указателей на строки; память для самих строк должна быть выделена в другом месте (либо в виде статических массивов, либо с помощью malloc ()
или calloc ()
). Вы можете использовать список инициализаторов, как в предыдущем примере:
char *strs[NUMBER_OF_STRINGS] = {"foo", "bar", "bletch", ...};
Вместо копирования содержимого строковых констант вы просто сохраняете на них указатели. Обратите внимание, что строковые константы могут быть недоступны для записи; вы можете переназначить указатель, например:
strs[i] = "bar";
strs[i] = "foo";
Но вы не сможете изменить содержимое строки; т.е.
strs[i] = "bar";
strcpy(strs[i], "foo");
не может быть разрешено.
Вы можете использовать malloc ()
для динамического выделения буфера для каждой строки и копирования в этот буфер:
strs[i] = malloc(strlen("foo") + 1);
strcpy(strs[i], "foo");
Кстати,
char (*a[2])[14];
Объявляет как 2-элементный массив указателей на 14-элементные массивы char.
Верно! Постоянные строки:
const char *strings[] = {"one","two","three"};
Если я правильно помню.
О, и вы хотите использовать strcpy для присваивания, а не оператор =. strcpy_s безопаснее, но его нет ни в стандартах C89, ни в стандартах C99.
char arr[MAX_NUMBER_STRINGS][MAX_STRING_SIZE];
strcpy(arr[0], "blah");
Обновление: Томас говорит, что strlcpy
- это правильный путь.