Странное поведение C ++ std :: string ... Как это исправить? - PullRequest
1 голос
/ 28 апреля 2009

Это сводит меня с ума. Я занимался этим более 2 часов, пытаясь понять это ...

Вот моя проблема. Я работаю над довольно большой программой, которая работает с байесовскими сетями. Вот основная функция:

using namespace std;

int main()
{  
    DSL_network net;
    initializeNetwork(net); 
    setEvidence(net);
    net.SetDefaultBNAlgorithm(7);
    net.SetNumberOfSamples(80000);
    cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
    updateEvidence(net);
    //net.WriteFile("test.dsl");
    return(DSL_OKAY);
}

Это все отлично работает. Проблема возникает, когда я хочу распечатать строку:

using namespace std;

int main()
{  
    //simple string creation
    string a = "test";
    //should print out "test"
    cout << a << endl;
    DSL_network net;
    initializeNetwork(net); 
    setEvidence(net);
    net.SetDefaultBNAlgorithm(7);
    net.SetNumberOfSamples(80000);
    cout << "Samples:\t" << net.GetNumberOfSamples() << endl;
    updateEvidence(net);
    //net.WriteFile("test.dsl");
    return(DSL_OKAY);
}

Вот вывод (только после печати строки a ...):

yΦy ♠ ≈6 ♦

Что может происходить?

UPDATE:

int main()
    {  
        //simple string creation
        string a = "test";
        //should print out "test"
        cout << a << endl;
        return(DSL_OKAY);
    }

все еще печатает

▀ÇΦy♠≈6 ♦

БОЛЬШОЕ ОБНОВЛЕНИЕ: Вот недавний. Я создал новый проект и вставил код, который опубликовал Нил Баттерворт (спасибо, кстати). Я запустил код, и он напечатан правильно. Затем я добавил два файла .lib в компоновщик в новом проекте (smile.lib для библиотеки SMILE и wsock32.lib для использования сокетов.)

Я попробовал код еще раз, и он правильно напечатал первый «тест», а затем напечатал тарабарщину. Это проблема с одним из .libs, который я связываю вместе. Я попробовал каждый из них по отдельности, чтобы увидеть, не конфликтуют ли они, и кажется, что проблема связана с библиотекой smile.lib. Мне нужно будет зайти в их документацию и выяснить, почему.

Есть идеи?

Спасибо всем за помощь

Спасибо

Ответы [ 11 ]

7 голосов
/ 28 апреля 2009

Это странно. Мне всегда нравится разбивать проблему на минимум. Что делает следующая программа при запуске?

using namespace std;
int main() {  
    string a = "test";
    cout << a << endl;
    return 0;
}

Если это работает, значит что-то еще не так, и вам нужно добавлять по одной строке за раз, пока не произойдет сбой. Затем внимательно изучите эту строку очень ("Я охочусь на тараканов").

В зависимости от вашего редактирования может использоваться другой класс строки. Попробуйте это:

int main() {  
    std::string a = "test";
    std::cout << a << std::endl;
    return 0;
}

Обновление:

Поскольку он работает в новом проекте, а не в текущем, проверьте следующее.

  • Убедитесь, что вы связываетесь со стандартными средами выполнения C ++.
  • убедитесь, что вы не #define string считаете чем-то другим (и включает в себя параметр -Dstring=somethingelse командной строки для компилятора).
  • проверьте поведение, используя std::string, а не только string.
2 голосов
/ 28 апреля 2009

Также попробуйте это:

int main()
    {  
        //simple string creation
        string a = "test";
        const char* cStr = a.c_str();
        //should print out "test"
        cout << cStr << endl;
        return(DSL_OKAY);
    }

Если строка const char* не вызывает ошибку компилятора, то мы знаем, что std::str является 8-битной строкой. Если cout не вызывает ошибку компилятора, то мы знаем, что cout определено для 8-битных символов. (И если программа выдаст тот же результат, мы все еще в замешательстве: -}

