Oppure

Loading
27/08/09 10:49
Ciao ho un problema con le stringhe: devo ricavare username e password da un file di configurazione del tipo:

<config>
<rule1>400</rule1>
<username>nome</username>
<something>boh</something>
<password>secret</password>
</config>

Forse ho trovato il modo di farlo, ma il programma mi va in SegFault e non riesco a capire perchè (gcc compila senza warnings).

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

int main()
{
char *a, *b, *c;
a = strstr("aa<aa><username>admin</username>wdw","username");
a = strstr(a,">");
b = strstr(a,"<");
size_t n = strlen(a) - strlen(b);
strncpy(c,a,n);
printf("%s\n",c);

a = strstr(a,"password");
a = strstr(a,">");
b = strstr(a,"<");
n = strlen(a) - strlen(b);
strncpy(c,a,n);
printf("%s\n",c);

return 0;
}


Non so cosa sbaglio nel codice, qualche illuminazione?

-- PS ---
Per me va anche meglio se mi dite come fare la stessa cosa in bash!
Voglio dire, lo split in bash riesco a farlo solo usando come delimitatore un carattere, mentre a me servirebbe inserire una stringa:
Cioè
tmp=`echo $config | cut -d'<username>' -f2`

Mi da errore perchè <username> è una stringa e bisogna usare un carattere per il delimitatore...
31/08/09 15:18
HeDo

è un problema più complesso di quello che sembra, ad ogni modo guarda questo parser:

codeguru.com/cpp/data/data-misc/xml/article.php/c4549/

aaa
10/09/09 23:03
Grazie ma non ho risolto, al progetto che mi hai linkato gli ho dato una letta veloce, ma il codice è abbastanza lungo: a me serviva giusto una funzione.

NB: Non sono pigro ma il progetto non c'entrava comunque con la mia richiesta

Grazie,
aspetto qualche altra soluzione

Va bene anche se mettete a posto il codice che ho postato sopra, evitando il segfault!
Comunque è C, non C++
Ultima modifica effettuata da 10/09/09 23:08
11/09/09 9:40
HeDo

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

int GetField(char *pContent, char *pField, char *Buff, int iLen);

int main(int argc, char *pArgv[]) {

	int iRet;
	char pBuff[32];

	char *pFileContent = "<config><rule1>400</rule1><username>nome</username><something>boh</something><password>secret</password></config>";
	
	iRet = GetField(pFileContent, "username", pBuff, 32);
	
	if (!iRet) {

		printf("Unable to find 'username' field\n");

	} else {

		printf("Username: %s\n", pBuff);

	}

	iRet = GetField(pFileContent, "password", pBuff, 32);

	if (!iRet) {

		printf("Unable to find 'password' field\n");

	} else {

		printf("Password: %s\n", pBuff);

	}	

	iRet = GetField(pFileContent, "pippo", pBuff, 32);

	if (!iRet) {

		printf("Unable to find 'pippo' field\n");

	} else {

		printf("Pippo: %s\n", pBuff);

	}

	system("PAUSE");
		
	return 0;
}

int GetField(char *pContent, char *pField, char *pBuff, int iLen) {

	char *p, *pBeg, *pEnd;

	memset(pBuff, 0, iLen);

	// Look for the opening tag
	p = strstr(pContent, pField);

	if (!p) return 0;

	// Go beyond the field name
	p += strlen(pField);

	// Go Beyond spaces/newlines/etc.. till '>'
	while(*p && *p != '>') p++;

	// EOF
	if (!*p) return 0;

	// Beginning of field value
	pBeg = ++p;

	// Look for the closing tag, it should match the opening one
	pEnd = strstr(pBeg, pField);

	// EOF
	if (!pEnd) return 0;

	// Check malformed XML
	if ((*(pEnd - 1) != '/') || (*(pEnd - 2) != '<') | (*(pEnd + strlen(pField)) != '>')) return 0;

	// Backwards '</'
	pEnd -= 2;

	// Copy the extracted string value (length capped if needed)
	strncpy(pBuff, pBeg, (iLen < (pEnd - pBeg)) ? (iLen - 1) : (pEnd - pBeg));

	return 1;

}


