Jump to content

Erro em string


Leudassdf
 Share

Recommended Posts

Boas pessoal,

tenho o seguinte codigo:

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

int main()
{
   char str[3],caracteresValidos[]="#ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.!";
   strcpy(str,"abc");
   int i=0,j=0,ncaracteresValidos=0;
   //printf("%d\n%d",strlen(str),strlen(caracteresValidos));
   printf("Str:%s\n",str);
   for(i=0;i<3;i++)
   {
       //verifica se todos os caracteres sao validos
       for(j=0;j<strlen(caracteresValidos);j++)
       {
           if(toupper(str[i])==toupper(caracteresValidos[j])){//ncaracteresvalidos++;
                   ncaracteresValidos++;
                   break;
           }
       }
   }
   printf("Str:%s\n",str);
   printf("%d\n%d",strlen(str),strlen(caracteresValidos));
   //if(ncaracteresValidos==strlen(str)) printf("Sim");
   return 0;
}

O problema é que na primeira saida sai o valor abc mas na segunda adiciona um coração ao str. isto deixa de acontecer quando coloco o ncaracteresValidos++ em comentario.

No entanto nao estou a perceber o que causa isto.

Alguem me sabe dizer qual o problema?

Cumprimentos

Leandro

Link to comment
Share on other sites

eu não percebo muito bem que andas p'rai a tentar fazer, mas não deves fazer ideia do tremendo erro que tens quando existe um caracter em str "inválido" ...

ps : vendo melhor o problema é ainda pior ...

testa a seguinte str : "ba"

Edited by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

eu não percebo muito bem que andas p'rai a tentar fazer, mas não deves fazer ideia do tremendo erro que tens quando existe um caracter em str "inválido" ...

ps : vendo melhor o problema é ainda pior ...

testa a seguinte str : "ba"

ja percebi o problema.quando faco com o "ba" fica igual. Estavas a falar do numero 3 no ciclo for?

Se sim foi so para teste. Ai vai ficar o strlen(str)

Link to comment
Share on other sites

ja percebi o problema.quando faco com o "ba" fica igual. Estavas a falar do numero 3 no ciclo for?

Se sim foi so para teste. Ai vai ficar o strlen(str)

estás longe do problema ...

dica : fazes ideia do que está a acontecer quando fazes ?

ncaracteresValidos++;
Edited by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

é isso que estás a ler na declaração da variável ?

char caracteresValidos[]="#ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.!";

Não estás a confundir caracteresValidos com ncaracteresValidos?

(O único problema que eu vi no código está no tamanho de str, onde não está a ser considerado o espaço para o \0. E penso que era a isto que o HHH se referia quando sugeriu o teste com "ba", que já é uma string que cabe na variável str.)

Link to comment
Share on other sites

Não estás a confundir caracteresValidos com ncaracteresValidos?

(O único problema que eu vi no código está no tamanho de str, onde não está a ser considerado o espaço para o \0. E penso que era a isto que o HHH se referia quando sugeriu o teste com "ba", que já é uma string que cabe na variável str.)

nao a confundir acho que nao. verifiquei varias vezes.

eu depois percebi que efetivamente o tamanho estava mal. quando o HHH respondeu pela primeira vez eu tentei dizer isso ainda que nao se tivesse entendido. para alem de que o ciclo for estava a ser repetido sempre 3 vezes. e esse 3 teria de ser o teria de ser o tamanho da string, pois a string pode nao ter propriamente os 3 caracteres.

HHH era este o problema a que te referias?

Link to comment
Share on other sites

peço desculpa

realmente, estava a confundir as variáveis (é o que dá estar a responder a tópicos a essa hora ...)

inicialmente era minha minha intenção dizer que "abc" tem na realidade 4 bytes e não 3, mas depois descarrilou devido à confusão.

nota : o que deverá estar a acontecer é

- como o comportamento do strcpy é indefinido para casos em que o destino é menor que o espaço necessário, a cópia deverá estar a ocorrer com sucesso mas com o caracter '\0' no byte imediatamente após o array de 3 bytes (como numa string normal)

