Wątek(z FileExists) + OpenDialog = błąd

dział ogólny

Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez GoldWolf » niedziela, 14 czerwca 2009, 19:02

Witam, mam taki błąd, iż jak użyję OpenD to sypnie mi się FileExists. Jak nacisnę B2:
Kod: Zaznacz cały
void __fastcall TForm5::Button2Click(TObject *Sender)
{
straznik = 0;
OpenDialog1->InitialDir = "c:\\"; //katalog początkowy
if(OpenDialog1->Execute()){
   if(!OpenDialog1->FileName.IsEmpty()){ //zabezpieczenie przed pustą nazwą
      nazwa_pliku = OpenDialog1->FileName.c_str();//
/*      if (nazwa_pliku.find(".txt") != std::string::npos)
         straznik = 1;*/
   }
}
}
Domyśliłem się, iż chodzi o to, że gdy wskaże plik a.txt, to potem ja chce użyć w wątku FileExists("b.txt") - to on sprawdzi ten warunek dla a.txt. Jak to wyczyścić?

PS chyba ze zmęczenia napisałem brednie, dokładniej sformułowane pytanie.
Ostatnio edytowano poniedziałek, 15 czerwca 2009, 21:09 przez GoldWolf, łącznie edytowano 1 raz
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez banita » niedziela, 14 czerwca 2009, 20:44

nie rozumiem o co tobie chodzili ale podany fragment kodu jest conajmniej lekko niepoprawny.
gdy piszesz:
Kod: Zaznacz cały
if(OpenDialog1->Execute())
{
// ten kod wykona sie tylko gdy wybrano jaki plik. pusta nazwa nie jest tu mozliwa.
}


dalej:
Kod: Zaznacz cały
nazwa_pliku = OpenDialog1->FileName.c_str();
if (nazwa_pliku.find(".txt") != std::string::npos)
straznik = 1;

wystarczy:
Kod: Zaznacz cały
if(ExtractFileExt(OpenDialog1->FileName).AnsiCompareIC("txt") == 0)
Avatar użytkownika
banita
Kreacjusz
Kreacjusz
 
Posty: 283
Dołączył(a): poniedziałek, 28 lipca 2008, 20:07
Podziękował : 1
Otrzymał podziękowań: 18
System operacyjny: Windows 7 Professional
Kompilator: C++Builder 2010 Update 5,
Delphi 2010 Update 5,
NetBeans 6.9(MinGw + Qt),
Visual Studio 2008 + Qt
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Cyfrowy Baron » poniedziałek, 15 czerwca 2009, 15:53

JA też nie do końca to rozumiem.

Kod: Zaznacz cały
nazwa_pliku = OpenDialog1->FileName.c_str();


jakim typem jest zmienna nazwa_pliku, gdyż przypisując jej wartość dokonujesz konwersji na typ char, jeżeli więc nazwa_pliku jest typu char to oczywiście nie można jej tak po prostu przypisać wartości typu AnsiString, trzeba by tutaj posłużyć się np. funkcją sprintf. Jeżeli nazwa_pliku jest typu AnsiString, no to dlaczego przypisując zmiennej typu AnsiString wartość będącą również typem AnsiString (OpenDialog1->FileName <- typ AnsiString), dokonujesz konwersji na typ char?!
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez polymorphism » poniedziałek, 15 czerwca 2009, 16:02

Cyfrowy Baron napisał(a):jakim typem jest zmienna nazwa_pliku [...]

Przecież po warunku if'a widać, że chodzi o std::string'a. Stąd użycie c_str, wszak string nie ma przeładowanego operatora = dla AnsiString'a (w każdym razie nic mi o tym nie wiadomo).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Cyfrowy Baron » poniedziałek, 15 czerwca 2009, 16:06

Tylko jaki sens jest tutaj używać zmiennej typu std::string, pomijając już fakt, że banita podał rozwiązanie, można by się posłużyć typem AnsiString i zamiast:

Kod: Zaznacz cały
if (nazwa_pliku.find(".txt") != std::string::npos)
         straznik = 1;*/


