Złe wpisy w pliku ini - czas systemowy

0

Witam. mam program działający jako baza danych numerów, które wpisze. razem z nimi jest dodawana data wpisania. Numer jest zapisywany jednoczesnie w pliku INI_1 oraz data w pliku INI_2. Mój problem polega na tym, że za każdym razem w pliku INI zapisuje sie pod każdym elementem bazy danych data ostatniego wpisanego elementu. Spędzam juz 2 dni nad szukaniem problemu, pomożecie?

 
#include <windows.h>
#include <windowsx.h>
#include <process.h>
#include <commctrl.h>
#include <string>
#include <vector>
#include <ctime>


#define ID_DODAJ 1
#define ID_USUN 2
#define ID_TRAY 3
#define CMSG_TRAY 0x8001

using namespace std;

vector <char *> vCzas;


LRESULT CALLBACK WindowProcedure (HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ListWndProc( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam );
WNDPROC g_OldWndProc;

struct sSTATUS{
    LPCSTR nazwa;
    NOTIFYICONDATA nid;
};
struct sSTATUS status;

char szClassName[ ] = "CLASS_DZIENNIK";
HINSTANCE *hInstance;
HWND hwnd;

bool f_DodajNumer(string numer);
bool f_UsunNumer();
bool f_KasujStare();
bool f_Wyszukaj(string numer);
void f_WyszukajFraze(string numer);
void f_Wczytaj();
void f_Zapisz();

void DodajStruktureCzasu();
void UsunStrukture(int index);

HWND hLista, hWpisz, hSzukaj, hDodaj, hUsun, hKasujStare, hInformacje;

bool f_DodajNumer(string numer){
    if(f_Wyszukaj(numer) == false)
    {
        SendMessage(hLista, LB_ADDSTRING, -1, (LPARAM)numer.c_str());
        SendMessage(hLista, LB_SETCURSEL, SendMessage(hLista, LB_GETCOUNT, 0, 0)-1, 0);
        DodajStruktureCzasu();
        f_Zapisz();
    }
    else
    {
        MessageBox(0, "Podany numer jest juz w bazie danych !", "Blad Dodania", MB_ICONWARNING | MB_OK);
    }
    SetWindowText(hWpisz, "");
    return true;
}
bool f_UsunNumer(){
    UsunStrukture(SendMessage(hLista, LB_GETCURSEL, 0, 0));
    SendMessage(hLista, LB_DELETESTRING, SendMessage(hLista, LB_GETCURSEL, 0, 0), 0);
    f_Zapisz();
    return true;
}
bool f_Wyszukaj(string numer){
    int result = ListBox_FindString(hLista, 0, numer.c_str() );
    if(result == LB_ERR)
        return false;
    else
    {
        int dlugosc = ListBox_GetTextLen(hLista, result);
        if(dlugosc == (int)numer.length())
        {
            SendMessage(hLista, LB_SETCURSEL, result, 0);
            return true;
        }
        return false;
    }
}
void f_WyszukajFraze(string numer){
    int result = ListBox_FindString(hLista, 0, numer.c_str() );
    if(result == LB_ERR)
        SendMessage(hLista, LB_SETCURSEL, -1, 0);
    else
    {
        SendMessage(hLista, LB_SETCURSEL, result, 0);
    }
}
void f_Wczytaj(){
    int ilosc = GetPrivateProfileInt("DZIENNIK", "ilosc", 0, "C:\\Dziennik.ini");
    for(int n=0; n<ilosc; n++)
    {
        char index[5];
        char tekst[50];
        itoa(n, index, 10);
        GetPrivateProfileString("DZIENNIK", index, NULL, tekst, 50, "C:\\Dziennik.ini");
        SendMessage(hLista, LB_ADDSTRING, -1, (LPARAM)tekst);


        char *struktura = new char[18];
        GetPrivateProfileString("DATY", index, "Brak", struktura, 50, "C:\\DziennikDaty.ini");
        vCzas.push_back(struktura);
    }
}
void f_Zapisz(){
    char ilosc[5];
    itoa(SendMessage(hLista, LB_GETCOUNT, 0, 0), ilosc, 10);
    WritePrivateProfileString("DZIENNIK", "ilosc", ilosc, "C:\\Dziennik.ini");


    for(int i=0; i<SendMessage(hLista, LB_GETCOUNT, 0, 0); i++)
    {
        char index[5];
        itoa(i, index, 10);

        int dlugosc = ListBox_GetTextLen(hLista, i);
        char *tekst = new char[dlugosc+1];
        ListBox_GetText(hLista, i, tekst);

        WritePrivateProfileString("DZIENNIK", index, tekst, "C:\\Dziennik.ini");
        MessageBox(0, vCzas[i], index, MB_OK);
        WritePrivateProfileString("DATY", index, vCzas[i], "C:\\DziennikDaty.ini");

        delete tekst;
    }
}

void DodajStruktureCzasu(){
    char *data;

    time_t czas;
    struct tm * ptr;
    time( & czas );
    ptr = localtime( & czas );

    char roboczy[5];
    string tekst = "";

    int dd;
    int mm;
    int rrrr;
    int godzina;
    int minuta;

    ///dzien

    dd = ptr->tm_mday;
    itoa(dd, roboczy, 10);
    if(dd >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ".";

    ///Miesiac

    mm = ptr->tm_mon+1;
    itoa(mm, roboczy, 10);
    if(mm >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ".";

    ///rok

    rrrr = ptr->tm_year+1900;
    itoa(rrrr, roboczy, 10);
    tekst += roboczy;

    tekst += " - ";

    ///godzina

    godzina = ptr->tm_hour;
    itoa(godzina, roboczy, 10);
    if(godzina >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ":";

    ///minuta

    minuta = ptr->tm_min;
    itoa(minuta, roboczy, 10);
    if(minuta >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }

    data = (char*)tekst.c_str();
    vCzas.push_back(data);
};
void UsunStrukture(int index){
    vCzas.erase(vCzas.begin()+index);
}


int WINAPI WinMain (HINSTANCE hThisInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR lpszArgument,
                     int nCmdShow)
{
    MSG messages;
    WNDCLASSEX wincl;
    hInstance = &hThisInstance;
    { ///KLASA OKNA
    wincl.hInstance = hThisInstance;
    wincl.lpszClassName = szClassName;
    wincl.lpfnWndProc = WindowProcedure;      /* This function is called by windows */
    wincl.style = CS_DBLCLKS;                 /* Catch double-clicks */
    wincl.cbSize = sizeof (WNDCLASSEX);

    /* Use default icon and mouse-pointer */
    wincl.hIcon = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hIconSm = LoadIcon (NULL, IDI_APPLICATION);
    wincl.hCursor = LoadCursor (NULL, IDC_ARROW);
    wincl.lpszMenuName = NULL;                 /* No menu */
    wincl.cbClsExtra = 0;                      /* No extra bytes after the window class */
    wincl.cbWndExtra = 0;                      /* structure or the window instance */
    /* Use Windows's default colour as the background of the window */
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
    }
    if (!RegisterClassEx (&wincl)){
        return 0;}
    InitCommonControls();
    { /// UCHWYTY
            hwnd = CreateWindowEx (0,szClassName,"Baza numerow", WS_SYSMENU | WS_MINIMIZEBOX, CW_USEDEFAULT, CW_USEDEFAULT, 265, 550, HWND_DESKTOP, NULL, hThisInstance, NULL);
            //
            hLista = CreateWindowEx(1, "LISTBOX", "", WS_VISIBLE | WS_CHILD | WS_VSCROLL, 0, 0, 200, 400, hwnd, NULL, hThisInstance, NULL);
            hWpisz = CreateWindowEx(1, "EDIT", "", WS_VISIBLE | WS_CHILD | ES_AUTOHSCROLL, 0, 400, 150, 23, hwnd, NULL, hThisInstance, NULL);
            hDodaj = CreateWindowEx(0, "BUTTON", "Dodaj", WS_VISIBLE | WS_CHILD, 150, 400, 100, 23, hwnd, (HMENU)ID_DODAJ, hThisInstance, NULL);
            hUsun = CreateWindowEx(0, "BUTTON", "Usun", WS_VISIBLE | WS_CHILD, 150, 423, 100, 23, hwnd, (HMENU) ID_USUN, hThisInstance, NULL);
            hKasujStare = CreateWindowEx(0, "BUTTON", "Kasuj Stare Numery", WS_VISIBLE | WS_CHILD, 0, 423, 150, 23, hwnd, NULL, hThisInstance, NULL);
            hInformacje = CreateWindowEx(1, "EDIT", "", WS_VISIBLE | WS_CHILD | ES_MULTILINE | ES_READONLY | WS_BORDER, 2, 447, 255, 70, hwnd, NULL, hThisInstance, NULL);
    }
    { /// Wczytywanie i deklaracje
        f_Wczytaj();
        g_OldWndProc =( WNDPROC ) SetWindowLong( hWpisz, GWL_WNDPROC,( LONG ) ListWndProc );
        SetTimer(hwnd, 1, 500, NULL);

        status.nazwa = "Baza numerow z dziennika.";
    }
    ShowWindow (hwnd, nCmdShow);
    while (GetMessage (&messages, NULL, 0, 0)){
        TranslateMessage(&messages);
        DispatchMessage(&messages);
    }
    return messages.wParam;
}


///===========================================================================

LRESULT CALLBACK WindowProcedure (HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    switch (message)
    {
        case CMSG_TRAY:{
            if( wParam == ID_TRAY )
            if( lParam == WM_LBUTTONDOWN )
                SendMessage(hwnd, WM_SIZE, SIZE_MAXIMIZED, 0);
            break;
        }
        case WM_SIZE:{
            if( wParam == SIZE_MINIMIZED ){
                ShowWindow( hwnd, SW_HIDE );
                status.nid.cbSize = sizeof( NOTIFYICONDATA );
                status.nid.hWnd = hwnd;
                status.nid.uID = ID_TRAY;
                status.nid.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
                status.nid.uCallbackMessage = CMSG_TRAY;
                status.nid.hIcon = LoadIcon( NULL, IDI_APPLICATION );
                lstrcpy( status.nid.szTip, status.nazwa );
                Shell_NotifyIcon( NIM_ADD, & status.nid );
            }
            if( wParam == SIZE_MAXIMIZED ){
                ShowWindow( hwnd, SW_RESTORE );
                status.nid.cbSize = sizeof( NOTIFYICONDATA );
                status.nid.hWnd = hwnd;
                status.nid.uID = ID_TRAY;
                status.nid.uFlags = 0;
                Shell_NotifyIcon( NIM_DELETE, & status.nid );
                // 2
            }
            break;
        }
        case WM_COMMAND:{
            switch(wParam)
            {
                case ID_DODAJ:{
                    char *tekst = new char[50];
                    int dlugosc = GetWindowTextLength(hWpisz);
                    GetWindowText(hWpisz, tekst, dlugosc+1);
                    f_DodajNumer(tekst);
                    delete tekst;
                    break;
                }
                case ID_USUN:{
                    f_UsunNumer();
                    break;
                }
            }
            break;
        }
        case WM_TIMER:{
            int index = SendMessage(hLista, LB_GETCURSEL, 0, 0);
            if(index != -1)
            {
                string tekst = "Data wystawienia: ";
                tekst += vCzas[index];
                SetWindowText(hInformacje, tekst.c_str());
                tekst.clear();
            }
            else
                SetWindowText(hInformacje, "");
            int dlugosc = GetWindowTextLength(hWpisz);
            if(dlugosc == 0){
                break;
            }
            char *tekst = new char[dlugosc+1];
            GetWindowText(hWpisz, tekst, dlugosc+1);
            f_WyszukajFraze(tekst);
            delete tekst;
            break;
        }
        case WM_DESTROY:{
            KillTimer(hwnd, 1);

            if( IsIconic( hwnd ) )
            {
                NOTIFYICONDATA nid;
                nid.cbSize = sizeof( NOTIFYICONDATA );
                nid.hWnd = hwnd;
                nid.uID = ID_TRAY;
                nid.uFlags = 0;
                Shell_NotifyIcon( NIM_DELETE, & nid );
            }

            PostQuitMessage (0);
            break;
        }
        default:
            return DefWindowProc (hwnd, message, wParam, lParam);
    }
    return 0;
}

///===========================================================================

LRESULT CALLBACK ListWndProc( HWND hwnd, UINT mesg, WPARAM wParam, LPARAM lParam )
{
    switch( mesg )
    {
        case WM_KEYDOWN:
        {
            switch(wParam)
            {
                case VK_RETURN:{
                    int dlugosc = GetWindowTextLength(hWpisz);
                    if(dlugosc == 0){
                        SendMessage(hLista, LB_SETCURSEL, -1, 0);
                        break;
                    }
                    char *tekst = new char[dlugosc+1];
                    GetWindowText(hWpisz, tekst, dlugosc+1);
                    f_DodajNumer(tekst);
                    delete tekst;
                    break;
                }
            }
        }
        break;
    }

    return CallWindowProc( g_OldWndProc, hwnd, mesg, wParam, lParam );
}

2

Kod jest mało czytelny. Masz w nim wycieki, MessageBoxy wyświetlają śmieci... to trzeba ogarnąć od początku.

Zamiast rozwiązania, kilka uwag:

vector <char *> vCzas;

To jest coś bardzo, bardzo, bardzo dziwnego. Użyj vector<string>.
I w ogóle pozbądź się tych różnych new i delete. Stos jest ograniczony, ale bez przesady.
Zamiast

char *tekst = new char[50];

Spokojnie możesz

char tekst[50];
struct sSTATUS status;
char szClassName[ ] = "CLASS_DZIENNIK";
HINSTANCE *hInstance;
HWND hwnd;
HWND hLista, hWpisz, hSzukaj, hDodaj, hUsun, hKasujStare, hInformacje;

Bardzo dużo masz tych zmiennych globalnych...

SendMessage(hLista, LB_ADDSTRING, -1, (LPARAM)numer.c_str());
SendMessage(hLista, LB_SETCURSEL, SendMessage(hLista, LB_GETCOUNT, 0, 0)-1, 0);
ListBox_AddString(hLista, numer.c_str());
ListBox_SetCurSel(hLista, ListBox_GetCount(hLista) - 1);
    wincl.hbrBackground = (HBRUSH) COLOR_BACKGROUND;

To co ci się wyświetla to nie jest COLOR_BACKGROUND. Dokumentacja nakazuje dodawać +1 do pożądanej stałej:

    wincl.hbrBackground = (HBRUSH)(COLOR_BACKGROUND+1);
hLista = CreateWindowEx(1, "LISTBOX", "", WS_VISIBLE | WS_CHILD | WS_VSCROLL, 0, 0, 200, 400, hwnd, NULL, hThisInstance, NULL);

Co to za magic value 1 na początku? Co to oznacza? Nie chce mi się szukać która stała ma wartość akurat 1. Dlaczego nie użyjesz stałej?

 g_OldWndProc =( WNDPROC ) SetWindowLong( hWpisz, GWL_WNDPROC,( LONG ) ListWndProc );

Ta funkcja jest deprecated. Należy używać SetWindowLongPtr.

g_OldWndProc = (WNDPROC)SetWindowLongPtr(hWpisz, GWLP_WNDPROC, (LONG_PTR)ListWndProc);
    for(int i=0; i<SendMessage(hLista, LB_GETCOUNT, 0, 0); i++)

W każdej iteracji pętli wywołujesz SendMessage, co jest bardzo złożoną operacją związaną z wywołaniem WndProc kontrolki... wyciągnij to do zmiennej po prostu.

0

Poinformuje, iż znalazłem błąd. Wstawiłem messagebox w tym miejscu:

 
void DodajStruktureCzasu(){
    char *data;
 
    time_t czas;
    struct tm * ptr;
    time( & czas );
    ptr = localtime( & czas );
 
    char roboczy[5];
    string tekst = "";
 
    int dd;
    int mm;
    int rrrr;
    int godzina;
    int minuta;
 
    ///dzien
 
    dd = ptr->tm_mday;
    itoa(dd, roboczy, 10);
    if(dd >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ".";
 
    ///Miesiac
 
    mm = ptr->tm_mon+1;
    itoa(mm, roboczy, 10);
    if(mm >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ".";
 
    ///rok
 
    rrrr = ptr->tm_year+1900;
    itoa(rrrr, roboczy, 10);
    tekst += roboczy;
 
    tekst += " - ";
 
    ///godzina
 
    godzina = ptr->tm_hour;
    itoa(godzina, roboczy, 10);
    if(godzina >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }
    tekst += ":";
 
    ///minuta
 
    minuta = ptr->tm_min;
    itoa(minuta, roboczy, 10);
    if(minuta >= 10)
     tekst += roboczy;
    else
    {
        tekst += "0";
        tekst += roboczy;
    }

    data = (char*)tekst.c_str();

**MessageBox(0, data, "", MB_OK);**

    vCzas.push_back(data);
};

i program sie wysypywał pojęcia nie mam dlaczego (przecież (char*)tekst.c_str(); zwraca wskaźnik do tekstu).
Problem crashu jak i całego problemu rozwiązałem:

 char *data;

zamieniłem na

 char *data = new char[18];
 data = (char*)tekst.c_str();

zamieniłem na

 strcpy(data, (char*)tekst.c_str());

teraz pozostało wyeliminować błędy wskazane przez @Azarien (dziekuje bardzo za pomoc).
mam jeszcze jedno pytanie. Jeżeli wychodze z funkcji lub zamykam program musze dopilnować wyczyszczenia "stringów" ? Bo new wyczyszczę delete, a string samo się usunie czy trzeba mu pomóc string.clear() ?

1

Wyniku metody .c_str() nie powinno się przypisywać do zmiennej, a jedynie używać w wywołaniu jakiejś funkcji która potrzebuje char* a my mamy string:

MessageBox(0, tekst.c_str(), "", MB_OK);

czyli cały czas trzymasz zmienną typu string, a c_str używasz tylko tam gdzie jest już konieczność.

Nie, nie musisz czyścić zmiennych typu string. Same się usuwają.
Dlatego trzeba uważać z tymi c_str, bo zwracany char* jest nadal „przywiązany” do stringa, i jest zwalniany razem ze stringiem.

Takie coś jest na przykład błędem:

string s = "Ala ma kota";
return s.c_str();

bo zmienna s zostaje automatycznie zniszczona, a razem z nią to co zwróciła metoda c_str().

1

Nie korzystaj z plików INI jak z bazy danych, dla małych plików nie ma problemu, jednak problemy z szybkością czytania tych danych zaczynają się już przy większym nadmiarze informacji w plikach INI, lepiej skorzystaj z uniwersalnej bazy danych SQLite - http://www.sqlite.org/

1 użytkowników online, w tym zalogowanych: 0, gości: 1