- o espaço (byte) imediatamente após o array deverá estar a ser atribuído a outra variável

- após a execução o valor da variável que não o array será alterado para um valor que não o '\0' (zero = 0)

- o printf tenta apresentar a string guardada no array, processo que é agnóstigo ao tamanho do array porque o que interessa e mesmo o primeiro byte com o valor de '\0' (zero = 0)

conclusão : nunca esquecer do terminador de string '\0' !

IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Pois esse é uma das coisas que nao me posso esquecer. e que uma pessoa as vezes esquece-se do terminador. e isso depois torna-se um grande problema.

No entanto esta implementação nao é a melhor. Pelo menos parece-me que nao. Por isso queria saber a vossa opiniao acerca da implementação abaixo:

int main()
{
char str[]="a bcá;";
int i=0;
for(i=0;i<strlen(str);i++)
{
    if((((int)str[i]>=32 && (int)str[i]<=58) || ((int)str[i]>=60 && (int)str[i]<=126))!=1)
    {
    printf("Caracter invalido na Posicao:%d\n",i+1);
    }
}
return 0;
}

O objectivo continua a ser verificar se o utilizador nao escreve caracteres invalidos. P.ex:caracteres com acentuação.

Será esta uma implementação mais eficiente?

Edited by Leudassdf
Link to comment
Share on other sites

queres eficiente ? ok:

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

#define VALID_CHARS " #ABCDEFGHIJKLMNOPQRSTUVWXYZ01234567890_.!"

int compare(const void * a, const void * b) {
   return ( *(char *) a - *(char *) b );
}

int validate(const char * chk, const char * val, int * is_valid) {
 char * auxchk = NULL, * auxval = NULL;
 char * iauxchk = NULL, * iauxval = NULL;

 if (chk == NULL || val == NULL || is_valid == NULL)
   return -1;

 if ((auxval = malloc(strlen(val) + 1)) == NULL)
   return -2;

 if ((auxchk = malloc(strlen(chk) + 1)) == NULL) {
   free(auxval);
   return -3;
 }

 strcpy(auxchk, chk);
 strcpy(auxval, val);

 qsort(auxchk, strlen(auxchk), sizeof(char), compare);
 qsort(auxval, strlen(auxval), sizeof(char), compare);

 iauxchk = auxchk;
 iauxval = auxval;

 *is_valid = 1;
 while (*iauxchk != 0 && *is_valid) {
   while (*iauxval != 0 && tolower(*iauxval) < tolower(*iauxchk))
     ++iauxval;

   if (tolower(*iauxval) == tolower(*iauxchk))
     ++iauxchk;
   else
     *is_valid = 0;
 }

 free(auxchk);
 free(auxval);

 return 0;
}

int main(void) {
 char * string = "my string";
 int is_valid;

 validate(string, VALID_CHARS, &is_valid);
 if (is_valid)
   printf("%s : is valid !!!\n", string);
 else
   printf("%s : is not valid ...\n", string);

 return 0;
}

pode parecer estranho ao ler o código e ver um while dentro de outro while e dizer que é eficiente, mas se leres bem o código, verás que é na realidade bem eficiente

isto claro em termos de processamento e não em termos de memória, pois é necessário duplicar as strings devido ao processo destrutivo dos dados originais

---------------

nota em termos de complexidade :

+ duas alocações de memória

+ duas cópias de memória

+ duas ordenações com qsort (n*log2(n))

+ (no pior caso) um varrimento completo das duas strings (strlen(chk) + strlen(val))

+ duas libertações de memória

total ~> (desprezar memória) + 2*n*log2(n) + strlen(chk) + strlen(val)

implementação naive :

+ (no pior caso) varrer a lista de caracteres válidos o número de vezes igual ao número de caracteres a serem verificados

total ~> strlen(chk) * strlen(val)

Edited by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

By using this site you accept our Terms of Use and Privacy Policy. We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.