można zrobić tak:

Kod: Zaznacz cały
  if(nazwa_pliku.LastDelimiter(".txt") <= 0)
     straznik = 1;
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez polymorphism » poniedziałek, 15 czerwca 2009, 16:10

Tylko jaki sens jest tutaj używać zmiennej typu std::string

Nie wiem, nie mój kod, nie do mnie to pytanie.
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez GoldWolf » poniedziałek, 15 czerwca 2009, 18:18

Nie o to chodzi o czym mówicie. Button2 działa poprawnie tak jak chcę, może jest to trochę łopatologicznie wykonane, ale działa tak jak chcę.

Chodzi mi o to, iż jeśli w programie użyję tego klawisza wskażę plik o nazwie a.txt to gdy potem chce
Kod: Zaznacz cały
int __fastcall Watek1(Pointer Parameter){
using std::string;
using std::ifstream;

if (FileExists("b.txt")) {
   plik.open("b.txt");
   if (plik.is_open()) {
      getline(plik, klu);
   }else{
      Form5->Label1->Caption = "Błąd odczytu!";
      ExitThread(GetExitCodeThread(Watek1, NULL)); // usunięcie wątku z pamięci,
   }
   plik.close();

ExitThread(GetExitCodeThread(Watek1, NULL)); // usunięcie wątku z pamięci,
            //od tego momentu wątku nie można już wstrzymać.
return 0;
}
To on nie sprawdzi mi FileExists od b.txt, tylko pamięta to a.txt czyli tak jakby sprawdza FileExists("a.txt"). Jak napisałem domyśliłem się, iż chodzi o to iż używam wcześniej OpenDialog i wskazuje plik a.txt, tylko dlaczego przy użyciu FileExists on nie szuka dla b.txt jak mam w kodzie tylko szuka dla a.txt. A co za tym idzie, mój if(dla wątku) się nie wykona. Gdy po uruchomieniu aplikacji użyję tylko wątku to działa poprawnie, ale jak użyję butona2 a potem wątku nie działa(Form5->Label1->Caption = "Błąd odczytu!";).

PS przepraszam za pierwszego posta chyba wyciąłem za dużo podczas edycji i pytanie było bez sensu.
Ostatnio edytowano poniedziałek, 15 czerwca 2009, 18:50 przez GoldWolf, łącznie edytowano 1 raz
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez GoldWolf » poniedziałek, 15 czerwca 2009, 18:35

Cyfrowy Baron napisał(a):Tylko jaki sens jest tutaj używać zmiennej typu std::string, pomijając już fakt, że banita podał rozwiązanie, można by się posłużyć typem AnsiString i zamiast:

Kod: Zaznacz cały
if (nazwa_pliku.find(".txt") != std::string::npos)
         straznik = 1;*/
Robi dokładnie to co chce sprawdza czy został wybrany plik z rozszerzeniem .txt(tylko txt mnie interesuje), nie znałem innych rozwiązań. Trochę ostatnio pracowałem ze stringiem więc wydało mi się to naturalne.

można zrobić tak:

Kod: Zaznacz cały
  if(nazwa_pliku.LastDelimiter(".txt") <= 0)
     straznik = 1;

Postaram się zapamiętać, w książce nie było takiej metody.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez GoldWolf » poniedziałek, 15 czerwca 2009, 18:56

banita napisał(a):nie rozumiem o co tobie chodzili ale podany fragment kodu jest conajmniej lekko niepoprawny.
gdy piszesz:
Kod: Zaznacz cały
if(OpenDialog1->Execute())
{
// ten kod wykona sie tylko gdy wybrano jaki plik. pusta nazwa nie jest tu mozliwa.
}


dalej:
Kod: Zaznacz cały
nazwa_pliku = OpenDialog1->FileName.c_str();
if (nazwa_pliku.find(".txt") != std::string::npos)
straznik = 1;

wystarczy:
Kod: Zaznacz cały
if(ExtractFileExt(OpenDialog1->FileName).AnsiCompareIC("txt") == 0)

Rozwiązanie zaczerpnięte z doctora.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Witold » poniedziałek, 15 czerwca 2009, 19:39

można zrobić tak:

Kod: Zaznacz cały
  if(nazwa_pliku.LastDelimiter(".txt") <= 0)
     straznik = 1;

Postaram się zapamiętać, w książce nie było takiej metody.


Lepiej nie, to nie zadziała poprawnie. LastDelimiter szuka znaku, nie ciągu znaków.
Konstrukcja ExitThread(GetExitCodeThread(Watek1, NULL)); jest też błędna. Zły argument dla GetExitCodeThread. Argumentem dla ExitThread może być GetExitCodeThread ?
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez GoldWolf » poniedziałek, 15 czerwca 2009, 21:12

Witold napisał(a):
można zrobić tak:

Kod: Zaznacz cały
  if(nazwa_pliku.LastDelimiter(".txt") <= 0)
     straznik = 1;

Postaram się zapamiętać, w książce nie było takiej metody.


Lepiej nie, to nie zadziała poprawnie. LastDelimiter szuka znaku, nie ciągu znaków.
Konstrukcja ExitThread(GetExitCodeThread(Watek1, NULL)); jest też błędna. Zły argument dla GetExitCodeThread. Argumentem dla ExitThread może być GetExitCodeThread ?
Dzięki za info jednak nie rozwiązuje to mojego problemu. Ponieważ i wątek i to co jest w guziku nr 2 działa poprawnie ale osobno. Po prostu nie współpracują jak wydawać się powinni.

PS wg artykułu, mam dobre wyjście z wątki.
Tylko dwie rzeczy są nieskończone: wszechświat oraz ludzka głupota, choć nie jestem pewien co do tej pierwszej. - Albert Einstein

Błędów nie popełnia ten, kto nic nie robi. - Theodore Roosevelt
Avatar użytkownika
GoldWolf
Homos antropiczny
Homos antropiczny
 
Posty: 116
Dołączył(a): piątek, 16 stycznia 2009, 18:42
Podziękował : 8
Otrzymał podziękowań: 0
System operacyjny: Siódemka Profesjonalna
Kompilator: Microsoft Visual Studio 2010
Version 10.0.30319.1
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Cyfrowy Baron » poniedziałek, 15 czerwca 2009, 21:34

Lepiej nie, to nie zadziała poprawnie. LastDelimiter szuka znaku, nie ciągu znaków.


To prawda, pomyliłem funkcje, powinno być:

Kod: Zaznacz cały
  if(nazwa_pliku.AnsiPos(".txt") <= 0)
     straznik = 1;
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Witold » poniedziałek, 15 czerwca 2009, 23:23

Dante napisał(a): jednak nie rozwiązuje to mojego problemu. Ponieważ i wątek i to co jest w guziku nr 2 działa poprawnie ale osobno. Po prostu nie współpracują jak wydawać się powinni.

Metoda TForm5::Button2Click(TObject *Sender) i funkcja int __fastcall Watek1(Pointer Parameter) mają u Ciebie tą samą treść jak te wklejone na forum ?
Form5->Label1->Caption = "Błąd odczytu!" pojawia się przy niepowodzeniu if (plik.is_open()) a nie przy if (FileExists("b.txt")) . Testowałeś flagi strumienia?

Dante napisał(a): PS wg artykułu, mam dobre wyjście z wątki.

Tam jest błąd. Mogłeś sobie posprawdzać/zrozumieć co wklejasz do kodu, ale po co ?
Avatar użytkownika
Witold
Konstrukcjonista
Konstrukcjonista
 
Posty: 223
Dołączył(a): piątek, 29 sierpnia 2008, 10:53
Podziękował : 1
Otrzymał podziękowań: 14
Kompilator: bcb6, Turbo C++ Explorer
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez polymorphism » wtorek, 16 czerwca 2009, 09:58

Ponieważ i wątek i to co jest w guziku nr 2 działa poprawnie ale osobno.

Hmm, czyli chodzi ci o to, żeby plik, który wybierzesz w Button2Click był otwarty w wątku, tak?

PS wg artykułu, mam dobre wyjście z wątki.

Nie masz. Po pierwsze, użycie GetExitCodeThread jest zupełnie bez sensu. Sprawdzałeś w ogóle co to za funkcja? Podejrzewam, że nie. Tą funkcję wywołujesz wtedy, gdy chcesz pobrać exit code'a wątku. Jeśli tak, to wywołanie tej funkcji ma sens wtedy, gdy wątek zostanie zakończony, czyli nie wywołujesz jej wewnątrz wątka, od którego chcesz pobrać wartość zwrotną - to chyba logiczne 8-) Po drugie, w C++ użycie ExitThread do wychodzenia z wątków nie jest zbyt bezpieczne (nie będę wnikał dlaczego). Po trzecie, w VCL-u masz klasę TThread, użyj jej zamiast funkcji CreateThread/BeginThread. Po czwarte, nie możesz obwoływać się do obiektów VCL wewnątrz wątków bez synchonizacji (vide TThread::Synchronize). Po szóste, nawet po wywołaniu ExitThread, uchwyt zwrócony przez funkcję tworzącą wątek trzeba zwolnić (w "poradzie" nic na ten temat nie ma).
C++ Reference - opis wszystkich klas STL-a i funkcji C.
Avatar użytkownika
polymorphism
Doświadczony Programista ● Moderator
Doświadczony Programista ● Moderator
 
Posty: 2156
Dołączył(a): piątek, 19 grudnia 2008, 13:04
Podziękował : 0
Otrzymał podziękowań: 200
System operacyjny: Windows 8.1
Windows 10
Linux Mint 21.1
Kompilator: Visual Studio
Visual Studio Code
MSYS2 (MinGW, clang)
g++
clang
Gadu Gadu: 0
    NieznanyNieznana

Re: Wątek(z FileExists) + OpenDialog = błąd

Nowy postprzez Cyfrowy Baron » wtorek, 16 czerwca 2009, 11:25

Porada z której korzystasz jest tak stara, że aż dziw bierze iż ktoś jeszcze z tego korzysta.

Lepiej skorzystać z klasy TThread, o czym było już gdzieś na tym forum, niżej masz prosty przykład użycia tej klasy:

plik nagłówkowy:
Kod: Zaznacz cały
public:      // User declarations
    __fastcall TForm1(TComponent* Owner);
      int p;


plik źródłowy:
Kod: Zaznacz cały
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm1 *Form1;
//---------------------------------------------------------------------------
class myThread : public TThread
{
    TForm1 *tForm;

protected:
    void __fastcall get_p(void);
    void __fastcall Execute(void);

public:

   // __fastcall myThread(TForm1 *Form);
   myThread(TForm1 *_form):TThread(true), tForm(_form){}
};
/*__fastcall myThread::myThread(TForm1 *Form)
  : TThread(Form)
{
tForm = Form;
}  */
//---
void _fastcall myThread::get_p(void)
{
  int czas = tForm->p + tForm->Edit1->Text.ToIntDef(-1);
  tForm->Edit2->Text = czas;
}
void __fastcall myThread::Execute(void)
{
while(1)
{
  Synchronize(get_p);
}
}

myThread* thread;

__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
p = 100;
thread = new myThread(Form1);

}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
thread->Suspend();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
thread->Resume();
}
//---------------------------------------------------------------------------
Avatar użytkownika
Cyfrowy Baron
Administrator
Administrator
 
Posty: 4716
Dołączył(a): niedziela, 13 lipca 2008, 15:17
Podziękował : 12
Otrzymał podziękowań: 442
System operacyjny: Windows 7 x64 SP1
Kompilator: Embarcadero RAD Studio XE2
C++ Builder XE2 Update 4
SKYPE: cyfbar
Gadu Gadu: 0
    NieznanyNieznana

Następna strona

  • Podobne tematy
    Odpowiedzi
    Wyświetlone
    Ostatni post

Powrót do Ogólne problemy z programowaniem

Kto przegląda forum

Użytkownicy przeglądający ten dział: Brak zalogowanych użytkowników i 3 gości

cron