PDA

Visualizza la versione completa : [C] Replicare funziona explode/split


zacca94
18-06-2017, 21:33
void explode(char **str) {
int elem = 0, i = 0, i2 = 0;
char *prova = "-1,-1,2,3,5,6,7,8,9";
char *tmp = NULL;
char **ret = NULL;

for (; i < strlen(prova); i++) {
if (tmp != NULL) {
tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
} else {
tmp = (char *)malloc(1 * sizeof(char));
}

tmp[i] = *(prova+i);

/*printf("\nsize: %ld\n", strlen(tmp));
printf("\ntmp: %s\n", tmp);*/

if (*(prova+i) == ',') {
elem += 1;

if (ret == NULL) {
ret = (char **)malloc(elem * sizeof(char));
} else {
ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
}

ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));

for (; i2 < (strlen(tmp)-1); i2++) {
strcpy(ret[elem - 1], tmp[i2]);

}

free(tmp);
tmp = NULL;

}
}

free(tmp);

printf("\nElementi: %d\n", (elem+1));

Vorrei replicare la funzione explode di PHP o split di Python/JS per scopo didattico (senza strtok grazie).

2 quesiti:
- Lo "strcpy" non mi funziona. Perchè?
- Oltretutto come posso poi ritornare l'array dopo aver deallocato la memoria con free a ret?

oregon
18-06-2017, 21:52
- Lo "strcpy" non mi funziona. Perchè?

Che vuol dire? Come "non funziona"?



- Oltretutto come posso poi ritornare l'array dopo aver deallocato la memoria con free a ret?

Non devi chiamare la free e la funzione deve restituire il puntatore

Posta anche codice di esempio con un main che utilizza la tua funzione.
(ma a che serve il parametro str della funzione? come mai utilizzi prova all'interno della funzione?)

zacca94
18-06-2017, 22:16
A dir la verità non cambia quasi per niente in quanto mi ero concentro nel far funzionare la funzione, però in linea di massima dovrebbe essere:


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

char** explode(char sep, char *prova);

int main (void)
{
char **new;

new = explode(',', "-1,-1,2,3,5,6,7,8,9");

return 0;
}

char** explode(char sep, char *prova) {
int elem = 0, i = 0, i2 = 0;
//char *prova = "-1,-1,2,3,5,6,7,8,9";
char *tmp = NULL;
char **ret = NULL;

for (; i < strlen(prova); i++) {
if (tmp != NULL) {
tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
} else {
tmp = (char *)malloc(1 * sizeof(char));
}

tmp[i] = *(prova+i);

if (*(prova+i) == sep) {
elem += 1;

if (ret == NULL) {
ret = (char **)malloc(elem * sizeof(char));
} else {
ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
}

ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));

for (; i2 < (strlen(tmp)-1); i2++) {
strcpy(ret[elem - 1], tmp[i2]);

}

free(tmp);
tmp = NULL;

}
}

free(tmp);

printf("\nElementi: %d\n", (elem+1));

return ret;
}

oregon
18-06-2017, 22:22
La funzione va scritta nella sua forma finale.

La linea con la strcpy non può essere compilata perché il secondo argomento che passi

tmp[i2]

è un carattere e non una stringa. La stringa è tmp.

zacca94
18-06-2017, 22:24
Errore:
root@matias-desktop:/# gcc try.c -o try
try.c: In function ‘explode’:
try.c:43:39: warning: passing argument 2 of ‘strcpy’ makes pointer from integer without a cast [-Wint-conversion]
strcpy(ret[elem - 1], tmp[i2]);
^
In file included from try.c:1:0:
/usr/include/string.h:125:14: note: expected ‘const char * restrict’ but argument is of type ‘char’
extern char *strcpy (char *__restrict __dest, const char *__restrict __src)
^


(ho inserito 2 messaggi che mi diceva fosse troppo lungo)

zacca94
18-06-2017, 22:26
Scusa ora provo, non mi sta funzionando il forum, ora provo a modificare secondo i tuoi suggerimenti.

zacca94
18-06-2017, 22:43
Ho provato ad eliminare totalmente strcpy, a questo punto se posso dargli un valore con malloc alla array multdimensionale uguale alla lunghezza del "tmp"... questa è la funzione, però non funziona:


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

