Torna indietro   Hardware Upgrade Forum > Software > Programmazione

Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa
Marvel's Wolverine porta Logan in un'avventura inedita, violenta e fortemente narrativa, costruita attorno alla sua natura di combattente e al difficile rapporto con il proprio passato. Insomniac Games punta su combattimenti spettacolari, progressione e personalizzazione, inserendo l'azione in un mondo segnato dalla persecuzione dei mutanti. Un viaggio intenso, che alterna mattanza, esplorazione e momenti sorprendentemente emotivi.
DJI Romo 2: tante novità lo rendono un robot completo
DJI Romo 2: tante novità lo rendono un robot completo
Romo 2 è la seconda generazione di robot lavapavimenti di DJI, un modello che si caratterizza per la precisione nel sistema di navigazione e per il funzionamento particolarmente silenzioso. Con le modifiche introdotte in questa seconda versione, e un posizionamento di prezzo più allineato alla concorrenza, rappresenta una valida alternativa sul mercato delle soluzioni di pulizia domestica
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED
Il primo Sony con retroilluminazione True RGB alla prova del banco di misura e dei contenuti: luminanza enorme, colori accurati in HDR e un antiriflesso molto efficace. I limiti sono due sole HDMI 2.1 e il blooming fuori asse
Tutti gli articoli Tutte le news

Vai al Forum
Rispondi
 
Strumenti
Old 21-05-2004, 22:21   #1
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
[newbie] problema "liste" con il C.

salve a tutti! Sono un totale principiante che sta cercando di imparare il C per esigenze scolastiche.. ho un problema nella gestione delle liste dinamiche.

Ho definito una struttura in questo modo:

struct elem {
char Titolo[20];
char Autori[20];
struct elem *link_t;
struct elem *link_a;
};

il problema è che inizializzando un puntatore in questo modo *t2 = NULL si verifica questa situazione:

t2->Titolo = NULL
t2->Autori= ""

così quando dopo controllo se t2 != NULL la risposta è positiva. Come posso fare??

grazie per l'aiuto!!

allego il file sorgente completo e la finestra con l'errore

p.s. il programmino dovrebbe collocare la struttura creata in ordine alfabetico rispetto alle altre...

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

struct elem {
char Titolo[20];
char Autori[20];
struct elem *link_t;
struct elem *link_a;
};

void ordina_autori (struct elem *aux, struct elem **testa ) {
struct elem *t1 = NULL, *t2 = NULL;

t1 = t2 = *testa; //Collega la struttura in base agli autori

while (t2->Autori && strcmp(aux->Autori, t2->Autori) > 0 ) {
t1 = t2;
t2 = t1->link_a;
}

if (t1 == t2) {
aux->link_a = *testa;
*testa = aux;
}
else {
t1->link_a = aux;
aux->link_a = t2;
}
}
main () {
struct elem *testa_a = NULL, *testa_t = NULL, *nuova_t = NULL, *nuova_a = NULL;
char istruzione[40];
int i;

printf("\nInserire una scheda (EOF per finire) => ");
for (i=0; i<5; i++) {
gets(istruzione);
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
sscanf(istruzione, "%s %s", nuova_t->Titolo, nuova_t->Autori);

ordina_autori (nuova_a, &testa_a);

printf("Inserire un altra scheda (EOF per finire) => ");
}

return 0;
}
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 21-05-2004, 22:23   #2
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
errore
Immagini allegate
File Type: jpg telist_error.jpg (24.0 KB, 20 visite)
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 21-05-2004, 22:46   #3
Ziosilvio
Moderatore
 
L'Avatar di Ziosilvio
 
Iscritto dal: Nov 2003
Messaggi: 16215
Ciao.
Solo qualche nota qua e là, non ho letto il codice a fondo.

Se esegui:
Codice:
*t2=NULL;
non inizializzi a NULL t2, ma la variabile il cui indirizzo è il valore di t2; e che, di solito, non è NULL.

