2016-03-05 1 views
2

Я пытаюсь запросить SQL Server (Express) через Visual C++ (экспресс) и сохранить полученный набор данных в вектор C++ (массив также был бы большим). С этой целью я исследовал библиотеку ADO и нашел много помощи в MSDN. Короче говоря, ссылайтесь на библиотеку msado15.dll и используйте эти функции (особенно привязку записи ADO, для которой требуется icrsint.h). Короче говоря, я смог запросить базу данных и отобразить значения полей с помощью printf(); но я спотыкаюсь, когда пытаюсь загрузить значения полей в вектор.ADO Recordset Значение поля для вектора/массива C++ (значение указателя захвата)

Первоначально я попытался загрузить значения, выставив все как char * (из-за отчаяния после многих ошибок преобразования типов) только для того, чтобы найти конечный результат был вектор указателей, которые все указали на один и тот же адрес памяти. Далее (и это код, приведенный ниже). Я попытался присвоить значение местоположения памяти, но в итоге я получил вектор первого символа только в памяти. Короче говоря, мне нужна помощь в понимании того, как передать все значение, хранящееся в указателе Fieldset (rs.symbol) указателя (в то время, когда оно передается вектору), а не только первого символа? В этом случае значения, возвращаемые из SQL, являются строками.

#include "stdafx.h" 
#import "msado15.dll" no_namespace rename("EOF", "EndOfFile") 
#include "iostream" 
#include <icrsint.h> 
#include <vector> 
int j; 
_COM_SMARTPTR_TYPEDEF(IADORecordBinding, __uuidof(IADORecordBinding)); 
inline void TESTHR(HRESULT _hr) { if FAILED(_hr) _com_issue_error(_hr); } 
class CCustomRs : public CADORecordBinding { 
    BEGIN_ADO_BINDING(CCustomRs) 
     ADO_VARIABLE_LENGTH_ENTRY2(1, adVarChar, symbol, sizeof(symbol), symbolStatus, false) 
     END_ADO_BINDING() 
public: 
    CHAR symbol[6]; 
    ULONG symbolStatus; 
}; 
int main() { 
    ::CoInitialize(NULL); 
    std::vector<char> tickers; 
    try { 
     char sym; 
     _RecordsetPtr pRs("ADODB.Recordset"); 
     CCustomRs rs; 
     IADORecordBindingPtr picRs(pRs); 
     pRs->Open(L"SELECT symbol From Test", L"driver={sql server};SERVER=(local);Database=Securities;Trusted_Connection=Yes;", 
      adOpenForwardOnly, adLockReadOnly, adCmdText); 
     TESTHR(picRs->BindToRecordset(&rs)); 
     while (!pRs->EndOfFile) { 
      // Process data in the CCustomRs C++ instance variables. 
//Try to load field value into a vector 
      printf("Name = %s\n", 
       (rs.symbolStatus == adFldOK ? rs.symbol: "<Error>")); 


//This is likely where my mistake is 
sym = *rs.symbol;//only seems to store the first character at the pointer's address 


      // Move to the next row of the Recordset. Fields in the new row will 
      // automatically be placed in the CCustomRs C++ instance variables. 
//Try to load field value into a vector 
      tickers.push_back (sym); //I can redefine everything as char*, but I end up with an array of a single memory location... 
      pRs->MoveNext(); 
     } 
    } 
    catch (_com_error &e) { 
     printf("Error:\n"); 
     printf("Code = %08lx\n", e.Error()); 
     printf("Meaning = %s\n", e.ErrorMessage()); 
     printf("Source = %s\n", (LPCSTR)e.Source()); 
     printf("Description = %s\n", (LPCSTR)e.Description()); 
    } 
    ::CoUninitialize(); 
//This is me running tests to ensure the data passes as expected, which it doesn't 
    std::cin.get(); 
    std::cout << "the vector contains: " << tickers.size() << '\n'; 
    std::cin.get(); 
    j = 0; 
    while (j < tickers.size()) { 
     std::cout << j << ' ' << tickers.size() << ' ' << tickers[j] << '\n'; 
     j++; 
    } 
    std::cin.get(); 
} 

Благодарим за любые рекомендации, которые вы можете предоставить.

ответ

0

A std::vector<char*> не работает, потому что тот же буфер используется для всех записей. Поэтому, когда вызывается pRs->MoveNext(), новое содержимое загружается в буфер, перезаписывая предыдущий контент.

Вам необходимо сделать копию содержания.

Я хотел бы предложить использовать std::vector<std::string>:

std::vector<std::string> tickers; 
... 

    tickers.push_back(std::string(rs.symbol)); 
+0

Могу ли я спросить, почему это было приостановлено? – alain

+0

Hey alain (я не уменьшал это, просто FYI). Я принял ваш совет и переработал вектор тиккеров и push_back, как вы упомянули. Однако, когда у меня есть программа, напечатайте значения в результирующем векторе, используя printf («% s \ n», тикеры [j]); значения, хранящиеся в векторе, кажутся jibberish ... Я пропустил что-то еще здесь? – Shawn802

+0

Вы можете использовать 'cout <<', как в вопросе, или 'printf ("% s \ n ", tickers [j] .c_str());'. Я знаю, что вы не спустили вниз, я думаю, это из-за комментария, который я написал на мета. – alain

0

Почему вы не использовали std::string вместо std::vector? Для добавления символов используйте одну из следующих функций: basic_string& append(const CharT* s); - для cstrings, basic_string& append(const CharT* s,size_type count); - в противном случае. Подробнее: http://en.cppreference.com/w/cpp/string/basic_string/append.

Если вы хотите, чтобы линия перерывов, просто добавьте '\n', где вы этого хотите.

+0

Не уверен, если я понимаю это. Я хочу использовать массив, потому что у меня будет много элементов - этот массив/вектор будет использоваться для создания дополнительных массивов/векторов; поэтому я хотел использовать вектор для управления рабочим процессом. Я не хочу, чтобы у меня была одна длинная строка. – Shawn802

+0

Да, 'string.append' предназначен для добавления отдельных символов в строку, поэтому здесь это не работает. – alain

Смежные вопросы