View Full Version : [C++] passare due puntatori a una funzione
Mattyfog
13-08-2008, 17:30
ciao a tutti,
scusate ma non sapevo della regola di scrivere tra [] il linguaggio!!! sono nuovo!!!
comunque vorrei riprendere la discussione iniziata qua: http://www.hwupgrade.it/forum/showthread.php?t=1798829
ciao
ps: rispondetemi presto!!!
sottovento
13-08-2008, 17:36
Dagli errori riportati non sembra che abbia fatto come suggerito, anche se giuri... non e' per caso che la funzione copyfile() e' in un altro file, ed hai cambiato solo il .cpp ma non il .h?
Inoltre immagino che in libreria ci sia gia' una funzione con questo nome. Prova a dargli un altro nome (per esempio, copia_file()) e riprova...
Mattyfog
13-08-2008, 18:04
grazie,
forse il problema era dovuto all'esistenza di quella funzione in una libreria...
ora tui sarei grato semi aiutassi ancora una volta!!!:) :) :)
funzione usata per richiamare la funzione:
copydir("E:\\Php", buf);
funzione:
void copydir(char *percorso[MAX_PATH], char *percorso2[MAX_PATH])
{
char tpercorso2[MAX_PATH];
strcat(tpercorso2, "E:\\Documents and Settings\\Matteo\\Immagini\\");
strcat(tpercorso2, percorso2);
strcpy(percorso2, tpercorso2);
listadir.push_back(percorso2);
search(percorso, percorso2);
//cout<<endl<<endl<<endl;
crearedir(percorso2);
copyallfile();
//system("pause");
}
c'è un problema nel passare i dati alla copy dir e nell'"elaborazione" della variabile con il percorso.
Devono essere tutti legati alle conversioni da char a const char o altre...
ciao
sottovento
13-08-2008, 21:47
void copydir(char *percorso[MAX_PATH], char *percorso2[MAX_PATH])
Ad una prima occhiata al codice, sembri interessato a passare due stringhe a questa funzione, pertanto l'intestazione sopra riportata non e' corretta (la si potrebbe interpretare come "vettori di stringhe" mentre vuoi due stringhe solamente).
Prova con
void copydir(char *percorso, char *percorso2)
Mattyfog
14-08-2008, 10:42
ciao,
siamo alla fine: la libreria è conclusa e funziona, solo che provandola da un file main.cpp quando il programma finisce dopo il system("pause") viene fuori il tipico messaggio windows:
Si è verificato un errore in Progetto1.exe. L'applicazione verrà chiusa.
main.cpp
#include <iostream.h>
#include "copymydir.h"
int main()
{
char name[] = ("prova");
copymydir("E:\\Php", name);
system("pause");
}
copymydir.h
//#include "stdafx.h"
#include <windows.h>
#include <iostream>
#include <stdio.h>
#include <vector>
#include <string>
#include <direct.h>
#include <fstream>
#include "copymyfile.h"
using namespace std;
vector<string> listaofile;
vector<string> listadfile;
vector<string> listadir;
void search(char *p, char *p2)
{
WIN32_FIND_DATA fd;
char tlist[MAX_PATH];
char pf[MAX_PATH];
strcpy(pf, p);
strcat(pf, "\\*.*");
HANDLE h = FindFirstFile(pf, &fd);
if (h != INVALID_HANDLE_VALUE)
{
do
{
if( strcmp(fd.cFileName, ".") && strcmp(fd.cFileName, ".."))
{
if(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
//printf ("[%s]\n", fd.cFileName);
//per continuare la ricerca:
char pf[MAX_PATH];
strcpy(pf, p);
strcat(pf, "\\");
strcat(pf, fd.cFileName);
//per generare la lista
strcpy(tlist, p2);
strcat(tlist, "\\");
strcat(tlist, fd.cFileName);
listadir.push_back(tlist);
search(pf, tlist);
}
else
{
//printf ("\t%s\n", fd.cFileName);
//lista origine file
strcpy(tlist, p);
strcat(tlist, "\\");
strcat(tlist, fd.cFileName);
listaofile.push_back(tlist);
//lista destinazione file
char tdlist[MAX_PATH];
strcpy(tdlist, p2);
strcat(tdlist, "\\");
strcat(tdlist, fd.cFileName);
listadfile.push_back(tdlist);
}
}
} while (FindNextFile(h, &fd));
FindClose(h);
}
else
printf("Errore %d\n", GetLastError ());
}
void crearedir(char *d){
//e tutte le altre...
vector<string>::iterator a = listadir.begin();
while(a != listadir.end())
{
cout<<*a<<endl;
mkdir(a->c_str());
a++;
}
cout<<"Cartelle create.\n";
}
void copyallfile()
{
vector<string>::iterator a = listaofile.begin();
vector<string>::iterator b = listadfile.begin();
while(a != listaofile.end())
{
cout<<"Origine "<<*a<<endl;
cout<<" Destinazione "<<*b<<endl;
copymyfile((*a).c_str(), (*b).c_str());
a++; b++;
}
}
void copymydir(char *percorso, char *percorso2)
{
char tpercorso2[MAX_PATH];
strcat(tpercorso2, "E:\\Documents and Settings\\Matteo\\Documenti\\Immagini\\");
strcat(tpercorso2, percorso2);
strcpy(percorso2, tpercorso2);
listadir.push_back(percorso2);
search(percorso, percorso2);
cout<<endl<<endl<<endl;
crearedir(percorso2);
copyallfile();
}
copymyfile.h
#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
using namespace std;
void copymyfile(const char *origine, const char *destinazione)
{
char sfile;
ifstream in(origine, ios::in | ios::binary);
if(!in)
{
cout<<"Impossibile aprire il file di origine!!!";
}
ofstream out(destinazione, ios::out | ios::binary);
if(!out)
{
cout<<"Impossibile aprire il file di destinazione!!!";
}
while(!in.eof())
{
in.get(sfile);
out.put(sfile);
}
in.close();
out.close();
}
ciao ciao
ti sarò e sono molto grato...
sottovento
14-08-2008, 11:09
Prova a sostituire:
char name[] = ("prova");
con
char *name = "prova";
e posta il risultato...
sottovento
14-08-2008, 11:13
En passant, ne ho vista un'altra:
void copymydir(char *percorso, char *percorso2)
{
char tpercorso2[MAX_PATH];
strcat(tpercorso2, "E:\\Documents and Settings\\Matteo\\Documenti\\Immagini\\");
strcat(tpercorso2, percorso2);
Beh, almeno la prima deve essere una strcpy(), cosa ne dici? Qualcosa del tipo:
void copymydir(char *percorso, char *percorso2)
{
char tpercorso2[MAX_PATH];
strcpy(tpercorso2, "E:\\Documents and Settings\\Matteo\\Documenti\\Immagini\\");
strcat(tpercorso2, percorso2);
Mattyfog
14-08-2008, 11:21
dunque con la prima sostituzione l'errore arriva all'apertura del programma, con la seconda come sempre alla fine...
che femo???
sottovento
14-08-2008, 11:31
Il codice che hai pubblicato e' lunghino e non e' facile individuare ad occhio il problema. Occorre fare un po' di debugging. Cmq le modifiche che ti ho suggerito dovrebbero essere corrette, per cui ti consiglio di tenerle.
Hai parlato di errore: e' qualcosa del tipo "L'istruzione a 0x004018b8 ha fatto accesso alla memoria 0x0000000c. La memoria non poteva essere "written"" o simile?
Se fosse cosi', sarebbe interessante sapere cosa scrive esattamente ed i numeri che sono scritti in quel dialogo. Inoltre servirebbe vedere il .map che e' stato generato dal linker (usi Visual C?)
Nel caso fosse qualche altro errore, servono piu' dettagli altrimenti si brancola nel buio....
Se e' Visual, potresti postare l'intero progetto? Si fa prima... (beh, io ho una versione molto vecchia, speriamo di farcela)
sottovento
14-08-2008, 11:41
Intanto ne ho vista un'altra: per inciso, questo significa che le modifiche che ti ho suggerito sembrano andar bene.
void copymydir(char *percorso, char *percorso2)
{
char tpercorso2[MAX_PATH];
strcat(tpercorso2, "E:\\Documents and Settings\\Matteo\\Documenti\\Immagini\\");
strcat(tpercorso2, percorso2);
strcpy(percorso2, tpercorso2);
listadir.push_back(percorso2);
search(percorso, percorso2);
cout<<endl<<endl<<endl;
crearedir(percorso2);
copyallfile();
}
Guarda l'istruzione in neretto: dopo aver attaccato il path, copi il risultato sulla variabile di ingresso, quella che originariamente valeva "prova".
Siccome il compilatore ti ha riservato solo 6 byte per quella variabile (cioe' sufficiente a contenere la parola "prova" + il carattere di terminazione della stringa), non c'e' spazio sufficiente per tutta la nuova stringa.
Vai quindi a sovrascrivere qualcos'altro (qualcosa che non doveva essere sovrascritto) dunque il programma termina con un errore.
Soluzioni:
1 - prima di tutto, valutare se ti serve davvero copiare indietro la stringa, poiche' ad una prima analisi potresti benissimo usare tpercorso2;
2 - Chiedere al compilatore di allocare piu' spazio per detta stringa. Comunque ricordati che le operazioni che hai usato, quali strcpy() e strcat() non possono controllare se c'e' spazio sufficiente per copiare quanto serve. Copiano e basta, e se non c'e' spazio puo' succedere di tutto (la fortuna e' andare immediatamente in crash, cosi' da trovarlo).
In questo secondo caso, per esempio potresti sostituire nel tuo main l'istruzione
char *name = "prova";
con
char name[MAX_PATH];
strcpy (name, "prova");
Mattyfog
14-08-2008, 12:40
evvai!!!!
6 un grande!!!
dovevo scrivere quel max path!!!
grazie!
se ho ancora problemi faccio sapere
Mattyfog
14-08-2008, 12:52
bene, il programma che volevo creare funziona alla perfezione!!! solo un'ultima cosa fastidiosa:
quando si apre viene visualizzata dietro la finestra principale (che viene creata dal file di risorse e che quindi ha un interfaccia, diciamola così!!!) la tipica finestra della console... siccome non mi era mai successo volevo sapere come posso toglierla (non renderla visibile).
ciao
sottovento
14-08-2008, 13:04
bene, il programma che volevo creare funziona alla perfezione!!! solo un'ultima cosa fastidiosa:
quando si apre viene visualizzata dietro la finestra principale (che viene creata dal file di risorse e che quindi ha un interfaccia, diciamola così!!!) la tipica finestra della console... siccome non mi era mai successo volevo sapere come posso toglierla (non renderla visibile).
ciao
Penso di non aver capito. Da quel poco che ho capito, dipende dal progetto che hai creato, perche' se crei un normale progetto "Win32 console" non ci sono altre finestre, risorse o quant'altro...
Mattyfog
14-08-2008, 13:07
ciao,
io uso dev-c++ ... comunque ho creato un progetto vuoto ma sto lavorando con le API in modo che il mio programma abbia un'interfaccia grafica e non si apra più con la console (il prompt dei comandi o cmd.exe)... tutto funziona a parte il fatto che si apre comunque la console!!!
in pratica mi ritrovo con due finestre: quella da me creata con le api e la finestra console vuota.
Quindi non sai che dirmi???
sottovento
14-08-2008, 13:20
ciao,
io uso dev-c++ ... comunque ho creato un progetto vuoto ma sto lavorando con le API in modo che il mio programma abbia un'interfaccia grafica e non si apra più con la console (il prompt dei comandi o cmd.exe)... tutto funziona a parte il fatto che si apre comunque la console!!!
in pratica mi ritrovo con due finestre: quella da me creata con le api e la finestra console vuota.
Quindi non sai che dirmi???
Non ho mai visto dev-c++. Posso immaginare che quando crei un progetto devi selezionare quale tipo vuoi: console, win32,....
Probabilmente hai creato il progetto console, salvo aprire poi le tue finestre di grafica.
Hai gia' provato a creare qualche altro tipo di progetto?
Magari qualcuno piu' esperto ti puo' aiutare...
DanieleC88
14-08-2008, 13:25
ciao,
io uso dev-c++
Ti consiglio di provare Code::Blocks invece di Dev-C++, è un'IDE sicuramente più maturo e completo (oltre che ancora vivo :D).
Per il fatto delle "due finestre" c'è da dire che se hai creato un progetto per console e poi hai creato le finestre solo in seguito usando le API Win32, il tuo progetto sarà sempre un'applicazione per console. Fai prima a creare un nuovo progetto riutilizzando il codice scritto finora.
DanieleC88
14-08-2008, 13:26
Non ho mai visto dev-c++. Posso immaginare che quando crei un progetto devi selezionare quale tipo vuoi: console, win32,....
Azz mi hai preceduto! :D
Comunque sì, è esatto quel che hai detto, è semplicemente che veniva compilato un target diverso da quello che gli interessava. ;)
Mattyfog
14-08-2008, 14:09
già meglio code::blocks...
comunque il problema non è stato risolto... piuttosto cè una roba molto strana: il programma deve semplicemente copiare da una cartella predefinita tutti i file in una cartella scelta dall'utente. L'utente infatti deve solo inserire un nome come ad esempio montagna2008 perchè tutti i file vengano copiati dentro Documenti\Immagini\montagna2008. Ora il programma funziona a volte si a volte no. Infatti dopo aver copiato le immagini a volte si chiude.
Il codice è qui allegato se potete aiutarmi...
grazie
ps: la finestra era colpa mia che scemo!!! avevo avviato in modalità debug e quindi... ciao!!!
sottovento
14-08-2008, 14:31
Prima di tutto, risolvi i blind trust (i.e. "fede cieca"): e' un anti-pattern molto comune che consiste nel credere sempre che quello che si fa vada a buon fine.
Per esempio, nel tuo codice:
void copymyfile(const char *origine, const char *destinazione)
{
char sfile;
ifstream in(origine, ios::in | ios::binary);
if(!in)
{
//cout<<"Impossibile aprire il file di origine!!!";
}
ofstream out(destinazione, ios::out | ios::binary);
if(!out)
{
//cout<<"Impossibile aprire il file di destinazione!!!";
}
while(!in.eof())
{
in.get(sfile);
out.put(sfile);
}
in.close();
out.close();
}
E' chiaro che se non riesci ad aprire i file per qualsiasi motivo,
1 - non lo saprai mai;
2 - l'applicazione andra' in crash;
Dovresti risolvere prima queste cose, anche se non ti risolvono il problema specifico.
Dopo di che, avrai piu' probabilita' di avere dei crash "regolari", cioe' che avvengono sempre quando si verifica una determinata condizione (cioe' una condizione che si puo' capire). Se riesci ad ottenere dei crash cosi', e' sicuramente piu' facile risolverli.
Suggerimento: per quanto riguarda l'esempio sopra riportato, potresti modificare facendo riportare un codice di errore alla funzione, per esempio:
bool copymyfile (......);
potresti far ritornare true se tutto ok, false in caso di errori,...
Penso ci siano altri casi come questi nel tuo codice. Inoltre dovresti controllare quanto diventano lunghe le tue stringhe.
Una volta che hai fatto queste cose, se vuoi, potresti postare il nuovo codice
Mattyfog
14-08-2008, 14:50
ciao,
ho provato ad inserire alcuni cout cosicchè in modalità debug potessi osservare cosa succedesse.
Ho così scoperto che, i file vengono ciopiati senza alcun errore e l'operazione finisce bene. Semplicemente però dopo che l'operazione viene eseguita il programma va in tilt, vale a dire che appena ci si clicca sopra col mouse (oppure viene "modificato" con una messagebox) parte l'errore. E' come se non fosse più capace di rispondere.
#include <windows.h>
#include "copymydir.h"
#include "resource.h"
BOOL CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_COMMAND:
switch(LOWORD(wParam))
{
case ID_EXIT:
PostQuitMessage(0);
break;
case ID_COPY:
int len = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT1));
if(len < 0)
{
cout<<"Non è stato inserito alcun nome.";
}
if(len > 0)
{
//int i;
char* buf;
cout<<"iniziato.";
buf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hWnd, IDC_EDIT1, buf, len + 1);
//... fa qualcosa con il testo ...
cout<<"iniziato.";
copymydir("E:\\Php", buf);
GlobalFree((HANDLE)buf);
}
//MessageBox(NULL, "Copia effettuata!", "Finito", MB_OK);
cout<<"Copia effettuata.\n";
break;
}
break;
case WM_CLOSE:
cout<<"E' stato deciso di chiudere l'applicazione.\n";
DestroyWindow(hWnd);
break;
case WM_DESTROY:
cout<<"L'applicazione sta per essere chiusa.\n";
PostQuitMessage(0);
break;
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
//Creo la form dalle risorse.
HWND hWnd = CreateDialogParam(hInstance, MAKEINTRESOURCE(IDD_DIALOG1), NULL, WndProc, NULL);
ShowWindow(hWnd, SW_SHOWNORMAL);
UpdateWindow(hWnd);
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
Mattyfog
14-08-2008, 14:52
ps: non è che all'interno di WM_COMMAND bisogna inserire un'opzione di default??? solo che non saprei come metterla...
sottovento
14-08-2008, 15:00
Mi sembra che sia stato reintrodotto lo stesso problema di prima:
case ID_COPY:
int len = GetWindowTextLength(GetDlgItem(hWnd, IDC_EDIT1));
if(len < 0)
{
cout<<"Non è stato inserito alcun nome.";
}
if(len > 0)
{
//int i;
char* buf;
cout<<"iniziato.";
buf = (char*)GlobalAlloc(GPTR, len + 1);
GetDlgItemText(hWnd, IDC_EDIT1, buf, len + 1);
//... fa qualcosa con il testo ...
cout<<"iniziato.";
copymydir("E:\\Php", buf);
GlobalFree((HANDLE)buf);
}
buf viene ancora allocato della dimensione giusta giusta per contenere la stringa iniziale + terminatore. Dopo di che la copymydir() va ad aggiungerci il percorso e tutto il resto, per cui siamo ancora allo stesso problema di prima.
La soluzione e' ovviamente la medesima: dichiara bug[MAX_PATH] oppure se vuoi usare la GlobalAlloc, alloca almeno MAX_PATH bytes.
Attenzione che qui ci trovi un altro caso di blind trust o, se preferisci, fede cieca: infatti credi ciecamente che GlobalAlloc() non fallira'. Non e' un buon stile di programmazione, controlla sempre l'esito delle funzioni che allocano memoria.
Mattyfog
14-08-2008, 18:08
Grazie ora funziona tutto alla perfezione. Dunque nella mia ignoranza chiedo solo come si fa a verificare se la globalalloc ha avuto esito positivo???
Grazie ora funziona tutto alla perfezione. Dunque nella mia ignoranza chiedo solo come si fa a verificare se la globalalloc ha avuto esito positivo???
la sparo, restituisce NULL?
Mattyfog
14-08-2008, 19:34
e come va scritto???
if(variabile != NULL)
{
//fai le tue cose
}
Mattyfog
14-08-2008, 20:41
ok...
sentite già che ci sono se io richiamo una funzione così:
copymydir("Z:\\SD Drive", buf, result);
come faccio a fare in modo che se c'è un errore result diventi TRUE???
cioè è una variabile BOOL e in caso di errore ho scritto questo:
result = TRUE;
solo che in caso di errore resta sempre false. Forse perchè viene modificata in un altra funzione... comunque come faccio???
DanieleC88
14-08-2008, 20:55
Devi pensare che le variabili locali esistono tutte in memoria, ma appartengono a diversi "spazi": se le hai dichiarate in una funzione, non puoi accedervi direttamente.
In C++ le variabili vengono passate sullo stack alle funzioni chiamate e sono una copia di quelle originali: in pratica, all'interno delle funzioni richiamate, lavori sulle copie. A questo punto puoi decidere di usare un puntatore e lavorare direttamente sull'area di memoria che contiene la variabile, oppure dire al compilatore di passare la variabile per riferimento:
int miaFunzione(int copia1, int copia2, int &riferimento);
A questo punto, le modifiche fatte all'interno di miaFunzione() si propagheranno anche sulla variabile originale.
Mattyfog
15-08-2008, 09:51
grazie siete veramente bravissimi... lo so che è da un po' che dico che è l'ultima domanda comunque... non ho capito come mai questo (SEMPLICISSIMO) codice non incrementa pos:
ifstream in("options.config", ios::in | ios::binary);
if(!in)
{
MessageBox(NULL, "Impossibile trovare il file di configurazione\noptions.config", "Errore", MB_OK|MB_ICONEXCLAMATION);
}
char porigine[500];
int pos;
for(pos=0; porigine[pos]!='>'; pos++)
{
if(pos=0)
{in.ignore(1);}
in.get(porigine[pos]);
cout<<pos<<endl;
}
in.close();
ciaio
nel ciclo stai facendo un assegnamento non un confronto.. pos == 0 non pos = 0..
Mattyfog
15-08-2008, 10:16
già che scemo!!!
resta il fatto che il contenuto del file da aprire è:
<E:\Php>
e che il programma non lo legge correttamente e va avanti fino a 250 (circa) caratteri.
sottovento
15-08-2008, 10:23
char porigine[500];
int pos;
for(pos=0; porigine[pos]!='>'; pos++)
{
if(pos=0)
{in.ignore(1);}
in.get(porigine[pos]);
cout<<pos<<endl;
}
in.close();
Ciao,
il ciclo for va a testare porigine[pos] per vedere se e' diverso da '>', ma in porigine, nel momento che fai quel test, non hai ancora scritto nulla.
Siccome non scrivi nulla, il contenuto e' indeterminato. Intorno alla posizione 250 c'e' casualmente scritto un '>' pertanto il ciclo termina.
Ti consiglio di rivedere questo ciclo
Mattyfog
17-08-2008, 16:40
cavolo...
continuo ad avere errori nei punti in cui meno me lo aspetto...
char porigine[500];
int pos = 0;
while(porigine[pos]!='>')
{
if(pos==0)
{in.ignore(1);}
if(in.peek()=='>')
{break;}
in.get(porigine[pos]);
cout<<porigine[pos]<<endl;
pos++;
}
in.close();
copymydir(porigine, buf, result);
questo legge correttamente il file e poi dovrebbe passare il percorso(variabile porigine) alla copymydir. Il compilatore non da errore ma probabilmente avviene qualcosa di sbagliato perchè copymydir restituisce un errore.
Mattyfog
17-08-2008, 17:03
niente risolto
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.