БлогNot. C++: старый исходник - в Studio

C++: старый исходник - в Studio

У новичков нередко возникает проблема миграции учебных (и не только) исходников на C++ (или на "простом" C), взятых из эпохи Borland C++ 3.1 и Turbo C, в современные среды вроде Visual Studio. Если с созданием консольного приложения они худо-бедно разбираются, то необходимость поменять пару слов в исходнике часто вызывает ступор :)

Да, без минимальных правок исходного текста программы обычно не обойтись. Но они почти всегда типовые. Кратко перечислю их в этом сообщении.

Во-первых, волшебная директива в начале файла.

1.

#include <alloc.h>

Ошибка. alloc.h - борландовский, чаще всего был нужен для выделения памяти сишными функциями malloc/calloc. Просто подключите вместо него cstdlib.

2. Также обычно нужно добавить к инклудам

#include <clocale>
#include <windows.h>

В начале функции main напишите

setlocale(LC_ALL,"Russian");

для русского текста в консоли, есть ещё setlocale(LC_CTYPE, ".1251"), если кодировка исходника = Windows, и даже setlocale(LC_CTYPE, ".866") должно работать :)

Если нужен ввод русских букв именно в Visual Studio C++, обычно достаточно добавить вместо setlocale

SetConsoleCP(1251);                
SetConsoleOutputCP(1251);

(в чём разница - тут)

3.

#include <conio.h>

Они разные у Микрософта и Борланда. Например, у Микрософта нет Борландовской очистки экрана clrscr() :) Сойдёт на крайний случай

#include <cstdlib>
//...
system("cls");

но учтите :)

Если нужно переставить курсор в консоли на Visual C++ - подойдёт вот эта функция:

void gotoxy(int xpos, int ypos) {
 COORD screen;
 HANDLE handle = GetStdHandle(STD_OUTPUT_HANDLE);
 screen.X = xpos; screen.Y = ypos;
 SetConsoleCursorPosition(handle,screen);
}

Только она нумерует столбцы и строки с нуля, а не с единицы, как борландовская функция. Ну да сделать

xpos--; ypos--;
первой строкой функции, чтоб не перебивать координат при множественных вызовах gotoxy - сообразите.

Имейте в виду, что в Unix/Linux conio.h нет. Если очень нужно, как вариант - решение из этой заметки.

4.

#include <graphics.h>

Вот с этим хуже. Борландовские графические движки устарели и несовместимы с современными. Если переписывать весь графический вывод программы трудоёмко или невозможно, сделайте для неё виртуалку и там запускайте :) "Самопалки" graphics.h, конечно, тоже есть, законченных решений пока не видел.

Вот здесь ещё можно посмотреть BGI'шки для подключения к Studio программ с Borland-совместимой графикой, инструкция там же.

5.

#include <iostream.h>

Было и такое. Уберите .h и добавьте

using namespace std;

после инклудов, чтоб не переписывать все

cout << "Hello";

в

std::cout << "Hello";

6.

#include <math.h>

Само по себе не проблема, но кое-что не переехало в современные Math.h (Builder) или пространство имён Math (Studio).

Самые частые проблемы такие:

  • нет константы пи (M_PI) и т.п. Проще всего - возьмите её определение из math.h и скопируйте в проект:
    #define M_PI        3.14159265358979323846

    ну или

    const double M_PI = 3.14159265358979323846;
  • не найдена перегрузка для какой-нибудь математической функции, например, Studio не поймёт exp(1) ... ну так напишите exp(1.) или exp((double)1) (от вещественного, а не целого аргумента :)

7.

#include <values.h>

Увы, это тоже Борландовский файл, был в его продуктах и последующих Builder от Embarcadero, у Microsoft такого нет. Но некоторые определения есть в стандартном climits (для целых типов), а кое-что в сfloat (для вещественных).

Между прочим, оба файла были и у Борланда.

Например, Borland'овский MAXINT в Visual C++ превращается в INT_MAX (limits.h), а аналогом MAXFLOAT может служить FLT_MAX из float.h (соответственно, вместо MAXDOUBLE пишется DBL_MAX).

Выходов по-прежнему два, или скопировать #define-определение из Борландовского .h-файла, или заменять названия констант во всём проекте. Вот некоторые определения float.h из старых борладовских компиляторов:

#define MAXSHORT    0x7FFF
#define MAXINT      0x7FFF
#define MAXLONG     0x7FFFFFFFL
#define DMAXEXP     308
#define FMAXEXP     38
#define DMINEXP     -307
#define FMINEXP     -37
#define MAXDOUBLE   1.797693E+308
#define MAXFLOAT    3.37E+38
#define MINDOUBLE   2.225074E-308
#define MINFLOAT    8.43E-37

8.

#include <dir.h> 

- отстутствует в Studio. Можно попробовать подключить io.h и использовать методы _findfirst и _findnext для поиска файлов (вместо классических findfirst, findnext).

Кроме того, в windows.h есть структура WIN32_FIND_DATA для работы с каталогами и файлами. Пример: выводим в консоль оглавление головного каталога.

#include <windows.h>
#include <iostream>

using namespace std;

void main() {
 WIN32_FIND_DATA FindFileData;
 HANDLE hf;
 hf=FindFirstFile((LPCSTR)"c:\\*", &FindFileData);
 if (hf!=INVALID_HANDLE_VALUE) {
  do {
   printf("%s\n", FindFileData.cFileName);
  }
  while (FindNextFile(hf,&FindFileData)!=0);
  FindClose(hf);
 }
 system("pause>nul");
}

9.

fflush(stdin);
- не работает нормально в актуальных версиях Studio. Для очистки буфера ввода можно сделать
scanf("%*[^\n]");

Директива при этом включена.

Перед fgets можно и rewind. Вот ввод различных типов данных в консоли Visual Studio 2019:

#define _CRT_SECURE_NO_WARNINGS
#include <cstdio>

int main() {
 
 char ch;
 printf ("\nType one char: ");
 scanf ("%c",&ch);
 printf ("Char=%c (%02X)",ch, ch);
 scanf("%*[^\n]"); //fflush(stdin) не работает в новых версиях Studio
 
 char buf[80];
 printf("\nType string without spaces: ");
 scanf("%s", buf);
 printf("String=%s", buf);
 scanf("%*[^\n]");
 
 printf("\nType string with spaces: ");
 buf[0] = '\0'; //буфер снова пуст
 rewind(stdin); //сброс
 fgets(buf,80,stdin);
 fputs(buf, stdout);

 int d;
 printf("\nType integer number: ");
 scanf("%d", &d);
 printf("Number=%d (dec), %o (oct), %x (hex)", d, d, d);
 scanf("%*[^\n]");
 
 double f;
 printf("\nType float number: ");
 scanf("%lf", &f);
 printf("Number=%12.4f", f);

 return 0;
}

22.02.2015, 22:18 [14610 просмотров]


теги: c++ программирование памятка список ретро studio

показать комментарии (1)