Мечты о кроссплатформенном коде...

Здравствуйте. Захотелось мне написать программу, которая меняет местами в случайном порядке буквы в слове, кроме первой и последней буквы. Но написать мне захотелось такой код, который бы без проблем компилировался и работал как под windows, так и под linux.

Для осуществления цели был создан макрос:

#define crossWinLinux( win, linux )      
#if ( defined( WIN32 ) || defined( WIN64 ) )
    win;
#else
    linux;
#endif

Который я пытался использовать в таком коде:

#include <iostream>
#include <fstream>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <ctime>

#define crossWinLinux( win, linux )      
#if ( defined( WIN32 ) || defined( WIN64 ) )
    win;
#else
    linux;
#endif

crossWinLinux( #include<windows.h>, 0 );

using namespace std;

int main()
{
    setlocale( 0, "" );
    srand( static_cast< unsigned int >( time( NULL ) ) );
    cout << "*** Данная программа показывает, ***\n"
         << "*** на что способен наш мозг. ***\n"
         << "*** Программа случайно меняет местами все буквы в слове, ***\n"
         << "*** кроме первой и последней. ***\n"
         << "*** Но ваш мозг всё равно будет в состоянии понять смылс слова ***\n" << endl;
    crossWinLinux( ( string input ), ( wstring input ) );
    while ( true )
    {
        cout << "*** Введите предложение( exit - для выхода ) ***\n"
             << "  ?_ ";
        crossWinLinux( ( getline( cin, input ); ), ( getline( wcin, input ); ) );
        if ( input == "exit" )
            break;
        crossWinLinux( 
            ( stringstream stream; string temp; ), 
            ( wstringstream stream; wstring temp; ) 
        );        

        cout << "\n*** Перекодированное предложение: ";
        while ( stream >> temp )
        {
            if ( temp.size() > 3 )
                for ( size_t i = 1; i < temp.size() - 1; i++ )
                    swap( temp[ i ], temp[ rand() % ( ( temp.size() - 1 ) ) + 1 ] );

            crossWinLinux (
                (
                    char *buffer = new char[ temp.c_str() + 1 ];
                    OemToCharA( temp.c_str(), buffer );
                    cout << buffer << " ";
                    delete []buffer;
                ),

                ( wcout << temp << " " );
            );
        }
        cout << endl << endl;
    }
    cout << "*** Досвидания. Для выхода нажмите <Enter> ***\n";
    cin.get();
    return 0;
}

Ругается на любое использование stream, input и temp.
Утверждает, будь то не знает эти имена.

Так же выкрикивал такие неприличные фразы как:

main.cpp:12:2: error: expected unqualified-id before numeric constant
  linux;
  ^

Чем я не угодил компилятору? :)

Меня больше волнует это:

Да, ошибочка вышла. Проблема в том, что я несколько раз переписывал код, и последний вариант, так как он не компилировался, протестировать не удалось. Изначально там стояло temp.lenght() + 1.

Что касается всяких макросов, то чем typedef'ы не угодили?

#if ( defined( WIN32 ) || defined( WIN64 ) )
    typedef std::string String ;
    typedef std::stringstream SStream ;
    //...
#else
    typedef std::wstring String ;
    typedef std::wstringstream SStream ;
    //...
#endif

Что касается всяких макросов, то чем typedef'ы не угодили?

typedef'ы это хорошо, но ведь есть и другие места, где этим оператором не обойтись.( хотя, конечно, в данном случае только одно место( где вывод ), но на будущее... )

Ещё вопрос: насколько я помню gcc под windows не хотел компилировать строку L"выход" ( собирась добавить ) ругался на какую-то неправильную последовательность байт. Или нет?

Не вижу причин, чтобы оно не работало.

cout << "Тоже стандартное действие, однако данное сообщение не будет показано нормально в Windows" << endl;

Это проблема поддержки non-ansi кодировок в cmd.exe. Не проблема стандарта

Ну да, я знаю, что это проблема cmd.exe. Но ведь стандарт не работает, хотя вина не его. А значит, я не мог быть 100 процентно уверен в роботоспособности. Поэтому я применял конструкции, в роботоспособности которых я уверен.

Стандарт не может работать или не работать. Он может только существовать, как набор определений.
Не работать может реализация стандарта. Но в данном случае все работает, просто устройство вывода не поддерживает отображение расширенных символов cp1251 или юникода по умолчанию.
Ты можешь перенаправлять вывод cout в файл и он нормально прочитается текстовым редактором с поддержкой нужной кодировки.

в данном случае только одно место( где вывод ), но на будущее...

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

У меня на VS2010 этот код не компилируется. Выводит такие ошибки:

1>d:\мои документы\программирование\3_temp_msvs2010\temp_msvs2010\examples.cpp(98): error C4430: missing type specifier — int assumed. Note: C++ does not support default-int
1>d:\мои документы\программирование\3_temp_msvs2010\temp_msvs2010\examples.cpp(122): error C2065: 'input' : undeclared identifier
1>d:\мои документы\программирование\3_temp_msvs2010\temp_msvs2010\examples.cpp(130): error C2065: 'stream' : undeclared identifier
1>d:\мои документы\программирование\3_temp_msvs2010\temp_msvs2010\examples.cpp(130): error C2065: 'temp' : undeclared identifier

Требует указать спецификатор типа для win и linux, а также объявить идентификаторы для input,stream и temp.

Мне кажется, что твой хитрый макрос должен выглядеть так:

#define crossWinLinux( win, linux )  \
#if ( defined( WIN32 ) || defined( WIN64 ) ) \
    win; \
#else  \
    linux;  \
#endif

Да, так работает. Спасибо. Но я так понял что толку от этого макроса никого. Или всё таки он есть?

Я бы сказал, что такой макрос — штука опасная. Легко можно получить странные ошибки при компиляции.

Обычно фрагменты, различные для разных ОС или версий одной ОС, оформляют просто с использованием директив условной компиляции. Примеры можно посмотреть в заголовочных файлах стандартной библиотеки (CRT) или STL.

Внимание! Это довольно старый топик, посты в него не попадут в новые, и их никто не увидит. Пишите пост, если хотите просто дополнить топик, а чтобы задать новый вопрос — начните новый.

Ответить

Вы можете использовать разметку markdown для оформления комментариев и постов. Используйте функцию предпросмотра для проверки корректности разметки.

Пожалуйста, оформляйте исходный код в соответствии с правилами разметки. Для того, чтобы вставить код в комментарий, скопируйте его в текстовое поле ниже, после чего выделите то, что скопировали и нажмите кнопку «код» в панели инструментов. Иначе ваш код может принять нечитаемый вид.

Либо производите оформление кода вручную, следующим образом:

``` #include <iostream> using namespace std; int main() { // ... } ```

Предпросмотр сообщения

Ваше сообщение пусто.