РЕДАКТИРОВАТЬ (на основе вашего комментария ниже): я заметил, что ошибочный вывод «test» работает до 9 символов - «▀ÇΦy ♠ ≈6 ♦». Попробуйте другие "тестовые" строки, такие как, о, "retest" или "foo". Я подозреваю, что ваш вывод обычно будет 2x или 2x + 1 число символов в исходной строке (12 или 13 для «повторного тестирования», 6 или 7 для «foo».) Это говорит о том, что вы используете 16-битные строки в 8-битный буфер. Я не знаю, как вы можете справиться с этим без компилятора - возможно, у вас есть неверное или устаревшее определение для std :: string и / или cout?

РЕДАКТИРОВАТЬ 2 : Я помню, где я видел это раньше. Пару лет назад я увидел проблему, когда окно консоли DOS искажало вывод программы. (Я не помню точных деталей, но я думаю, что проблема заключалась в том, что консоль DOS не могла обрабатывать наборы символов UTF-8.) Если вы видите этот вывод в окне DOS (или, менее вероятно, если это передается через system() в другую программу), затем попробуйте перенаправить его в файл, затем откройте этот файл с помощью Блокнота. Это может сработать ...

1 голос
/ 28 апреля 2009

Являетесь ли вы на 100% файлом с исходным кодом ASCII? Попробуйте открыть его в каком-нибудь шестнадцатеричном редакторе.

Попробуйте набрать (не копировать / вставить) код в совершенно новом файле и посмотрите, что получится.

Если это не удастся, то, очевидно, что-то повозится с твоим кутом. Не могли бы вы показать нам, какие библиотеки связаны с исполняемым файлом? Может быть, что-то закрывает поток stdout или что-то в этом роде.

1 голос
/ 28 апреля 2009

Проверьте, если

  • У вас есть #include<iostream> и другие соответствующие заголовки включают?
  • net.GetNumberOfSamples() имеет допустимое значение И
  • вы не смешиваете string и wstring.
0 голосов
/ 30 апреля 2009

Предложения:

  • позвоните cout.flush до вашего cout <<, чтобы узнать, получите ли вы странные символы
  • попробуй printf
0 голосов
/ 28 апреля 2009

Возможно ли, что где-то в другом файле в том же проекте, operator << перегружен? пожалуйста попробуйте поискать "operator <<" или "operator<<".

0 голосов
/ 28 апреля 2009

Кажется очень вероятным, что вы смешиваете wchar и char, так что в вашей основной записи фиксированные символы считаются широкими (2 байта / символ) или каким-то юникодом, и ваша библиотека lib для cout считает, что они простые 1 байт / символ. Я бы посмотрел в библиотеках, которые связаны с проектом.

К сожалению, я не совсем уверен, как это исправить. Почти наверняка есть настройка для вашего проекта, которую вы можете изменить (к сожалению, у меня нет VS 2005 передо мной), но вы ищете такие вещи, как wchar, t_char или unicode.

Мне было бы интересно, что произойдет, если вы используете

string a("test");

вместо прямого назначения.

0 голосов
/ 28 апреля 2009

Работает ли преобразование std :: string в строку символов. то есть:

cout << a << endl;

становится

cout << a.c_str() << endl;
0 голосов
/ 28 апреля 2009

Скомпилируйте и запустите следующий точный код; не добавляйте никаких директив using.

#include <iostream>
#include <string>

int main() {
    std::string s = "test";
    for ( unsigned int i = 0; i < s.size(); i++ ) {
        std::cout << s[i];
    }
    std::cout << "\n";
    std::operator<<( std::cout, s );
    std::cout << "\n";
}

Если цикл выдает «test», это означает, что строка в порядке и проблема в выводе. Если второй «тест» искажается, проблема определенно заключается в обработке вывода.

0 голосов
/ 28 апреля 2009

Вы можете попытаться явно указать пространство имен std для строкового типа.

Моя основная причина предложить вам попробовать это в том, что в некоторых из включенных заголовочных файлов может быть определение, которое заменяет строку другим классом или определением. Добавление пространства имен должно привести к тому, что макрос не будет использоваться.

Еще одна вещь, которую нужно проверить, - это получить обработанный список (или список сборок и исходного кода, если вы хотите сделать какой-то взлом сборки) исходного кода, записанного в файл, и проверить его, чтобы увидеть, что происходит Вы, вероятно, найдете там свой ответ, если ничего другого.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...