è un parser BASE di XML che estrae solo i valori compresi tra due tag, è in grado di capire se l'xml non è ben formattato. Non supporta gli attributi ed è case sensitive.

EDIT: Perchè non mi colora la sintassi?
Ultima modifica effettuata da HeDo 11/09/09 10:21
aaa
11/09/09 12:58
Grazie mille, ottimo!! A parte il system("PAUSE); ... programmi su windows?
Credo che tu intendessi la funzione getchar()... credo che anche su windows ci sia, o almeno una simile.

Grazie comunque ciao

---- Edit ----
un'altra cosa: nella riga

 iRet = GetField(pFileContent, "username", pBuff, 32); 


e in

char pBuff[32];


32 sta per la lunghezza della stringa? Occorre cambiarlo a seconda della stringa, cioè della lunghezza del file xml?
Ultima modifica effettuata da 11/09/09 13:08
11/09/09 14:00
HeDo
Postato originariamente da TheWorm:

Grazie mille, ottimo!! A parte il system("PAUSE); ... programmi su windows?
Credo che tu intendessi la funzione getchar()... credo che anche su windows ci sia, o almeno una simile.

Grazie comunque ciao

---- Edit ----
un'altra cosa: nella riga

 iRet = GetField(pFileContent, "username", pBuff, 32); 


e in

char pBuff[32];


32 sta per la lunghezza della stringa? Occorre cambiarlo a seconda della stringa, cioè della lunghezza del file xml?


si l'ho fatto sotto windows, e la GetField ha come parametri: il contenuto del file xml, il campo da cercare, un buffer nel quale mettere il valore del campo e la lunghezza di questo buffer.

dovrebbe funzionare tutto senza problemi anche sotto linux, testa e fammi sapere :)
aaa
11/09/09 15:00
HeDo
EDIT: doppio post
Ultima modifica effettuata da HeDo 11/09/09 15:01
aaa
11/09/09 17:57
Grazie mille ho risolto subito con poche modifiche: ecco il parser a cui bisogna passare una stringa o il contenuto di un file come arg1 e il campo da ricercare come arg2.
Ex:
./xmlparse "<config><username>tony</username><password>secret123</password></config>" username
./xmlparse `cat config.xml` username

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

int GetField(char *pContent, char *pField, char *Buff, int iLen);

int main(int argc, char *pArgv[]) {

    if(argc < 3) {
	printf("Use: %s xmlstring desired_field\n", pArgv[0]);
	return -1;
    }

    char *pFileContent = pArgv[1];
    char *pField = pArgv[2];
    int strln = strlen(pFileContent);
    int iRet;
    char pBuff[strln];
    
    iRet = GetField(pFileContent, pField, pBuff, strln);
    
    if (!iRet) {
        printf("Unable to find '%s' field\n", pField);
    } else {

        printf("%s: %s\n", pField, pBuff);
    }
     
    return 0;
}

int GetField(char *pContent, char *pField, char *pBuff, int iLen) {

    char *p, *pBeg, *pEnd;

    memset(pBuff, 0, iLen);

    // Look for the opening tag
    p = strstr(pContent, pField);

    if (!p) return 0;

    // Go beyond the field name
    p += strlen(pField);

    // Go Beyond spaces/newlines/etc.. till '>'
    while(*p && *p != '>') p++;

    // EOF
    if (!*p) return 0;

    // Beginning of field value
    pBeg = ++p;

    // Look for the closing tag, it should match the opening one
    pEnd = strstr(pBeg, pField);

    // EOF
    if (!pEnd) return 0;

    // Check malformed XML
    if ((*(pEnd - 1) != '/') || (*(pEnd - 2) != '<') | (*(pEnd + strlen(pField)) != '>')) return 0;

    // Backwards '</'
    pEnd -= 2;

    // Copy the extracted string value (length capped if needed)
    strncpy(pBuff, pBeg, (iLen < (pEnd - pBeg)) ? (iLen - 1) : (pEnd - pBeg));

    return 1;

}