Передача параметра в Си++

Тема в разделе "LANGS.C", создана пользователем REASY, 14 апр 2008.

  1. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Спасибо. Не знал.
     
  2. REASY

    REASY New Member

    Публикаций:
    0
    Регистрация:
    24 дек 2007
    Сообщения:
    108
    _basmp_

    Не знаю на какой бумаге вы имеете ввиду, но этот код не собирается
    Код (Text):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. int sumoflen(const char *words, const int N);
    5.  
    6. int main(int argc, char **argv)
    7. {
    8.     int N;
    9.     int i = 0;
    10.    
    11.     cin >> N;
    12.     cin.get();
    13.  
    14.     char *words  =new char[N+1];
    15.     cin.getline(words,N+1);
    16.  
    17.     cout << sumoflen(words,N);
    18.    
    19.     return 0;
    20. }
    21.  
    22. int sumoflen(const char *words,const int N)
    23. {
    24.  
    25.     int sum = 0;
    26.     sum = strlen(words);
    27.     cout << words <<endl;
    28.     words[0] = 'h';
    29.     cout << words << endl;
    30.     return sum;
    31. }
    Вылетает ошибка: error C2166: l-value specifies const object
    И еще вопрос(надеюсь не тупой =) ), константная переменная, это результат работы препроцессора или все таки в памяти константная переменная отличается от обычной?
     
  3. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    Зависит от реализации. Компилятор _может_ положить её в ro-область памяти, особенно, статическую переменную. Да и для автоматических применяются оптимизации, зависящие от константности. Правда, в последнем случае const - не более, чем спецификатор, т.к. компилятор всё равно увидит как снятие константности, так и неизменение данных, даже если они не помечены как константные.
     
  4. REASY

    REASY New Member

    Публикаций:
    0
    Регистрация:
    24 дек 2007
    Сообщения:
    108
    IceStudent
    Спасибо огромное за разъяснение.
    diamond
    А вам спасибо за красивый метод const char * const*words
    ---
    И вообщем,всем спасибо!
    ---
    PS: помогите разобраться с конструкцией #define TEXTMATRIX(x, y) *(pTextMatrix + (y * nWindowCharsX) + x). То есть тут всего лишь строка pTextMatrix , но способ обращение к элементам интересный какой-то? Просто я хочу написать собственный вариант edit'а, и нужно получше понять делает pTextMatrix
    Код (Text):
    1. #include <windows.h>
    2.  
    3. #define TEXTMATRIX(x, y) *(pTextMatrix + (y * nWindowCharsX) + x)  
    4. // Глобальные переменные
    5. HINSTANCE hinst;        // текущий экземпляр программы
    6. HBITMAP hCaret;     // точечный рисунок каретки
    7. HDC hdc;            // контекст устройства  
    8. PAINTSTRUCT ps;     // информация о прорисовке рабочей области
    9. static char *pTextMatrix = NULL;    // указатель на текстовую матрицу
    10. static int
    11.     nCharX,     // ширина символа в логических единицах
    12.     nCharY,     // высота символа в логических единицах
    13.     nWindowX,       // ширина рабочей области
    14.     nWindowY,       // высота рабочей области
    15.     nWindowCharsX,  // ширина рабочей области для символа
    16.     nWindowCharsY,  // высота рабочей области для символа
    17.     nCaretPosX, // x-координата каретки
    18.     nCaretPosY; // y-координата каретки
    19. static UINT uOldBlink;  // предыдущая частота мерцания
    20. int x, y;           // x и y координаты, используемые в текстовой матрице
    21. TEXTMETRIC tm;      // информация о фонте
    22.  
    23.  
    24.  
    25. int c = 0;
    26. LONG WINAPI WndProc(HWND, UINT, WPARAM, LPARAM);
    27. char a  = 0x30;
    28. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    29.                LPSTR lpCmdLine, int nCmdShow)
    30. {
    31.     HWND hwnd;
    32.     MSG msg;
    33.     WNDCLASS w;
    34.     memset(&w,0,sizeof(WNDCLASS));
    35.     w.style = CS_HREDRAW | CS_VREDRAW;
    36.     w.lpfnWndProc = WndProc;   
    37.     w.hInstance = hInstance;
    38.     w.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    39.     w.lpszClassName = "My Class";
    40.     RegisterClass(&w);
    41.     hwnd = CreateWindow(w.lpszClassName,"My new Tittle",WS_OVERLAPPEDWINDOW,
    42.         200,300,400,580,NULL,NULL,hInstance,NULL);
    43.  
    44.     ShowWindow(hwnd,nCmdShow);
    45.    
    46.     while (GetMessage(&msg, NULL,0,0))
    47.     {
    48.         TranslateMessage(&msg);
    49.         DispatchMessage(&msg); 
    50.         UpdateWindow(hwnd);
    51.     }
    52.  
    53.     return msg.wParam;
    54. }
    55.  
    56. LONG WINAPI WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
    57. {
    58.     switch (message)
    59.     {
    60.         case WM_CREATE:
    61. // Выбор фиксированной ширины системного фонта и получение его текстовой матрицы.
    62.             hdc = GetDC(hwnd);
    63.             SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    64.             GetTextMetrics(hdc, &tm);
    65.             ReleaseDC(hwnd, hdc);
    66. // Сохранение средней высоты и ширины символов.
    67.             nCharX = tm.tmAveCharWidth;
    68.             nCharY = tm.tmHeight;
    69.             return 0;
    70.         case WM_SIZE:
    71. // Определение ширины рабочей области, в пикселях и в количестве символов.
    72.             nWindowX = LOWORD(lParam);
    73.             nWindowCharsX = max(1, nWindowX/nCharX);
    74. // Определение высоты рабочей области, в пикселях и в количестве символов.
    75.             nWindowY = HIWORD(lParam);
    76.             nWindowCharsY = max(1, nWindowY/nCharY);
    77. // Очистка буфера, который содержит введенный текст.
    78.             if (pTextMatrix != NULL)
    79.                 free(pTextMatrix);
    80. // Если имеется достаточно памяти, распределите пространство для буфера ввода текста.
    81.             pTextMatrix = malloc(nWindowCharsX * nWindowCharsY);
    82.             if (pTextMatrix == NULL)
    83.                 ;//ErrorHandler("Not enough memory.");
    84.             else
    85.                 for (y = 0; y < nWindowCharsY; y++)
    86.                     for (x = 0; x < nWindowCharsX; x++)
    87.                         TEXTMATRIX(x, y) = ' ';
    88. // Переместим каретку в начало координат
    89.             SetCaretPos(0, 0);
    90.             return 0;
    91.         case WM_KEYDOWN:
    92.             switch (wParam)
    93.             {
    94.                 case VK_HOME:   // в начало
    95.                     nCaretPosX = 0;
    96.                     break;
    97.                 case VK_END:    // в конец
    98.                     nCaretPosX = nWindowCharsX - 1;
    99.                     break;
    100.                 case VK_PRIOR:  // предыдущая страница
    101.                     nCaretPosY = 0;
    102.                     break;
    103.                 case VK_NEXT:   // следующая страница
    104.                     nCaretPosY = nWindowCharsY -1;
    105.                     break;
    106.                 case VK_LEFT:   // перемещение стрелкой влево
    107.                     nCaretPosX = max(nCaretPosX - 1, 0);
    108.                     break;
    109.                 case VK_RIGHT:  // перемещение стрелкой вправо
    110.                     nCaretPosX = min(nCaretPosX + 1,
    111.                     nWindowCharsX - 1);
    112.                     break;
    113.                 case VK_UP: // перемещение стрелкой вверх
    114.                     nCaretPosY = max(nCaretPosY - 1, 0);
    115.                     break;
    116.                 case VK_DOWN:   // перемещение стрелкой вниз
    117.                     nCaretPosY = min(nCaretPosY + 1,
    118.                     nWindowCharsY - 1);
    119.                     break;
    120.                 case VK_DELETE: // удалить
    121. // Переместите все символы, которые следовали за удаленным символом (на той же самой строке) на один
    122. // пробел обратно (влево) в матрице
    123.                     for (x = nCaretPosX; x < nWindowCharsX; x++)
    124.                         TEXTMATRIX(x, nCaretPosY) = TEXTMATRIX(x + 1, nCaretPosY);
    125. // Замена последнего символа в строке с пробелом.
    126.                     TEXTMATRIX(nWindowCharsX - 1,
    127.                     nCaretPosY) = ' ';
    128. // Прикладная программа будет рисовать вне обработки сообщения
    129. // WM_PAINT, так скрывают каретку.
    130.                     HideCaret(hwnd);
    131. // Перерисовка строки для удаленного символа.
    132.                     hdc = GetDC(hwnd);
    133.                     SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    134.                     TextOut(hdc, nCaretPosX * nCharX,
    135.                         nCaretPosY * nCharY,
    136.                         &TEXTMATRIX(nCaretPosX, nCaretPosY),
    137.                         nWindowCharsX - nCaretPosX);
    138.                     ReleaseDC(hwnd, hdc);
    139. // Показать каретку.
    140.                     ShowCaret(hwnd);
    141.                     break;
    142.             }
    143. // Корректировать позицию каретки, основанную при обработке виртуальной клавиши
    144.             SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
    145.             return 0;
    146.         case WM_CHAR:
    147.             switch (wParam)
    148.             {
    149.             case 0x08:  // Обратный Пробел (Back Space)
    150. // Перемещение каретки на один пробел, а затем обработка этого действия подобно клавише DEL.
    151.                 if (nCaretPosX > 0)
    152.                 {
    153.                     nCaretPosX--;
    154.                     SendMessage(hwnd, WM_KEYDOWN, VK_DELETE, 1L);
    155.                 }
    156.                 break;
    157.             case 0x09:  // табуляция (Tab)
    158. // Табуляция останавливается, проходя каждые четыре пробела, таким образом добавляются пробелы,
    159. // до тех пор, пока пользователь нажимает следующий раз на клавишу табуляции.
    160.                 do
    161.                 {
    162.                     SendMessage(hwnd, WM_CHAR, ' ', 1L);
    163.                 } while (nCaretPosX % 4 != 0);
    164.                 break;
    165.  
    166.             case 0x0D:  // возврат каретки
    167. // Переход к началу следующей строки. Нижняя строка переносится по кругу в верхнюю часть.
    168.                 nCaretPosX = 0;
    169.                 if (++nCaretPosY == nWindowCharsY)
    170.                     nCaretPosY = 0;
    171.                 break;
    172.  
    173.             case 0x1B:  // Escape
    174.             case 0x0A:  // перевод строки
    175.                 MessageBeep((UINT) -1);
    176.                 break;
    177.             default:
    178. // Добавление символа в буфер текста.
    179.                 TEXTMATRIX(nCaretPosX, nCaretPosY) = (char) wParam;
    180. // Прикладная программа будет рисовать вне обработки сообщения WM_PAINT; так скрывают каретку.
    181.                 HideCaret(hwnd);
    182. // Прорисовка символа на экране
    183.                 hdc = GetDC(hwnd);
    184.                 SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    185.                 TextOut(hdc, nCaretPosX * nCharX,
    186.                     nCaretPosY * nCharY,
    187.                     &TEXTMATRIX(nCaretPosX, nCaretPosY), 1);
    188.                 ReleaseDC(hwnd, hdc);
    189. // Отобразим каретку
    190.                 ShowCaret(hwnd);
    191. // Подготовка переноса по словам с начала до конца, если Вы достигли конца строки
    192.                 if (++nCaretPosX == nWindowCharsX)
    193.                 {
    194.                     nCaretPosX = 0;
    195.                     if (++nCaretPosY == nWindowCharsY)
    196.                         nCaretPosY = 0;
    197.                 }
    198.                 break;
    199.             }
    200. // Регулировка позиции каретки, основанной на обработке символа.
    201.             SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
    202.             return 0;
    203.  
    204.         case WM_PAINT:
    205. // Прорисовка всех символов в буфере, строка за строкой.
    206.  
    207.             hdc = BeginPaint(hwnd, &ps);
    208.             SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
    209.             for (y = 0; y < nWindowCharsY; y++)
    210.                 TextOut(hdc, 0, y * nCharY, &TEXTMATRIX(0, y), nWindowCharsX);
    211.             EndPaint(hwnd, &ps);
    212.             break;
    213.         case WM_SETFOCUS:
    214. // Окно имеет фокус ввода. Загрузка каретки определенной ресурсом программного приложения.
    215.             hCaret = LoadBitmap(hinst, MAKEINTRESOURCE(120));
    216. // Создание каретки
    217.             CreateCaret(hwnd, hCaret, 0, 0);
    218. // Регулировка позиции каретки
    219.             SetCaretPos(nCaretPosX * nCharX, nCaretPosY * nCharY);
    220. // Изображение каретки.
    221.             ShowCaret(hwnd);
    222.             break;
    223.         case WM_KILLFOCUS:
    224. // Окно теряет фокус ввода, так что каретка уничтожается.
    225.             DestroyCaret();
    226.             break;
    227.         case WM_DESTROY:
    228.             PostQuitMessage(0);
    229.             break;
    230.         default:
    231.             return DefWindowProc(hwnd, message, wParam, lParam);
    232.         }
    233.         return NULL;
    234. }
     
  5. Xerx

    Xerx Алексей

    Публикаций:
    0
    Регистрация:
    17 фев 2005
    Сообщения:
    528
    Адрес:
    Russia
    Макрос TEXTMATRIX возвращает символ (char) в позиции в буфере (экране), заданной соответствующей координатой (x,y).
    Точка_входа + (номер_строки * ширина_строки + номер_колонки). т.к. размер элемента равен 1 байт, то нет домножения содержимого скобки на размер элемента.
     
  6. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Я не очень хорошо знаю С и С++, особенно теорию. Спасибо, что одернули, зарвался..
    Но код собирается на VC6 без варнингов (-W3 -GX).
    Код (Text):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. int sumoflen(const char *words, const int N);
    5.  
    6. int main(int argc, char **argv)
    7. {
    8.     int N;
    9.     int i = 0;
    10.    
    11.     cin >> N;
    12.     cin.get();
    13.  
    14.     char *words  =new char[N+1];
    15.     cin.getline(words,N+1);
    16.  
    17.     cout << sumoflen(words,N);
    18.    
    19.     return 0;
    20. }
    21.  
    22. int sumoflen(const char *words,const int N)
    23. {
    24.  
    25.     int sum = 0;
    26.     sum = strlen(words);
    27.     cout << words <<endl;
    28.     ((char*)words)[0] = 'h';
    29.     cout << words << endl;
    30.     return sum;
    31. }
    Вставлю свои пять копеек..
    Если не верите просмотрите в отладчике код генерируемый тем-же VC (предположим, что вы включили оптимизацию). Компилер определяет как представить любую переменную исходя из ее использования в проге. Если она не используется, то ей может быть не выделено места вообще. Если только читается - она может генерироваться как константа. Если пишется ей будет выделена память (обычно в месте записи), а вот куда (в кучу, в стек, в дата секцию) зависит от алгоритма оптимизатора. Кроме того константным строкам перед передачей в функцию может выделяться память в куче с копированием их туда. Функции объявленые как инлайн могут не инлайнится, а ф-и не объявленные как инлайн могут инлайнится и оптимизироваться в пределах ф-и в которую заинлайнены.
    Таким образом все спецификаторы, типы, функции итд носят скорее рекомендательный характер. Те нет достаточно строгого соответствия между вашими сорцами и сгенерированым кодом (вообще-то оно есть в пределах одного компилера и одной оптимизации, но нет его описания и познается истина в процессе созерцания скомпиленого кода в дебугере).
     
  7. IceStudent

    IceStudent Active Member

    Публикаций:
    0
    Регистрация:
    2 окт 2003
    Сообщения:
    4.300
    Адрес:
    Ukraine
    _basmp_
    Явное приведение типов. Предполагается, что в этом случае человек знает, что делает (хотя, бывает, что и не знает).

    Верно.

    Истина, но только по данному компилятору и даже его версии.
     
  8. _basmp_

    _basmp_ New Member

    Публикаций:
    0
    Регистрация:
    10 июл 2005
    Сообщения:
    2.939
    Ну в общем-то да. Кроме того на отладке, бывает полезно приводить типы даже в явных случаях. И еще
    Код (Text):
    1. int i=7643634;
    2. int j=(unsigned char)i;
    дает меньший код чем
    Код (Text):
    1. int i=7643634;
    2. int j=0xff & i;
    это о пользе явного приведения.
    сервис паку и ключам компиляции, но истина.
     
  9. _ir4_Y_

    _ir4_Y_ New Member

    Публикаций:
    0
    Регистрация:
    8 мар 2007
    Сообщения:
    76
    собственно все это замечательно но что мешает просто сделать приведение типов ??
    Код (Text):
    1. #include <iostream>
    2. using namespace std;
    3.  
    4. int sumoflen(const char **words, const int N);
    5.  
    6. int main(int argc, char **argv)
    7. {
    8.     const int size = 256;
    9.  
    10.     int N;
    11.     int i = 0;
    12.     cin >> N;
    13.     cin.get();
    14.  
    15.     char **mywords = new char*[N];
    16.  
    17.     for (i = 0; i < N;i++)
    18.         mywords[i] = new char[size-1];
    19.    
    20.     while(i < N)
    21.         cin.getline(mywords[i++],size-1);
    22.  
    23.     cout << sumoflen((const char**)mywords, N) << endl;
    24.    
    25.     return 0;
    26. }
    27.  
    28. int sumoflen(const char **words,const int N)
    29. {
    30.     int i;
    31.     int sum = 0;
    32.     for (i = 0; i < N; i++ )
    33.         sum += strlen(words[i]);
    34.  
    35.     return sum;
    36. }
     
  10. 63F45EF45RB65R6VR

    63F45EF45RB65R6VR New Member

    Публикаций:
    0
    Регистрация:
    26 окт 2011
    Сообщения:
    70
    зы для вас наверное это станет открытием что в .c это компилится а в .cpp нет по крайней мере в msvc 2008 а все почему ? потому что char * -> const char * можно а char ** -> const char ** нельзя иначе будет возможен хак как в примере в .cpp это запретили а в .c до сих пор работает
    Код (Text):
    1. #include <stdio.h>
    2.  
    3. int main()
    4. {
    5.     const char dds = 'j';
    6.     char * ty;
    7.     const char ** cc;
    8.     printf("%c\n", dds);
    9.     cc = &ty; // хак в .c (msvc 2008) можно в .cpp нет
    10.     *cc = &dds;
    11.     *ty = 'k';  
    12.     printf("%c\n", dds);
    13. }
    видите в чем соль ? если бы можно было присваивать char ** -> const char ** в отличии от char * -> const char * то стало бы возможным хитрым движением изменить константу
     
  11. Ezrah

    Ezrah Member

    Публикаций:
    0
    Регистрация:
    22 мар 2011
    Сообщения:
    411
    63F45EF45RB65R6VR
    Дату смотрите.