Counter of a subsequence of strings repeated in C

5

Consider a string composed of several subsequences.

  

For example: cccaaaabbbbxdddddddddaaannn.

The smallest substring is the letter x, with only one element; the largest subsequence is that of letter d, with 9 elements. Make an algorithm to read a string and show which is the letter that occurs in the largest subsequence and its size, as well as the letter that occurs in the smallest subsequence and its size.

Ex.:

  • Admission: aaabbbbaa;

  • Output: greater b, size 4; less than, size 2.

I was able to get the code to register and show the highest subsequence correctly but in the second if I can not figure out the correct logic to register and show the smallest subsequence of repeated characters.

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

#define n 50

int main()
{
    setlocale(LC_ALL,"portuguese");

    char cmaior, cmenor;
    char v[n];
    int i, temp = 1, maior=temp, menor=temp;

    printf("\nDigite a string: ");
    gets(v);

    for(i = 0;i < (strlen(v)-1); i++)
    {
        if(v[i] == v[i+1])
        {
            temp++;
        }
        else
        {
            temp = 1;
        }

        if ( temp > maior )
        {
            maior = temp;
            cmaior = v[i];
        }

        if ( temp <= menor )
        {
            menor = temp;
            cmenor = v[i];
        }

    }

    printf("\n Maior: %c, tamanho %d; Menor: %c, tamanho %d\n",cmaior,maior, cmenor, menor);

    return 0;
}
    
asked by anonymous 01.11.2018 / 21:18

3 answers

1

First, note that your code has some warnings:

main.c: In function ‘main’:
main.c:17:5: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
     gets(v);
     ^~~~
     fgets
main.c:19:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(i = 0;i < (strlen(v)-1); i++)
                 ^
/tmp/ccWK0gqI.o: In function 'main':
main.c:(.text+0x5a): warning: the 'gets' function is dangerous and should not be used.

In the condition of the loop for , you i < (strlen(v)-1) , in fact it should be i < strlen(v) or i <= strlen(v) - 1 . You mixed the two possibilities.

At each iteration you apply the check of the smallest string size. This is a logic error. All counts start with 1, so your algorithm incorrectly states that the smallest repetition is of size 1, even if it does not even exist. Take the test:

Digite a string: aaabbbbcccccc

Maior: c, tamanho 6; Menor: b, tamanho 1

See that the algorithm said that the smallest sequence has size 1, and that there is no size 1 sequence in the string.

You should do these checks only when the stream ends , which is in else of the first if .

for (i = 0; i < strlen(v); i++)
{
    if (v[i] == v[i+1])
    {
        temp++;
    }
    else
    {
        if (temp > maior)
        {
            maior = temp;
            cmaior = v[i];
        }

        if (temp < menor)
        {
            menor = temp;
            cmenor = v[i];
        }

        temp = 1;
    }
}

Lastly, you should initialize the counter menor with the highest possible value, so you ensure that your logic will update it during the loop (otherwise the condition will always be false when the smallest sequence is greater than 1) . The highest possible value is n , so use it to initialize the variable.

Here is the complete code, already with the warnings fixed:

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

#define n 50

int main()
{
    setlocale(LC_ALL,"portuguese");

    char cmaior, cmenor;
    char v[n];
    size_t maior = 1, menor = n, i, temp = 1;

    printf("\nDigite a string: ");
    fgets(v, n, stdin);
    v[strlen(v)-1] = '
main.c: In function ‘main’:
main.c:17:5: warning: implicit declaration of function ‘gets’; did you mean ‘fgets’? [-Wimplicit-function-declaration]
     gets(v);
     ^~~~
     fgets
main.c:19:17: warning: comparison between signed and unsigned integer expressions [-Wsign-compare]
     for(i = 0;i < (strlen(v)-1); i++)
                 ^
/tmp/ccWK0gqI.o: In function 'main':
main.c:(.text+0x5a): warning: the 'gets' function is dangerous and should not be used.
'; cmaior = v[0]; for (i = 0; i < strlen(v); i++) { if (v[i] == v[i+1]) { temp++; } else { if (temp > maior) { maior = temp; cmaior = v[i]; } if (temp < menor) { menor = temp; cmenor = v[i]; } temp = 1; } } printf("\nMaior: %c, tamanho %zu; Menor: %c, tamanho %zu\n", cmaior, maior, cmenor, menor); return EXIT_SUCCESS; }
    
02.11.2018 / 18:43
5

The problem is that menor starts already with a very low number, so it gets complicated. Just as you have initialized maior with the lowest possible number, you have to initialize menor with the highest possible number, so it is N . I improved some in the code:

#include <stdio.h>
#include <locale.h>

#define N 51

int main() {
    setlocale(LC_ALL,"portuguese");
    char cmaior, cmenor;
    char v[N];
    int contMaior = 1, contMenor = 1, maior = 1, menor = N;
    printf("\nDigite a string: ");
    scanf("%s", v);
    for (int i = 0; v[i] != '
#include <stdio.h>
#include <locale.h>

#define N 51

int main() {
    setlocale(LC_ALL,"portuguese");
    char cmaior, cmenor;
    char v[N];
    int contMaior = 1, contMenor = 1, maior = 1, menor = N;
    printf("\nDigite a string: ");
    scanf("%s", v);
    for (int i = 0; v[i] != '%pre%'; i++) {
        if (v[i] == v[i + 1]) {
            contMaior++;
            contMenor++;
        } else {
            contMaior = 1;
            contMenor = N;
        }
        if (contMaior > maior) {
            maior = contMaior;
            cmaior = v[i];
        }
        if (contMenor < menor) {
            menor = contMenor;
            cmenor = v[i];
        }
    }
    printf("\n Maior: %c, tamanho %d; Menor: %c, tamanho %d\n", cmaior, maior, cmenor, menor);
}
'; i++) { if (v[i] == v[i + 1]) { contMaior++; contMenor++; } else { contMaior = 1; contMenor = N; } if (contMaior > maior) { maior = contMaior; cmaior = v[i]; } if (contMenor < menor) { menor = contMenor; cmenor = v[i]; } } printf("\n Maior: %c, tamanho %d; Menor: %c, tamanho %d\n", cmaior, maior, cmenor, menor); }
    
01.11.2018 / 21:27
2

Your problem of the shortest sequence is in the loop, if you did not change it as Maniero suggested.

You use:

for(i = 0;i < (strlen(v)-1); i++)

In your case of entry the word has 9 letters. That way you made it to i < 8 , that is, it goes up to i = 7 .

If you want to keep the loop that way, it has to be:

for(i = 0;i < strlen(v); i++)
    
01.11.2018 / 21:56