Jump to content
  • Revista PROGRAMAR: Já está disponível a edição #60 da revista programar. Faz já o download aqui!

NASG

[Resolvido] strtol com letras para "digitos"

Recommended Posts

NASG

Bom dia a todos. Estou a implementar um programa que recebe na linha de comandos dois valores e deve dividir um pelo outro. Para isso tenho de usar a instrução STRTOL. O programa está a funcionar correctamente com valores numericos, mas quando coloco caracteres como a, ou b, ou c, o programa retorna sempre a mensagem não pode dividir por 0. Não é suposto a instrução strtol pegar no caracter e o traduzir para um numero inteiro longo e fazer a divisão na mesma. Alguem pode ajudar ?

Desde já obrigado

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

void minha_divisao(long int a, long int n,long int *quoc, long int *resto)
{

 *quoc =a/n;
 *resto=a%n;   

}

int main (int argc, char *argv[ ]) /* Estes parametros são usados quando queremos que o nosso programa aceite parametros através da linda de comandos */
{

    long int a,n;
    long int quoc, resto;

    if(argc<3||argc>3)
    {
    printf("Argumentos invalidos !!! Tem de digitar apenas dois valores.\n ");
   return 0;

    }

a=strtol(argv[1],NULL,0);                   
n=strtol(argv[2],NULL,0);

    if(n==0)
    {
               printf("Nao pode fazer a divisao por 0. Digite novo valor para Divisor :\n ");
       printf("Deve digitar na forma ./my_divisao num1, num2 e num2 nao pode ser=0 !!\n ");
       return 0;

    }

  minha_divisao(a,n,&quoc,&resto);


      printf("Resultado do quociente e: ""%ld\n",quoc);
   printf("Resultado do resto e: ""%ld\n",resto);

  return 0;         

}

Edited by pmg
GeSHi

Share this post


Link to post
Share on other sites
pmg

Não é suposto a instrução strtol pegar no caracter e o traduzir para um numero inteiro longo e fazer a divisão na mesma?

Nem por isso. Ve a descricao da funcao no site do POSIX, por exemplo

If the value of base is 0, the expected form of the subject sequence is that of a decimal constant, octal constant, or hexadecimal constant, any of which may be preceded by a '+' or '-' sign. A decimal constant begins with a non-zero digit, and consists of a sequence of decimal digits. An octal constant consists of the prefix '0' optionally followed by a sequence of the digits '0' to '7' only. A hexadecimal constant consists of the prefix 0x or 0X followed by a sequence of the decimal digits and letters 'a' (or 'A' ) to 'f' (or 'F' ) with values 10 to 15 respectively.

Ou seja: o input 42 é interpretado como 42; o input 042 é interpretado como 34; o input 0x42 é interpretado como 66.


What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
NASG

Obrigado pela tua resposta. eu estive a ler o que disseste e lá tem...

"...Se o valor de base é entre 2 e 36, a forma esperada da seqüência assunto é uma sequência de letras e números que representam um inteiro com o radix especificado pela base, opcionalmente precedido por um '+' ou '-' sinal. As letras de 'A' (ou 'A') a 'z' (ou 'Z'), inclusive, é atribuída os valores 10 a 35; apenas letras cujos valores atribuídos são menos do que o de base são permitidos. Se o valor de base é 16, o 0x caracteres ou 0X pode opcionalmente preceder a sequência de letras e dígitos, após o sinal, se presente..."

Isto não quer dizer que eu possa colocar letras e a instruçõa STRTOL a converte para um inteiro ?

Obrigado

Qual poderia ser a alternativa para que pudesse tambem converter letras para inteiros e os dividir ?

Share this post


Link to post
Share on other sites
pmg

Para leres letras com o strtol() tens que usar uma base diferente de 0. E usando essa base "ficas limitado" a essa base: se meteres base 16, por exemplo, é sempre base 16

strtol("42", NULL, 0);    // 42
strtol("042", NULL, 0);   // 34
strtol("0x42", NULL, 0);  // 66
strtol("42", NULL, 16);   // sempre 66
strtol("042", NULL, 16);  // sempre 66
strtol("0x42", NULL, 16); // sempre 66

strtol("42", NULL, 8);    // 34
strtol("042", NULL, 8);   // 34
strtol("0x42", NULL, 8);  // erro (x nao pode ser usado com base 8)
strtol("42", NULL, 10);   // 42
strtol("042", NULL, 10);  // 42
strtol("0x42", NULL, 10); // erro (x nao pode ser usado com base 10)

Se quiseres ler tanto com base 10 como com base 16, dependendo da existencia de letras no input, a minha sugestão é que experimentes primeiro com base 10. Se funcionar aceita o valor; se não funcionar experimenta com base 16.

/* NAO TESTADO */
char input[] = "4a";
char *err;
errno = 0;

a = strtol(input, &err, 10);
if ((errno == 0) && (*err == '\0')) {
   /* usa a */
} else {
   errno = 0;
   b = strtol(input, &err, 16);
   if ((errno == 0) && (*err == '\0')) {
       /* usa b */
   } else {
       /* input invalido */
   }
}

Edited by pmg
codigo para base 10 e 16

What have you tried?

Não respondo a dúvidas por PM

A minha bola de cristal está para compor; deve ficar pronta para a semana.

Torna os teus tópicos mais atractivos e legíveis usando a tag CODE para colorir o código!

Share this post


Link to post
Share on other sites
HappyHippyHippo

so uma nota :

printf("Deve digitar na forma ./my_divisao num1, num2 e num2 nao pode ser=0 !!\n ");

andas a colocar uma virgula como separador dos parâmetros da chamada da aplicação ?


IRC : sim, é algo que ainda existe >> #p@p

Share this post


Link to post
Share on other sites
NASG

Bom dia,

esta a funcionar para caracteres de letras com a escala no strtol selecionada para 36, ou seja aceita caracteres de a a z.

Cumprimentos e Obrigado pela ajuda

Share this post


Link to post
Share on other sites
NASG

Não, vou alterar isso, realmente não tem loigica porque para passar os parametros, não uso virgula.

Obrigado

Share this post


Link to post
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

×

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.