I need to break a string that I receive and I need to divide it. This division will be given to each comma. I’m getting him to recognize the comma

Asked

Viewed 43 times

-1

What I’ve done so far is this:

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

 int cont = 0;
 int pos[6];
char buffer[107] = "A!#NanoGsmA)85996161991,B)85996161991,C)85996161991,D)85996161991,E)85986854563,DATA: 09/06/21-09:50:00!!";
char buff[105];

int main(){


    for (int i = 0; i < strlen(buffer); i++) {
     
      buff[i] = buffer[i];
      if (buff[i] == ',') {
        cont++;
    if (cont <6) {
          pos[cont] = i+1 ;
        }
      }
    }
      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];

printf("%d\n,%d\n,%d\n,%d\n,%d\n",var1,var2,var3,var4,var5);
 }   

But it doesn’t show the numbers that are being separated.

  • 1

    You can’t use the functionstrtok?

  • the message may only come with a number and the rest of the number must be equal. Ex: A!#Nanogsm A)859961991.

  • 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.

  • 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...

  • 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

1 answer

1

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)

Browser other questions tagged

You are not signed in. Login or sign up in order to post.