Компьютерный форум
Правила
Вернуться   Компьютерный форум > Форум программистов > Программирование под Windows > C++ Builder
Перезагрузить страницу C/C++ FAQ как вывести русские символы
Ответ
 
Опции темы Опции просмотра
  (#1 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию C/C++ FAQ как вывести русские символы - 01.05.2003, 12:59

О чем этот FAQ ?
******************************
1. Как вывести русские символы в стандартном потоке вывода?
2. Как правильно сравнивать строки?
3. Как преобразовать в программе число в строку?
4. Как определить, в какой операционной системе работает программа?
5. Как из работающей программы определить каталог, в котором она находится?
6. Как сделать коллбэк, если функции принадлежат к разным классам?
7. Как синхронизировать файловый менеджер с событиями изменений открытых файлов?
8. Как сделать DLL с нормальными экспортами, как у системных DLL Windows?
9. Какие стандартные функции сортировки лучше использовать?
10. Как узнать путь к какой-либо системной папке, например, Автозагрузка?
11. Как из работающей программы запустить внешнюю программу?
12. Почему при записи в файл размер файла получается больше, чем размер буфера с данными?
13. Bjarne Stroustrup's C++ Style and Technique FAQ.
Ответить с цитированием
  (#2 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:00

Q: Как вывести русские символы в стандартном потоке вывода? У меня вместо русских символов выводятся каракули.

A: Правильно выводить русские символы нужно так:
Код:
char buf[256];  // размер буфера зависит от размера исходной строки
::CharToOem( "Привет, Мир!n", buf );
cout << buf;
Ответить с цитированием
  (#3 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:01

Q: Как правильно сравнивать строки? Я сравниваю одинаковые строки и оказывается, что они не равны. Вот исходник:
Код:
BOOL Test()
{
   char classname[256];
   char editclass[256];
   strcpy(classname, "edit");
   strcpy(editclass, "edit");
   if (classname == editclass) return TRUE;
   else return FALSE;
}
Почему?

A: Потому, что имена символьных массивов в C++ - это указатели.
Указатели, естественно, не равны друг другу. Правильным решением будет применение функции strcmp:
Код:
if (strcmp(classname, editclass) == 0) return TRUE;  // строки совпали
else return FALSE;  // не совпали
Ответить с цитированием
  (#4 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:02

Q: Как преобразовать в программе число в строку, с тем чтобы вывести его в какой-нибудь EditBox именно в виде строки?

A: Преобразовать число в строку можно так:
Код:
CString   str;
DWORD   dwVariable = 0x277FEA14;
str.Format("%x", dwVariable);
Можно применить функции itoa(), sprintf(). Для полной информации по функциям itoa(), sprintf(), CString::Format() см. MSDN.
Ответить с цитированием
  (#5 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:03

Q: Как программа может сама определить, в какой операционной системе она работает?

A: Как всегда - GetVersion() или GetVersionEx(). Пример:
Код:
OSVERSIONINFO osvi;
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
::GetVersionEx(&osvi);

BOOL bIsWindows98orLater =
     (osvi.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) &&
     ( (osvi.dwMajorVersion > 4) ||
     ( (osvi.dwMajorVersion == 4) && (osvi.dwMinorVersion > 0) ) );
Ответить с цитированием
Ads.
  (#6 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:04

Q: Как програмно, из работающей программы определить каталог, в котором она находится? Это для того, чтобы потом запустить из этого каталога другую программу.

A: Нет ничего проще. Имя текущего каталога программно можно получить так:
Код:
TCHAR buffer[MAX_PATH + 1];
GetCurrentDirectory(MAX_PATH, buffer);
// в buffer получено имя каталога
Однако если программа при своей работе изменит текущий каталог, то функция вернет имя нового текущего каталога, а не того, из которого был запущен exe-файл программы. Поэтому получить имя каталога программы лучше всего как можно раньше после ее старта.

Второй вариант:
использовать функцию API GetModuleFileName:
Код:
    TCHAR szPath[MAX_PATH + 1];
    ZeroMemory(szPath, sizeof(szPath));
    ::GetModuleFileName(NULL, szPath, MAX_PATH));
Ответить с цитированием
  (#7 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:05

Q: Как сделать коллбэк, если функции принадлежат к разным классам?

A: Вызывать функцию надо примерно так:
Код:
#include <iostream>
int f(int i)
{
   std::cout << "i = " << i << std::endl;
   return 0;
}
////////////////////////////
class A
{
public:
   int fA(int i) { return f(i); }
};
////////////////////////////
class B
{
public:
   typedef int (A::*PFA)(int);
   // в конструкторе сохраняем указатель на функцию - для callback
   B() { m_pFA = &A::fA; }

   void fB()
   {
      // вызываем callback-функцию
      (m_A.*m_pFA)(3);
   }
private:
   A m_A; // объект класса А
   PFA m_pFA; // указатель на метод из класса А
};

typedef int (*PF)(int);

int main(int argc, char** argv)
{
   // два способа сделать одно и то же:
   int (*pf1)(int) = f; // здесь явно определяем указатель на функцию
   PF pf2 = f;         // а здесь через созданный тип указателя на функцию

   pf1(1);
   pf2(2);

   B b;
   // эмулируем callback-вызов
   b.fB();

   return 0;
}
И еще один небольшой комментарий.
Обратите внимание, что сохраненный указатель на член-функцию может быть применимым только к конкретному объекту (и это вполне логично!). Дело в том, что тот же Страуструп в п.15.5. объясняет причину этого: указатель на член-функцию больше соответствует некоторому смещению (относительно объекта), чем на самом деле указателю. Таким образом, объект (т.н. база) + смещение = нужная член-функция объекта. (Только не думайте, что это на самом деле смещение - в отличие от виртуальной функции! - что, голову совсем запутал?)
И вообще:
а) указатели на виртуальные члены-функции можно передавать между различными объектами (т.к. размещение такой функции по отношению к объекту регулируется положением в vtbl и не зависит от расположения объекта в памяти);
б) указатели на обыкновенные член-функции НЕЛЬЗЯ передавать между разными объектами.

См. также обсуждение в Форуме.
Ответить с цитированием
  (#8 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:06

Q: Как синхронизировать файловый менеджер с событиями изменений открытых файлов? В чем секрет?

A: Для этого используется функция FindFirstChangeNotification(), единственное "но" - функция оповещает об изменениях в директории, а не в конкретном файле, поэтому необходимо самому определить изменения. Можно делать это по размеру файла, а можно - считать для файла контрольную сумму CRC32. Подойдут и другие методы контроля за изменением содержимого файла.

См. также обсуждение в Форуме.
Ответить с цитированием
  (#9 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:06

Q: Как сделать DLL с нормальными экспортами, как у системных DLL Windows? Если пишу extern "C" __declspec(dllexport) int __stdcall func(int), получается (я надеюсь) stdcall, но имена _func@4; а хочется func.

A: Джеффри Рихтер пишет по этому поводу:
"Дело в том, что компилятор Microsoft С, экспортируя С-функцию, искажает eе имя, даже если Вы вообще не пользуетесь С++. Это происходит, только когда Ваша функция экспортируется по соглашению __stdcall. (Увы, это самое популярное соглашение.) Тогда компилятор Microsoft искажает имя С-функции, впереди ставит знак подчеркивания, а к концу добавляет суффикс, состоящий из символа @ и числа байтов, передаваемых функции в качестве параметров.
Например, следующая функция экспортируется в таблицу экспорта DLL как _MyFunc@8:
Код:
__declspec(dllexport) LONG __stdcall MyFunc(int a, int b);
Чтобы средствами Microsoft собрать DLL, способную работать с инструментарием от другого поставщика, нужно указать компилятору Microsoft экспортировать имя функции без искажений."

Сделать это можно несколькими способами.

Первый — создать DEF-файл для Вашего проекта и включить в него раздел EXPORTS так:
Код:
EXPORTS MyFunc
Компоновщик от Microsoft, анализируя этот DEF-файл, увидит, что экспортировать надо обе функции: _MyFunc@8 и MyFunc. Поскольку их имена идентичны (не считая вышеописанных искажений), компоновщик на основе информации из DEF-файла экспортирует только функцию с именем MyFunc, а функцию _MуFunc@8 не экспортирует вообще.

Второй — надо добавить в Linker->Command line->Additional Options к опциям линкера дополнительные параметры. Например, Вы экспортируете две функции и хотите обойтись без искажения имен, в command line нужно добавить:
Код:
/export:Func1 /export:Func2
Этот способ имеет небольшое ограничение: сравнительно небольшое число экспортируемых функций. Представьте себе программиста, судорожно пытающегося найти опечатку в опциях линкера "/export" для хотя бы полусотни экспортируемых имен...

Третий способ — Вы можете в .CPP файле написать
Код:
#pragma comment(linker, "/export:Func1=_Func1@4")
и линкер экспортирует как недекорированное имя Func1, так и декорированное имя _Func1@4, причем оба они будут указывать на одну и ту же функцию.
Ответить с цитированием
  (#10 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:08

Q: Какие стандартные функции сортировки лучше использовать?

A: В C++ это std::sort, qsort().
Вот результаты тестов. Все результаты получены на двух машинах, приведенные цифры - число тиков таймера, вычисленное как среднее из результатов пяти прогонов. Сравнивалась скорость сортировки четырехбайтовых и восьмибайтовых целых чисел. Код поразрядной сортировки и QSort написан и откомпилирован Delphi 7, код std::sort и qsort откомпилирован Intel C++ 4.5.

На машине Celeron 300, 192 Мб ОЗУ, шина 66 МГц:
Код:
Число эл-тов       100`000    1`000`000   10`000`000
Разрядность,байт   4     8     4     8     4       8

std::sort         80   130    851  1143   9584   16954
qsort() C++      221   381   2613  5147  62049  124529
Поразрядная       55   178    674  2141   9684   22143
QSort (Delphi)   100   168   1178  2113  14380   25136
На машине Celeron 1000, 512 Мб ОЗУ, шина 133 МГц:
Код:
Число элементов      100`000   1`000`000   10`000`000
Разрядность, байт     4    8     4    8      4     8

std::sort            20   30   301   561   3835   7330
qsort() C++          70  140   911  1843  20369  41049
Поразрядная          20   83   223   836   2354   8482
QSort (Delphi)       30   53   396   773   5038   9884
Подробнее см. здесь.
Ответить с цитированием
  (#11 (permalink)) Старый
Влад Влад вне форума
Специалист
 
Сообщений: 3,884
Сказал(а) спасибо: 1
Поблагодарили 25 раз(а) в 25 сообщениях
Регистрация: 27.06.2002
Адрес: Санкт-Петербург
По умолчанию 01.05.2003, 13:09

Q: Как узнать путь к какой-либо системной папке, например, Автозагрузка ?

A: Используй функцию оболочки SHGetSpecialFolderLocation(), это официально документированный Microsoft способ.
Идентификаторы соответствующих системных папок см. в MSDN.
Ответить с цитированием
  (#12 (permalink)) Старый
Olesya Olesya вне форума
Member
 
Сообщений: 1,485
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 11.06.2002
По умолчанию 03.05.2003, 00:12

Q: Как запустить внешнюю програму из своей?
A: Существует несколько вариантов решения этого вопроса.
1. system
Пример:
Код:
system( "c:program filesmyappmyapp.exe" );
2. WinExec
Пример:
Код:
WinExec("C:Program FilesmyAppmyApp.exe", SW_SHOW);
3. ShellExecute, ShellExecuteEx
Пример:
Код:
ShellExecute(handle, NULL, path_to_folder, NULL, NULL, SW_SHOWNORMAL);
4. CreateProcess
Пример:
Код:
STARTUPINFO start_info;
ZeroMemory( & start_info , sizeof( start_info) );
start_info.cb = sizeof(start_info);
PROCESS_INFORMATION proc_info;
ZeroMemory( & proc_info , sizeof( proc_info ) );
if(!CreateProcess(NULL,
“notepad.exe”, 
NULL,
NULL,
FALSE;
0,
    NULL,
    NULL,
    &start_ino,
    &proc_info))
    {
    printf(“Creation process failed!n”);
    return -1;
    }

Подробное описание см. в MSDN
Ответить с цитированием
Ads
  (#13 (permalink)) Старый
Olesya Olesya вне форума
Member
 
Сообщений: 1,485
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 11.06.2002
По умолчанию Re: C/C++ FAQ - 25.06.2003, 23:37

Q: При записи в файл один буфер размером 4 кБ, а размер файла получается почти 5 кБ. Где ошибка?

А: Неправильно открыт файл. Он открыт как текстовый, соответствено, данные будут писаться как текст. Так как маркером конца строки в ОСях Microsoft является код 0x0D 0x0A (CR-LF), перед каждым байтом 0x0A будет дописан еще 0x0D. Чтобы было все правильно, надо файл открывать как бинарный.

Пример неправильного кода:
Код:
FILE *file = fopen("file.ext", "w");   // Ошибка!!!
long cwb = fwrite(pBuffer, BUFFER_SIZE, CountBuffers, file);
fclose(file);
В этом случае размер файла будет BUFFER_SIZE*CountBuffers + [количество 0x0А во всех записываемых буферах].

Теперь пишем правильно:
Код:
FILE *file = fopen("file.ext", "wb");
long cwb = fwrite(pBuffer, BUFFER_SIZE, CountBuffers, file);
fclose(file);
В этом случае размер файла будет BUFFER_SIZE*CountBuffers.
Ответить с цитированием
  (#14 (permalink)) Старый
Shunix Shunix вне форума
Member
 
Сообщений: 1,355
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 07.06.2002
По умолчанию 25.04.2005, 19:25

/* Возможно, это тоже будет кому-нибудь интересно и, что самое главное, полезно: */
Bjarne Stroustrup's C++ Style and Technique FAQ

Смотрите также дополнительные ссылки на странице.
Ответить с цитированием
  (#15 (permalink)) Старый
michael michael вне форума
Member
 
Сообщений: 969
Сказал(а) спасибо: 0
Поблагодарили 0 раз(а) в 0 сообщениях
Регистрация: 08.08.2003
По умолчанию 26.02.2007, 18:56

Q: Как сделать коллбэк, если функции принадлежат к разным классам?

A2:
В объектно-ориентированном стиле лучше всего использовать абстрактный callback-интерфейс:
Код:
class ICallback //abstract
{
public:
    virtual void notify() = 0;

protected:
    ~ICallback() {}
};
Класс, который реализует вызов callback-функции, хранит у себя не указатель на функцию, как это обычно делается, а указатель на интерфейс ICallback:
Код:
class A
{
public:
    void set_callback( ICallback* _object ) { _remote_object = _object; }
    // ...
    void func();
    // ...
private:
    ICallback* _remote_object;
};

void A::func()
{
    // ...
    if ( _remote_object != NULL )
        _remote_object->notify();
}
Класс, нуждающийся в уведомлении от класса A, наследуется от ICallback и реализует метод notify():
Код:
class B : public ICallback
{
public:
    B( A& a ) { a.set_callback( this ); } 
private:
    virtual void notify();
    // ...
};

void B::notify()
{
    // Реагируем на сообщение от класса A.
}
Преимущество такого подхода заключается в независимости интерфейса класса A от класса B. Он уже не нуждается в ссылке на класс B в callback-указателе, т.е. реализовать callback можно также в любом другом классе. Кроме того можно использовать интерфейсы с несколькими callback-функциями, а также можно добавить в callback-интерфейс указатель на свой класс для организации списка вызова.
Например:
Код:
class ICallbackInsertRemove //abstract
{
public:
    virtual void inserted( unsigned disk_number ) = 0;
    virtual void removed( unsigned disk_number ) = 0;

    ICallbackInsertRemove* next;

protected:
    ICallbackInsertRemove() : next( NULL ) {}
    ~ICallbackInsertRemove() {}
};
Организация вызова примерно следующая:
Код:
void A::func()
{
    // ...
    for ( ICallbackInsertRemove* ro = _remote_object; ro != NULL; ro = ro->next )
        ro->inserted( disk ); // или, например, ro->removed( disk )
}
Ну и, разумеется, для списка нужно доработать функцию set_callback() и, возможно, добавить функцию remove_callback().
Ответить с цитированием
Ads
Ответ

Опции темы
Опции просмотра

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Trackbacks are Вкл.
Pingbacks are Вкл.
Refbacks are Выкл.


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Не заносятся русские символы в базу Виталик 1 PHP 2 26.08.2011 03:10
Русские Samsung booster Мониторы 6 24.12.2009 20:37
DVD-rom нужно вывести символы по адресу Dexter-x Железо. Написание драйверов 2 31.01.2009 01:50
В приложениях исчезли русские символы. PiLiGriM Техническая поддержка 2 14.10.2008 17:22
Как в буфер wchar_t занести русские символы Antsu Visual C++ 1 07.05.2008 17:52
Encoding как отобразить русские символы kinder .NET 2 24.11.2006 00:50
Русские символы в cgi скриптах в Линуксе. forewar C++ на Unix 9 15.09.2006 23:54
Как вставить русские символы Northwood Java 1 27.08.2005 14:45
Как в Memo поставить русские символы SuMiSc Delphi 9 01.04.2005 00:17
как сделать, чтобы в программе русские символы отображались корректно Malnor Вопросы начинающих программистов 1 31.08.2004 23:53
Microsoft Visual C++ FAQ как вывести русские буквы Влад Программирование под Windows 6 23.04.2004 18:57
Шрифты русские на VC++ imported_Torres Visual C++ 1 23.03.2004 19:22



Powered by vBulletin® Version 3.8.7
Copyright ©2000 - 2018, Jelsoft Enterprises Ltd.
Нardforum.ru - компьютерный форум и программирование, форум программистов