Il codice:
Codice:
t2->Titolo=NULL;
t2->Autori="";
contiene almeno due errori.
Anzitutto, Titolo e Autori sono array e non puntatori, quindi non puoi inizializzarli, né a NULL, né a nessun altro valore.
Inoltre, se pure Autori fosse un puntatore, la riga non lo inizializzerebbe a NULL, ma lo farebbe puntare all'inizio di una stringa vuota (che non è NULL, ma una stringa che contiene il solo null character).

Inoltre, attenzione: quando esegui:
Codice:
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
nuova_t e nuova_a puntano tutti e due allo stesso oggetto, e non ciascuno a una copia diversa dello stesso oggetto: sei sicuro di volere questo?
__________________
Ubuntu è un'antica parola africana che significa "non so configurare Debian" Chi scherza col fuoco si brucia.
Scienza e tecnica: Matematica - Fisica - Chimica - Informatica - Software scientifico - Consulti medici
REGOLAMENTO DarthMaul = Asus FX505 Ryzen 7 3700U 8GB GeForce GTX 1650 Win10 + Ubuntu
Ziosilvio è offline   Rispondi citando il messaggio o parte di esso
Old 21-05-2004, 23:05   #4
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
innanzitutto grazie per l'aiuto

Quote:
Originariamente inviato da Ziosilvio
Il codice:
Codice:
t2->Titolo=NULL;
t2->Autori="";
contiene almeno due errori...
ops mi sono spiegato male io!! questo è quello che vedo nel watch, non quello che ho scritto nel file sorgente

Quote:
Inoltre, attenzione: quando esegui:
Codice:
nuova_t = nuova_a = (struct elem *) malloc (sizeof(struct elem));
nuova_t e nuova_a puntano tutti e due allo stesso oggetto, e non ciascuno a una copia diversa dello stesso oggetto: sei sicuro di volere questo?
si è proprio così perchè alla fine devo ottenere due concatenazioni di puntatori: una per il campo titolo e una per autori.

Cmq ho focalizzato il problema che mi blocca tutto: non riesco a trovare un controllo che mi ritorni NULL quando t2->Autori punta ad una stringa vuota!!
Ho provato con (t2->Autori[0] != '\0') e (strlen(t2->Autori)) ma in entrambi i casi il programma si blocca...
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 23-05-2004, 12:56   #5
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
Processor Fault

sto incontrando altri problemi con il compilatore Tc++ 4.5
Allego un programmino elementare che però non gira!!

se inizializzo un vettore di strutture di 3 elementi tutto ok, se gli elementi sono già 10 si pianta

sembrerebbero problemi di memoria...

sapreste dirmi come evitarli??

grazie
Immagini allegate
File Type: jpg processor_fault.jpg (24.3 KB, 11 visite)
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 23-05-2004, 13:23   #6
anx721
Senior Member
 
L'Avatar di anx721
 
Iscritto dal: Oct 2002
Città: Roma
Messaggi: 1502
Nel primo for l'indice i lo fai andare da 1 a N_LIBRI il che è errato, in quanto gli array sono indicizzati a partire da zero, quindi i deve variare da zero fino a N_LIBRI - 1, come fai nel secondo for.

Ciao.
__________________
Sun Certified Java Programmer
EUCIP Core Level Certified

European Certification of Informatics Professionals
anx721 è offline   Rispondi citando il messaggio o parte di esso
Old 23-05-2004, 15:14   #7
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
ops è vero...

cmq mettendo a posto quello il problema rimane!



poi un'altra cosa... nei file exe generati da Tc pp101 (avrà 10 anni) cliccando con il destro su proprietà posso impostare il quantitativo di memoria da riservagli (è su auto e va bene infatti...).

Al contrario con gli eseguibili generati da Tc++4.5 per win cliccando su proprietà appaiono solo 3 "linguetti" e posso solo cambiare autore, note etc.. niente riguardo la memoria!!!

il risultato finale è che i file compilati dal primo funzionano sempre, quelli compilati dal secondo funzionano solo se il numero di variabili è ridotto.
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 23-05-2004, 19:09   #8
anx721
Senior Member
 
L'Avatar di anx721
 
Iscritto dal: Oct 2002
Città: Roma
Messaggi: 1502
Ma perkè non cambi compilatore? Non l'ho mai sentito questo...
__________________
Sun Certified Java Programmer
EUCIP Core Level Certified

