i want to take information that is variable, and always comes after the word "data", e.g. Let’s say my string contains "data:HS73NSS9374N7ALW823", so I’m trying to develop a function that identifies the word "data" traverses 6 bytes and capture 19 bytes below "HS73NS9374N7ALW823"
There is a certain ambiguity in your question. You say you are looking for "dados"
but it looks like you’re looking "dados:"
and says that it wants to traverse 6 bytes but apparently wants to extract the data immediately from the string it is looking for, which in this case has 6 bytes if it is "dados:"
and not "dados"
as I said.
But your example helped well. Or I didn’t understand anything :) or so.
Imagine a function like this:
char* filtro19(
const char* origem,
const char* prefixo,
const size_t deslocamento,
const size_t comprimento);
Where
origem
is the initial string,"dados:HS73NSS9374N7ALW823"
in his case
prefixo
is, who would have thought, the prefix, like "dados:"
in his case
deslocamento
is the byte shift from where you start copying, 0 in your example
comprimento
is the total bytes you want to extract, 19 in your example
The return is a pointer to a string, dynamically allocated and which must be targeted by a free()
somewhere on your own. Of course, it returns NULL
if you cannot find the data to extract.
I have written an example. I have not tested beyond what I will show you below.
I tried not to call any other function, except malloc()
and memcpy()
at the end. I could avoid memcpy()
, but you’d have to copy it anyway and since you can’t tell if you have all the bytes to extract until you find the end of the entry so it should be faster.
Note that you need to test if you actually have enough data to extract before finishing the input string, and need to finish the output string at the end.
That is the function:
char* filtro19(
const char* origem,
const char* prefixo,
const size_t deslocamento,
const size_t comprimento)
{
size_t ixIn = 0;
size_t ix = 0; // para o deslocamento
char st = 0;
const char* alvo = prefixo;
char* saida = NULL;
// vai ate o fim da string de origem
while (*origem != 0)
{
switch (st)
{
case 0: // buscando inicio do prefixo
if (*origem != *prefixo)
{ // ainda nada
origem += 1;
break;
}; // if()
origem += 1;
prefixo += 1;
st = 1;
break;
case 1: // buscando prefixo na string
if (*prefixo == 0)
{ // fim do prefixo
st = 2;
break;
}; // if()
if (*prefixo != *origem)
{
st = 0;
prefixo = alvo; // reinicia prefixo
break;
};
// igual por enquanto
ixIn += 1; // precisa do tamanho
origem += 1;
prefixo += 1;
break;
case 2: // andando no intervalo
if (ix == deslocamento)
{
st = 3;
ix = 0; // agora vai contar a saida
alvo = origem; // aqui comeca o alvo
break;
};
ix += 1; // anda uma casa
origem += 1;
break;
case 3: // agora aponta para a saida e conta
// os bytes pedidos
if (*origem == 0)
{ // acabou antes: nao tem bytes suficientes
// depois do prefixo e eventual deslocamento
return NULL;
};
ix += 1;
if (ix == comprimento)
{ // achou tudo!
saida = malloc(comprimento + 1);
memcpy(saida, alvo, comprimento);
*(saida + comprimento) = 0;
return saida;
}; // if()
origem += 1;
break;
default:
break;
}
};
// se chegou aqui nao achou nada
return NULL;
};
The logic is simple: it is a FSA, a state machine because it’s easier to write. The idea is simple: search the prefix, calculate the offset, check if you have the requested content, allocate the memory, copy the data and finish the string.
Here is the output of a test program, with a function teste()
to display the parameters
Filtro: Buscando 2 bytes
0 bytes depois de
'73' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() retornou 'NS' [2]
Filtro: Buscando 2 bytes
0 bytes depois de
'8' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() retornou '23' [2]
Filtro: Buscando 3 bytes
0 bytes depois de
'8' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() nao encontrou resultado
Filtro: Buscando 1 bytes
0 bytes depois de
'2' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() retornou '3' [1]
Filtro: Buscando 5 bytes
2 bytes depois de
':' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() retornou '73NSS' [5]
Filtro: Buscando 19 bytes
0 bytes depois de
'dados:' em
'HS73NSS9374dados:HS73NSS9374N7ALW823'
filtro() retornou 'HS73NSS9374N7ALW823' [19]
Understand that the offset can be zero as in the case of your example. And the value between [ ] in the example is the length of the string returned
I don’t want to get into religious discussions here. I compiled only with CL 19.27 from Microsoft.
Here’s the whole program
#include <memory.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char* filtro19(
const char*, const char*,
const size_t, const size_t
); // o filtro
void teste(const char*, const char*,
const size_t, const size_t); // o teste
int main(void)
{
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
"73", 0, 2);
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
"8", 0, 2);
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
"8", 0, 3);
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
"2", 0, 1);
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
":", 2, 5);
teste("HS73NSS9374dados:HS73NSS9374N7ALW823",
"dados:", 0, 19);
return 0;
}; // main()
char* filtro19(
const char* origem,
const char* prefixo,
const size_t deslocamento,
const size_t comprimento)
{
size_t ixIn = 0;
size_t ix = 0; // para o deslocamento
char st = 0;
const char* alvo = prefixo;
char* saida = NULL;
// vai ate o fim da string de origem
while (*origem != 0)
{
switch (st)
{
case 0: // buscando inicio do prefixo
if (*origem != *prefixo)
{ // ainda nada
origem += 1;
break;
}; // if()
origem += 1;
prefixo += 1;
st = 1;
break;
case 1: // buscando prefixo na string
if (*prefixo == 0)
{ // fim do prefixo
st = 2;
break;
}; // if()
if (*prefixo != *origem)
{
st = 0;
prefixo = alvo; // reinicia prefixo
break;
};
// igual por enquanto
ixIn += 1; // precisa do tamanho
origem += 1;
prefixo += 1;
break;
case 2: // andando no intervalo
if (ix == deslocamento)
{
st = 3;
ix = 0; // agora vai contar a saida
alvo = origem; // aqui comeca o alvo
break;
};
ix += 1; // anda uma casa
origem += 1;
break;
case 3: // agora aponta para a saida e conta
// os bytes pedidos
if (*origem == 0)
{ // acabou antes: nao tem bytes suficientes
// depois do prefixo e eventual deslocamento
return NULL;
};
ix += 1;
if (ix == comprimento)
{ // achou tudo!
saida = malloc(comprimento + 1);
memcpy(saida, alvo, comprimento);
*(saida + comprimento) = 0;
return saida;
}; // if()
origem += 1;
break;
default:
break;
}
};
// se chegou aqui nao achou nada
return NULL;
};
void teste(
const char* origem,
const char* prefixo,
const size_t deslocamento,
const size_t comprimento
)
{
printf(
"\n\tFiltro:\tBuscando %zd bytes\n\t\t%zd bytes depois de "
"\n\t\t'%s' em\n\t\t'%s'\n",
comprimento, deslocamento, prefixo, origem);
char* valor = filtro19(origem, prefixo, deslocamento, comprimento);
if (valor != NULL)
printf("\nfiltro() retornou '%s' [%zd]\n", valor, strlen(valor));
else
printf("\nfiltro() nao encontrou resultado\n");
}; // teste()
// /questions/470035/
// retonar-parte-de-uma-string-no-return-da-fun%c3%a7%c3%a3o
Cool turned out great, but I still need a "for", why? Because, I want to take information that is variable, and it always comes after the word "data", e.g. Let’s say my string contains "data:HS73NSS9374N7ALW823", so I’m trying to develop a function that identifies the word "data" traverses 6 bytes and captures 19 bytes below "HS73NS9374N7ALW823".
– Dennis Piassa
The code I posted is a little more generic, but should do what you need
– arfneto