I’m not sure I understand the logic of what you’re trying to do on your show, but it’s something like a scanf()
imagine.
Whether to read only a table of values and at all times has 6 can use a call to sscanf()
and read everything at once. A single command.
About your program
Perhaps you would agree that
char buffer[107] = "A!#NanoGsmA)85996161991,B)85996161991,C)85996161991,D)85996161991,E)85986854563,DATA: 09/06/21-09:50:00!!";
is bad to read. You can write
char buffer[] = "\
A!#NanoGsmA)85996161991,\
B)85996161991,\
C)85996161991,\
D)85996161991,\
E)85986854563,\
DATA: 09/06/21-09:50:00!!";
using ' \ '
to indicate that it continues on the next line. It’s much easier. And you don’t have to declare the size of buffer
since the compiler can tell you.
using sscanf()
Watch this program
#include <stdio.h>
#include <string.h>
int main(void)
{
char buffer[] = "\
A!#NanoGsmA)85996161991,\
B)85996161991,\
C)85996161991,\
D)85996161991,\
E)85986854563,\
DATA: 09/06/21-09:50:00!!";
char campo[6][107];
const char* mascara = "%[^,]%*c%[^,]%*c%[^,]%*c%[^,]%*c%[^,]%*c%[^,]";
int res = sscanf ( buffer, mascara,
&campo[0][0], &campo[1][0], &campo[2][0],
&campo[3][0], &campo[4][0], &campo[5][0]
);
printf( "sscanf() leu %d\n", res);
if ( res == 6 )
for( int i=0; i<6; i+=1 )
printf( "#%d: \"%s\"\n", 1+i, campo[i] );
return 0;
}
who has only one instruction and uses sscanf()
to do this job. Understand that '[^,]'
consumes everything you have in the buffer up to but not including the ','
and the '*c%'
jumps the obvious comma that defined the previous field and thus explains the variable mascara
used in the call.
The program shows
sscanf() leu 6
#1: "A!#NanoGsmA)85996161991"
#2: "B)85996161991"
#3: "C)85996161991"
#4: "D)85996161991"
#5: "E)85986854563"
#6: "DATA: 09/06/21-09:50:00!!"
I don’t understand why you’re copying buffer
for buf
if not using. I highly recommend using more meaningful names. buffer
and buf
is bad to read.
And if they are strings you can copy using strcpy()
as below:
char original[] = "coisas";
char copia[100];
strcpy( copia, original) ;
Do not declare variables outside of main()
. Is a disaster.
About this passage
int var1 = pos[1] - pos[0];
int var2 = pos[2] - pos[1];
int var3 = pos[3] - pos[2];
int var4 = pos[4] - pos[3];
int var5 = pos[5] - pos[4];
This I imagine should give the sizes of the fields. Note that did not initialize pos
Example
This show I think does what it wants
#include <stdio.h>
#include <string.h>
int main(void)
{
char buffer[] = "\
A!#NanoGsmA)85996161991,\
B)85996161991,\
C)85996161991,\
D)85996161991,\
E)85986854563,\
DATA: 09/06/21-09:50:00!!";
// 23 14 14 14 14 25
int pos[107] = {0};
int i = 0;
int n = 0;
while ( buffer[i] != 0 )
{ if ( buffer[i] == ',' ) pos[++n] = i; // conta esse
i += 1;
};
pos[++n] = strlen(buffer) - 1;
printf("lidos %d campos\npos: ", n );
// para conferir
for( int i = 0; i<n; i+=1 ) printf("%d ", pos[i] );
printf("\ntamanhos: ");
for( int i = 0; i<n; i+=1 ) printf("%d ", (pos[i+1] - pos[i]) );
printf("\nOs separadores: ");
for( int i = 1; i<n; i+=1 ) printf("%c ", buffer[ (int)pos[i] ]);
printf("\n");
return 0;
}
And shows
lidos 6 campos
pos: 0 23 37 51 65 79
tamanhos: 23 14 14 14 14 25
Os separadores: , , , , ,
Another way
It may be more useful to read the string and split into others already ready to use...
Consider a function like this:
EXAMPLE
char** quebra(const char*);
Which you call by passing the line and it returns pointers to the already separated fields, and which you can call straight, for example:
char** uma = quebra("stack,overflow");
for( int i=0; uma[i]!=NULL; i+=1 ) printf("%d:\t\"%s\"\n", 1 + i, uma[i]);
and see on screen
1: "stack"
2: "overflow"
And it’s normal in C because it’s more practical.
how it would be a function like this?
Here’s an example commented on in C
char** quebra(const char* original)
{
const char delim = ','; // fixo
// agora aloca um vetor de ponteiros para as substrings
char** subs = (char**)malloc(sizeof(char*)*(2 + strlen(original)) );
const char* p = original;
const char* pIn = p; // inicio da substring
int N = 0; // N = total de substrings
while (*p != 0)
{ // ate o fim da string
if (*p == delim) // achou uma sub
{
subs[N] = (char*)malloc(1 + p - pIn);
memcpy(subs[N], pIn, p - pIn); // copia
subs[N][p - pIn] = 0; // termina a string
N += 1; // conta essa
pIn = 1 + p; // inicio da proxima
}; // if()
p++;
}; // while()
subs[N] = (char*)malloc(1 + p - pIn); // a ultima
memcpy(subs[N], pIn, p - pIn + 1); // copia a ultima
N += 1; // conta essa
subs[N] = NULL; // indica o final
return subs;
}
The logic is linear: a single loop scans the input and as it finds the delimiters assembles the strings. Note that the strings are copies of the data and can be used separately, and the original string, declared as const
, is preserved.
a complete test program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** quebra(const char*);
int main(void)
{
char buffer[] = "\
A!#NanoGsmA)85996161991,\
B)85996161991,\
C)85996161991,\
D)85996161991,\
E)85986854563,\
DATA: 09/06/21-09:50:00!!";
char* teste[] =
{
"",
"teste",
buffer,
",,,",
"1,2,3,4"
}; // uns testes basicos
// agora testa com todas as strings em 'outras'
int n_testes = sizeof(teste) / sizeof(char*);
printf("\n+%d testes:\n\n", n_testes);
char** uma = quebra("stack,overflow");
for (int i = 0; uma[i] != NULL; i += 1)
{
printf("%d:\t\"%s\"\n", 1 + i, uma[i]);
free(uma[i]);
}; // for()
char** subs = NULL;
for (int i = 0; i < n_testes; i += 1)
{
printf("\n==> #%d de %d:\nEntrada:\t\"%s\"\n", 1 + i, n_testes, teste[i]);
subs = quebra(teste[i]);
int N = 0;
while( subs[N] != NULL)
{
printf("%d:\t\"%s\"\n", 1 + i, subs[N]);
free(subs[N]); // nao vai usar mais
N += 1;
}
printf("\nEncontrada (s) %d substring (s)\n\n", N);
free(subs); // nao vai usar mais
}; // for()
return 0;
}
char** quebra(const char* original)
{
const char delim = ','; // fixo
// agora aloca um vetor de ponteiros para as substrings
char** subs = (char**)malloc(sizeof(char*)*(2 + strlen(original)) );
const char* p = original;
const char* pIn = p; // inicio da substring
int N = 0; // N = total de substrings
while (*p != 0)
{ // ate o fim da string
if (*p == delim) // achou uma sub
{
subs[N] = (char*)malloc(1 + p - pIn);
memcpy(subs[N], pIn, p - pIn); // copia
subs[N][p - pIn] = 0; // termina a string
N += 1; // conta essa
pIn = 1 + p; // inicio da proxima
}; // if()
p++;
}; // while()
subs[N] = (char*)malloc(1 + p - pIn); // a ultima
memcpy(subs[N], pIn, p - pIn + 1); // copia a ultima
N += 1; // conta essa
subs[N] = NULL; // indica o final
return subs;
}
// fim
That tests the function with an array of test strings, which includes its example.
1: "stack"
2: "overflow"
+5 testes:
==> #1 de 5:
Entrada: ""
1: ""
Encontrada (s) 1 substring (s)
==> #2 de 5:
Entrada: "teste"
2: "teste"
Encontrada (s) 1 substring (s)
==> #3 de 5:
Entrada: "A!#NanoGsmA)85996161991,B)85996161991,C)85996161991,\\...
D)85996161991,E)85986854563,DATA: 09/06/21-09:50:00!!"
3: "A!#NanoGsmA)85996161991"
3: "B)85996161991"
3: "C)85996161991"
3: "D)85996161991"
3: "E)85986854563"
3: "DATA: 09/06/21-09:50:00!!"
Encontrada (s) 6 substring (s)
==> #4 de 5:
Entrada: ",,,"
4: ""
4: ""
4: ""
4: ""
Encontrada (s) 4 substring (s)
==> #5 de 5:
Entrada: "1,2,3,4"
5: "1"
5: "2"
5: "3"
5: "4"
Encontrada (s) 4 substring (s)
You can’t use the function
strtok
?– hkotsubo
the message may only come with a number and the rest of the number must be equal. Ex: A!#Nanogsm A)859961991.
– Vinicius de Morias
Sure, the Strtok, but I tried to create something automatic, where it counts the number of ',' and divide them from that count. If you have an idea how I can do that will be of great help.
– Vinicius de Morias
The problem is that this way you have to go through the string 2 times: one to count and the other to divide. It is simpler to scroll through the string once: it starts from the first position and advances until it finds the comma, but already storing the characters in a substring. When you find the comma, save this substring and start another: arrow the starting position to after the comma and go until you find another, storing the characters in the new substring, and so on...
– hkotsubo
Tip: https://ideone.com/R7SKFc (simple example, which only prints, but if you want to save the strings, you would have to adapatar and put the partial strings in another array, for example). Remembering what to use
strlen
in a loop is not efficient: https://answall.com/q/167528/112052– hkotsubo