European Certification of Informatics Professionals
anx721 è offline   Rispondi citando il messaggio o parte di esso
Old 23-05-2004, 23:16   #9
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
boh a scuola è quello che va per la maggiore, pensavo fosse abbastanza conosciuto! Il nome completo è "Borland Turbo C++ 4.5 for win".

Cmq alla fine sono riusciuto a risolvere tutti i problemi, è bastato dichiarare il vettore di strutture come *record e allocargli la memoria necessaria solo in un secondo momento con la malloc!!

Ora il prog è Rock Solid
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 24-05-2004, 23:12   #10
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
rieccomi qui con il quesito del giorno... cosa c'è che non va in

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL) {
printf("Memoria insufficiente, impossibile inserire nuovo record.\n");
return -1;
}

qui il programma si pianta

(Libro è una struttura rinominata con typedef)
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 24-05-2004, 23:59   #11
Ziosilvio
Moderatore
 
L'Avatar di Ziosilvio
 
Iscritto dal: Nov 2003
Messaggi: 16215
Quote:
Originariamente inviato da Diabolik.cub
rieccomi qui con il quesito del giorno... cosa c'è che non va in

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL) {
printf("Memoria insufficiente, impossibile inserire nuovo record.\n");
return -1;
}

qui il programma si pianta

(Libro è una struttura rinominata con typedef)
Attenzionissima alle precedenze degli operatori!
L'espressione:
Codice:
 aux = (Libro *) malloc (sizeof(Libro)) == NULL
non corrisponde a:
Codice:
 (aux=(Libro*)malloc(sizeof(Libro))) == NULL
ma a:
Codice:
aux = ((Libro*)malloc(sizeof(Libro))==NULL)
Tutte queste espressioni sono vere se e solo se l'allocazione di memoria per un nuovo oggetto di tipo Libro riesce; ma mentre la seconda assegna ad aux l'indirizzo della nuova struttura allocata oppure NULL, l'ultima (o la prima, tanto sono equivalenti) gli assegna o il valore 0 o il valore 1.
Siccome aux è un puntatore, qualunque cosa cerchi in seguito di usare il suo valore si ritrova o alla locazione zero, che non è utilizzabile, o alla locazione 1, che è occupata dal sistema (sei sotto DOS, se ho capito bene): un'operazione di scrittura su una di queste zone provoca un errore.

[Modalità "io ciò Linux " ON]
Solo che Linux ti fa uscire con un messaggio di errore, Microzozz si impianta.
[Modalità "io ciò Linux " OFF]

Prova a correggere questa riga, e facci sapere che succede.
__________________
Ubuntu è un'antica parola africana che significa "non so configurare Debian" Chi scherza col fuoco si brucia.
Scienza e tecnica: Matematica - Fisica - Chimica - Informatica - Software scientifico - Consulti medici
REGOLAMENTO DarthMaul = Asus FX505 Ryzen 7 3700U 8GB GeForce GTX 1650 Win10 + Ubuntu
Ziosilvio è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 00:07   #12
anx721
Senior Member
 
L'Avatar di anx721
 
Iscritto dal: Oct 2002
Città: Roma
Messaggi: 1502
Purtroppo la sintassi del c ti permette di scrivere un sacco di cose, ma è anche piena di trappole e se non la si conosce a fondo si possono combinare dei casini, sopratutto se il programma non va in crash come nel tuo caso, per cui ti accorgi subito che c'è un bug.

Nel caso specifico almeno un errore è nella riga:

if (aux = (Libro *) malloc (sizeof(Libro)) == NULL)

perkè quello che tu vuoi fare è assegnare a aux l'indirizzo restituito dalla malloc e poi vedere se tale indirizzo è NULL, però, in virtù della precedenza degli operatori, viene eseguito prima il controllo sull'uguaglianza a NULL e poi l'assegnamento; se tu scrivi:

int ok = 1 == 0;

viene prima eseguito 1 == 0 producendo il risultato booleano che viene quindi assegnato alla variabile ok; analogamente con

aux = (Libro *) malloc (sizeof(Libro)) == NULL

viene eseguito prima

(Libro *) malloc (sizeof(Libro)) == NULL