char** explode(char sep, char *prova);

int main (void)
{
char **new;

new = explode(',', "-1,-1,2,3,5,6,7,8,9");

return 0;
}

char** explode(char sep, char *prova) {
int elem = 0, i = 0, i2 = 0;
//char *prova = "-1,-1,2,3,5,6,7,8,9";
char *tmp = NULL;
char **ret = NULL;

for (; i < strlen(prova); i++) {
if (tmp != NULL) {
tmp = (char *)realloc(tmp, (strlen(tmp) + 1) * sizeof(char));
} else {
tmp = (char *)malloc(1 * sizeof(char));
}

tmp[i] = *(prova+i);

if (*(prova+i) == sep) {
elem += 1;

if (ret == NULL) {
ret = (char **)malloc(elem * sizeof(char));
} else {
ret = (char **)realloc(ret, (strlen(*ret) + 1) * elem * sizeof(char));
}

ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
ret[elem -1] = tmp;

/*for (; i2 < (strlen(tmp)-1); i2++) {
strcpy(ret[elem - 1], tmp);

}*/

free(tmp);
tmp = NULL;

}
}

free(tmp);

printf("\nElementi: %d\n", (elem+1));

return ret;
}

Errore:
root@matias-desktop:/home/matias/Desktop# gcc try.c -o try
root@matias-desktop:/home/matias/Desktop# ./try
*** Error in `./try': realloc(): invalid next size: 0x000000000197a030 ***
======= Backtrace: =========
/lib/x86_64-linux-gnu/libc.so.6(+0x777e5)[0x7ffbdf84e7e5]
/lib/x86_64-linux-gnu/libc.so.6(+0x82a5a)[0x7ffbdf859a5a]
/lib/x86_64-linux-gnu/libc.so.6(realloc+0x179)[0x7ffbdf85ac89]
./try[0x40075f]
./try[0x40065d]
/lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7ffbdf7f7830]
./try[0x400579]
======= Memory map: ========
00400000-00401000 r-xp 00000000 00:2c 4194365 /home/matias/Desktop/try
00600000-00601000 r--p 00000000 00:2c 4194365 /home/matias/Desktop/try
00601000-00602000 rw-p 00001000 00:2c 4194365 /home/matias/Desktop/try
0197a000-0199b000 rw-p 00000000 00:00 0 [heap]
7ffbd8000000-7ffbd8021000 rw-p 00000000 00:00 0
7ffbd8021000-7ffbdc000000 ---p 00000000 00:00 0
7ffbdf5bf000-7ffbdf5d5000 r-xp 00000000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffbdf5d5000-7ffbdf7d4000 ---p 00016000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffbdf7d4000-7ffbdf7d5000 rw-p 00015000 08:04 10228185 /lib/x86_64-linux-gnu/libgcc_s.so.1
7ffbdf7d7000-7ffbdf996000 r-xp 00000000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
7ffbdf996000-7ffbdfb96000 ---p 001bf000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
7ffbdfb96000-7ffbdfb9a000 r--p 001bf000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
7ffbdfb9a000-7ffbdfb9c000 rw-p 001c3000 08:04 10230132 /lib/x86_64-linux-gnu/libc-2.23.so
7ffbdfb9c000-7ffbdfba0000 rw-p 00000000 00:00 0
7ffbdfba7000-7ffbdfbcd000 r-xp 00000000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
7ffbdfdca000-7ffbdfdcc000 rw-p 00000000 00:00 0
7ffbdfdcc000-7ffbdfdcd000 r--p 00025000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
7ffbdfdcd000-7ffbdfdce000 rw-p 00026000 08:04 10230133 /lib/x86_64-linux-gnu/ld-2.23.so
7ffbdfdce000-7ffbdfdd0000 rw-p 00000000 00:00 0
7ffbdfdd0000-7ffbdfdd3000 rw-p 00000000 00:00 0
7fff1cb0d000-7fff1cb2e000 rw-p 00000000 00:00 0 [stack]
7fff1cb47000-7fff1cb49000 r--p 00000000 00:00 0 [vvar]
7fff1cb49000-7fff1cb4b000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
Aborted (core dumped)

oregon
18-06-2017, 22:53
Righe come queste

ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
ret[elem -1] = tmp;

non hanno senso. Assegni due valori diversi uno dopo l'altro allo stesso elemento, creando un memory leak ...

Fossi in te rivedrei tutto l'algoritmo che stai usando, anche perché non si riesce a capire molto.

E farei degli esercizi molto più semplici con puntatori, stringhe e caratteri perché devi chiarirti melgio il loro utilizzo.

zacca94
19-06-2017, 00:35
Righe come queste

ret[elem -1] = (char *)malloc(strlen(tmp) * sizeof(char));
ret[elem -1] = tmp;

non hanno senso. Assegni due valori diversi uno dopo l'altro allo stesso elemento, creando un memory leak ...

Ok ho fatto dei miglioramenti anche riscrivendo il codice e ordinandolo un pò:


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

char **explode(char sep, char *str);

int main (void)
{
int i, i2;

char **new;

new = explode(',', "100,2,3,4,5,6,7,8,9,");

printf("%s ", new[0]);
printf("%s ", new[1]);
return 0;
}

char **explode(char sep, char *str)
{
int elem = 0
, i = 0
, i2;

char *tmp = NULL
, **ret = NULL;

ret = (char **)malloc(sizeof(char **) * (strlen(str)));
for (; i < strlen(str); i++)
{
if (*(str + i) == sep || *(str + i) == '\n')
{
printf("\n- %s\n", tmp);

ret[elem] = (char *)malloc(sizeof(char) * (strlen(tmp)));
for (i2 = 0; i2 < strlen(tmp); i2++)
{
ret[elem][i2] = tmp[i2];
}

elem++;
free(tmp);
tmp = NULL;
}
else
{
/* Se è il primo ciclo alloca, altrimenti re-alloca uno spazio più grande */
if (tmp != NULL) tmp = (char *)realloc(tmp, sizeof(char) * (strlen(tmp) + 1));
else tmp = (char *)malloc (sizeof(char) * 1);

tmp[i] = *(str + i);
}
}

free(tmp);

printf("\nElementi: %d\n", (elem + 1));

return ret;
}

Però mi assegna solo il primo elemento (100), gli altri se li mangia... penso di fare casino con il free e l'assegnazione di NULL.

zacca94
19-06-2017, 01:51
C'è l'ho fatta:


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

char **explode(char sep, char *str);

int main (void)
{
int i;

char **new;

new = explode(',', "100,222,33,4444,55555,6,7,8,9,");

for (i = 0; i < 9; i++)
{
printf("%s ", new[i]);
}
return 0;
}

char **explode(char sep, char *str)
{
int elem = 0
, i = 0
, i2
, i3;

char *tmp = NULL
, **ret = NULL;

ret = (char **)malloc(sizeof(char) * (strlen(str)));
for (; i < strlen(str); i++)
{
if (*(str + i) == sep || *(str + i) == '\n')
{
ret[elem] = (char *)malloc(sizeof(char) * (strlen(tmp)));
for (i2 = 0; i2 < strlen(tmp); i2++)
{
ret[elem][i2] = tmp[i2];
}

elem++;
//free(tmp);
tmp = NULL;
}
else
{
/* Se è il primo ciclo alloca, altrimenti re-alloca uno spazio più grande */
if (tmp != NULL) tmp = (char *)realloc(tmp, (sizeof(char)) * (strlen(tmp) + 1));
else {
tmp = (char *)malloc(sizeof(char) * 1);
i3 = 0;
}

tmp[i3++] = *(str + i);
}
}

free(tmp);

printf("\nElementi: %d\n", (elem + 1));

return ret;
}

Avevo sbagliato questa riga: tmp[i] = *(str + i);
dove i rappresentava l'indice della posizione della stringa, mentre dovevo partire da 0 ogni volta che riallocavo.

Ora voglio dei consigli riguardo alla gestione del codice, ergo: è palese che essendo inesperto ho scritto più righe di codice quando potevo fare lo stesso procedimento più facilmente (per esempio ho notato che molti codici re-allocano direttamente).

E altra domanda: il "\n" lo devo salvare a fine riga o posso saltarlo?

Grazie

Loading