che restituisce zero se l'indirizzo restituito dalla malloc non è NULL (come accade quasi sempre), o uno viceversa, e quindi assegni a aux rispettivamente zero o uno, ovvero hai un puntatore che punta a zero (NULL) o alla locazione 1, causando quindi il crash.

Prova allora a mettere le parentesi

if ((aux = (Libro *) malloc (sizeof(Libro)) )== NULL)

o ancora meglio evita queste facilitazioni della sintassi, che secondo me complicano solo la vita perche rendono il codice poco leggibile e favoriscono i bug:

aux = (Libro *) malloc (sizeof(Libro));
if(aux == NULL){

}


non ti piace cosi?
__________________
Sun Certified Java Programmer
EUCIP Core Level Certified

European Certification of Informatics Professionals
anx721 è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 00:14   #13
anx721
Senior Member
 
L'Avatar di anx721
 
Iscritto dal: Oct 2002
Città: Roma
Messaggi: 1502
Quote:

Solo che Linux ti fa uscire con un messaggio di errore, Microzozz si impianta.

Sempre a denigrare windows...windows non si pianta affatto, ti fà uscire la finestrella in cui ti dice che il programma ha causato un errore, clicchi sul pulsante 'chiudi', e continua normalmente, linux ti fa uscire il messagio 'segmentation fault' (credo) sulla console, non vedo la differenza
__________________
Sun Certified Java Programmer
EUCIP Core Level Certified

European Certification of Informatics Professionals
anx721 è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 01:24   #14
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
che pollo che sono!!



avete ragione l'errore era proprio lì... probabilmente mi ha fregato il gran numero di parentesi aperte.


grazie a tutti.

p.s. la cosa veramente vergognosa è che per 4-5 volte ho ignorato il warning che invece mi segnalava il tentativo di conversione INT->PTR... devo iniziare a leggere quei messaggi!!
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.

Ultima modifica di Diabolik.cub : 25-05-2004 alle 01:26.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 17:17   #15
h1jack3r
Senior Member
 
L'Avatar di h1jack3r
 
Iscritto dal: May 2002
Città: somewhere in Europe
Messaggi: 2554
Eh Diabolik...anche tu con Valenzano?
h1jack3r è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 21:22   #16
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
Quote:
Originariamente inviato da h1jack3r
Eh Diabolik...anche tu con Valenzano?


incredibile adesso scopriamo che siamo compagni di corso!!!

io sono 'inf' PRLP quindi al primo corso... (ovviamente primo anno) e tu?
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 25-05-2004, 22:56   #17
h1jack3r
Senior Member
 
L'Avatar di h1jack3r
 
Iscritto dal: May 2002
Città: somewhere in Europe
Messaggi: 2554
eh si...

sto forum è una figata cmq...e quella esercitazione è una bella rogna..
h1jack3r è offline   Rispondi citando il messaggio o parte di esso
Old 26-05-2004, 21:45   #18
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
siamo agli sgoccioli!

ho praticamente ultimato il programmino che devo fare, e funziona tutto se non fosse per un piccolo problema legato alla funzione free per "disallocare" la memoria di strutture da eliminare.

Per lo scopo ho definito una funzione "libera_memoria (Libro **ptr_aux)" dove Libro è una struttura composta da 2 campi: una stringa e un puntatore alla struttura (per creare una lista dinamica).

Il corpo della funzione è il seguente:
{
free (&(*ptr_aux)->Titolo);
free (&(*aux)->link_t);
}

subito dopo averla eseguita nel main con
Libro *aux;

libera_memoria (&aux);

libero il puntatore alla struttura con

free (aux);

Trovate qualche errore eclatante in queste righe di codice? Perchè dopo avermi liberato 5-6 puntatori mi viene il classico "Processor Fault" e non riesco a capire perchè!

ciao e grazie.
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.

Ultima modifica di Diabolik.cub : 26-05-2004 alle 21:50.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
Old 26-05-2004, 22:07   #19
anx721
Senior Member
 
L'Avatar di anx721
 
Iscritto dal: Oct 2002
Città: Roma
Messaggi: 1502
Il campo titolo non è un puntatore a della memoria allocata dinamicamente, quindi non dovrebbe essere deallocato con free, almeno cosi penso, poi non capisco perche usi l'operatore & e perche passi un puntatore a puntatore come argomento della funzione. Io avrei fatto così:

Codice:
void libera_memoria (Libro *ptr_aux){
         Libro * temp;
         while(ptr_aux != NULL){
                 //mi mantengo il puntatore all'elemento successivo
                 temp = ptr_aux -> link_t;
                 free(ptr_aux);
                 ptr_aux = temp;
         }
}
In questo caso ti basta l'istruzione

libera_memoria(aux);

per liberare tutta la memoria allocata.
__________________
Sun Certified Java Programmer
EUCIP Core Level Certified

European Certification of Informatics Professionals

Ultima modifica di anx721 : 26-05-2004 alle 22:09.
anx721 è offline   Rispondi citando il messaggio o parte di esso
Old 27-05-2004, 09:20   #20
Diabolik.cub
Senior Member
 
L'Avatar di Diabolik.cub
 
Iscritto dal: Apr 2001
Città: Torino (provincia)
Messaggi: 960
dunque non ho capito...

la tua funzione se non sbaglio mi dealloca tutti i puntatori da quello che inserisci fino all'ultimo, giusto?

io devo solo deallocare una singola struttura.

Mettiamo che questa struttura *aux sia composta da 3 stringhe a un puntatore alla struttura, non devo deallocare manualmente questi 4 puntatori prima di deallocare il puntatore 'aux' alla struttura??
__________________
Nel mercatino ho concluso con: eleoluca, huangwei, jai, ^v3rsus, Rinos, arvey, kinderboy.
Diabolik.cub è offline   Rispondi citando il messaggio o parte di esso
 Rispondi


Marvel's Wolverine, la recensione: Logan torna protagonista in un'avventura brutale e intensa Marvel's Wolverine, la recensione: Logan torna p...
DJI Romo 2: tante novità lo rendono un robot completo DJI Romo 2: tante novità lo rendono un ro...
Sony Bravia 9 II: il True RGB alla prova, dove l'LCD sfida l'OLED Sony Bravia 9 II: il True RGB alla prova, dove l...
Geely EX5, un mese al volante: il SUV elettrico cinese che ci ha sorpreso (quasi) senza riserve Geely EX5, un mese al volante: il SUV elettrico ...
Mova Z70 Ultra Roller Complete: motore potente, rullo di lavaggio e l'IA a guidare Mova Z70 Ultra Roller Complete: motore potente, ...
Avio si prepara ai test del Dimostratore...
Space Pioneer ha annunciato le cause del...
Anthropic avrebbe nuovi antibiotici cont...
Scoperto un 'moltiplicatore nascosto' ne...
DREO: a IFA 2026 4 novità fra cui...
Slackbot genera dashboard e microsite de...
Idrogeno, nuova cella a combustibile rag...
Con la NASA fuori dai giochi, l'ESA risc...
Una falla di ChatGPT permette di estrapo...
Piano clima, 1,34 miliardi per il bonus ...
Porsche esce definitvamente da Bugatti R...
NVIDIA App aggiunge una delle funzioni p...
Come sarebbe il mondo se la luce viaggia...
Titanio, ceramica e zaffiro per HUAWEI W...
Taglio delle accise sul gasolio prorogat...
Chromium
GPU-Z
OCCT
LibreOffice Portable
Opera One Portable
Opera One 106
CCleaner Portable
CCleaner Standard
Cpu-Z
Driver NVIDIA GeForce 546.65 WHQL
SmartFTP
Trillian
Google Chrome Portable
Google Chrome 120
VirtualBox
Tutti gli articoli Tutte le news Tutti i download

Strumenti

Regole
Non Puoi aprire nuove discussioni
Non Puoi rispondere ai messaggi
Non Puoi allegare file
Non Puoi modificare i tuoi messaggi

Il codice vB è On
Le Faccine sono On
Il codice [IMG] è On
Il codice HTML è Off
Vai al Forum


Tutti gli orari sono GMT +1. Ora sono le: 22:18.


Powered by vBulletin® Version 3.6.4
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Served by www3v