Jump to content

[Duvida] Problemas com Função / Char.


Recommended Posts

Posted (edited)

Boas mais uma vez, preciso novamente da vossa ajuda.

É o seguinte com esta função retorna-me a posição correspondente á letra que eu escolher, ou seja se for um A ela retorna-me um 0.

O problema é quando tento chamar esta mesma função dentro de outra para permitir que um utilizador introduza um CHAR e que esse se transforme num INT (ou seja a posição do char introduzido). não sei se me fiz compreender.

#include <stdio.h>
#include <stdlib.h>
char letras[27] = {'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','\0'};
int Caracteres(char);
int main(void) {

char linha;
int i=0, f;
printf("Linha: ");
scanf("%c",&linha);
f=Caracteres(linha);
printf("Linha: %d",f);
return 0;
}
int Caracteres(char l){
int i;
for (i = 0; i < 27; i++) {
 if (letras[i] == l) {
 return i;
 }
}
}

Esta é a função onde eu chamo a anterior, não coloquei aqui a função inteira porque só a chamo aqui nesta zona.

O problema é que esta função desde que mudei para caracter nem sequer me pede para colocar a Linha, passa-se e crasha mas se for com inteiros funciona perfeitamente.


//Submarino
   if(sub<4){
    printf("\n\nColoque os Submarino\n");
    printf("Digite as coordenadas(EX:Linha: 0 / Coluna:0)\n");

       printf("Linha: "); //Pede a letra

       scanf("%c",&linha); // Guarda a letra

       f=Caracteres(linha);// Aqui chamo a função para ela guardar em f a posição da letra

       l=f-1; // Aqui tiro 1 porque os arrays começam no 0 e o utilizador coloque sempre uma posição acima
      }

não sei se fui explicito o suficiente. Agradeço alguma ajuda, o thoga31 já me safou ontem e esta comunidade tem-me valido. Obrigado a Todos.

Edited by thoga31
GeSHi
Posted (edited)

scanf de caracteres e strings... um clássico de iniciação ao C 😛

Para leres um caracter, tens duas formas:

scanf(" %c", &foo);  // nota o espaço antes de "%c" - indica que deve ignorar certos caracteres, como o Enter de quando indicas a entrada de dados
foo = getchar();     // obtém um caracter e não necessita de Enter, mais usado para chars

Outra coisa, falta-te o 'Z'.

Por fim, essa forma de resolver o problema, é preciso ser mesmo assim ou não te lembras de outra forma?

Edited by thoga31

Knowledge is free!

Posted

em array de char não tens qualquer tipo de necesidade de usar o \0. Este só é utilizado para denotar o final de uma string. A criação de uma função também esta no formulario? se não é apenas mais recursos que vais gastar. por isso tira o \0 mete o tal Z. e faz uma solução mais generica usando o sizeof para saberes o tamanho, de seguida um ciclo com a comparação(o if). e no fim devolves o i. Outra coisa estas a usar também a stdlib mas não estas a usar nenhuma função lá definida, utiliza apenas a stdio 😉

Posted

Bem mais uma vez obrigado, tens sido a minha salvação, isto é para o jogo da Batalha Naval, que é para entregar amanhã 🙂 mas já está feito agora ando a limar todos os pontos fracos. E este problema com Chars já me assolava á bastante tempo 😄 .

Esta foi a forma que encontrei para resolver este problema, não me veio á ideia outra visto que tinha problemas com os Char's lol resolvi fazer uma matriz de inteiros e mascara-la depois na apresentação com Char...

Aproveito só para perguntar eu trabalho em linux com o Eclipse segundo sei o eclipse não gera executaveis, pois não? Qual o programa que eu poderia usar para gerar o meu executável.

Mais uma vez Obrigado.

Obrigado pelos concelhos Mkman vou imediatamente retificar, recursos é o que não preciso gastar quanto menos melhor.

Posted

Assim derrepente deparei-me com um problema, e se o utilizador colocar uma letra minuscula? Já não vai funcionar, existe alguma maneira de comparar para ver se é maiuscula ou minuscula?

E quanto ao compilador, para gerar um executável sabes-me dizer algum, para linux.

Obrigado pela solução que me indicas-te é parecida com a minha, não entendi a utilização do sizeof, o length vai guardar o tamanho em bytes que o array ocupa em memória certo, era com o objectivo de se tornara dinâmico e não dependente do numero de char do array?

Posted (edited)

Hoje vou dar uma solução. Não usei arrays, e tenho em conta as minúsculas. Vê se percebes 😉

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

int main(void) {
  char foo;
  foo = toupper(getchar());
  printf("%d", foo - 'A');
  return 0;
}

Edit: ou então outra mais "kamikaze"

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

int main(void) {
  char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  char c = toupper(getchar());
  char *pos = strchr(alpha, c);
  printf("%d", pos == NULL ? -1 : pos - alpha + 1);
  return 0;
}

Edit2: corrigi o 2º código para lidar com inputs que não sejam letras.

Edited by thoga31

Knowledge is free!

Posted

@thoga31 se ele já estava a ter dificuldade assim comeste lhe o caco. Loki o codigo do thoga tem a ver com a tabela ASCII e faz operações para saber a posição. Como já deves ter percebido chars são representados por numeros inteiros.

Se tens alguma distribuição de linux instalada o gcc já deve vir instalado por default. Tens ainda o clang.

http://pt.wikipedia.org/wiki/ASCII

Posted

@thoga31 se ele já estava a ter dificuldade assim comeste lhe o caco.

Eu sei que dei uma solução mais complexa para o @Loki. No entanto, é interessante ver que há formas de brincar com as características dos chars e das strings. O @Loki pode não perceber agora à primeira vista, mas fica alerta para a existência de tais possibilidades.

Mais, se o @Loki quiser, eu explico com quantas palavras forem necessárias o meu código. Assim talvez até cimente certos conhecimentos que ainda estão meios no ar tipo poeira. Pelo menos foi assim que eu aprendi muita coisa ao longo dos últimos anos: vendo coisas que não compreendia. Incentivava-me a querer saber mais. 🙂

Knowledge is free!

Posted (edited)

@thoga31 : falta a validação dos dados de entrada ...

O meu objectivo não era fazer um programa completo e totalmente seguro etc etc, tenho plena noção que falta a validação do input. Sim, também podia mostrar como isso se faz, mas não considerei prioritário neste tópico.

O essencial são os algoritmos/fórmulas utilizados, e eles estão lá. Portanto, quanto aos algoritmos, enganei-me? É que eu escrevi o código mas nem testei 😛

Edited by thoga31

Knowledge is free!

Posted

Bem nem sei por onde começar, em primeiro por agradecer a todos, 2º realmente se possivel thoga31 explica-me que fiquei a nora... Por ultimo o HappyHippyHippo tem razão isto relaciona-se com o input de dados do teclado.

Mais uma vez vos agradeço, e beber do vosso conhecimento é só brutal...

PS: A segunda do thoga31 então matou-me...

Posted
printf("%d", pos == NULL ? -1 : pos - alpha + 1);

AHAH, vocês metem isto à frente de um iniciado, só posso mesmo imaginar a cara dele a olhar para isto... Faz-me voltar ao meu tempo de Secundário, se visse isto à frente achava que quem o fez devia ser meio avariado 😛 Não é que seja difícil, mas para que nunca viu...

Explicando isto um pouco, é basicamente um if.

a expressão completa (pos == NULL ? -1 : pos - alpha + 1)

equivale a '-1' se 'pos==NULL', senão equivale a 'pos - alpha + 1'

Depois tens o uso da função strchr:

http://linux.die.net/man/3/strchr

Involve apontadores, algo que eu não tenho a certeza de já teres abordado. Basicamente procura-te um caracter dentro da string.

  • Vote 1
Posted (edited)

2º realmente se possivel thoga31 explica-me que fiquei a nora...

PS: A segunda do thoga31 então matou-me...

Uma coisa que te aconselho a veres é apontadores. Digo isto não com base neste tópico mas essencialmente com base no outro. C não vive sem eles, e são parte essencial da programação nesta linguagem.

Passando então a explicar os meus códigos:

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

int main(void) {
  char foo;
  foo = toupper(getchar());
  printf("%d", foo - 'A');
  return 0;
}

Estou a utilizar o método toupper, da biblioteca ctype, que pega no caracter lido com getchar e o transforma na letra maiúscula correspondente.

Em C, um char não é mais do que um número inteiro. Desta forma, podes fazer contas com chars. Cada caracter tem um número que o identifica na Tabela ASCII, e é com base nela que eu trabalhei. Os caracteres alfanuméricos estão todos seguidos, começando no "A" na posição 65 e acabando no "Z" na posição 90. Os caracteres minúsculos estão mais à frente. Vê o link para perceberes 😉

Portanto, para saber que caracter é, o que faço eu? Se eu quero que 'A' seja 0, então 'A'-'A'=0 uma vez que 'A'=65. Se eu quiser a "posição" do 'D', faço 'D'-'A'=3, ou seja, 68-65 uma vez que 'D'=68.

Desta forma, eu subtraio o caracter lido ao 'A', que é o nosso caracter de referência.

O segundo código é mais kamikaze e já tem validação de dados.

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

int main(void) {
  char alpha[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
  char c = toupper(getchar());
  char *pos = strchr(alpha, c);
  printf("%d", pos == NULL ? -1 : pos - alpha + 1);
  return 0;
}

Portanto, eu tenho uma strinh alpha que representa o alfabeto em letras maiúsculas. Mais uma vez, leio um caracter do teclado e transformo-o no seu respectivo caracter maiúsculo.

De seguida, usei a função strchr. Esta função pega numa String e num caracter e procura esse caracter na String. O que esta função retorna não é a posição! Ela retorna o endereço de memória em que está o caracter na String!

Não sei se já viste que uma String pode ser declarada como char s[] e char *s - um apontador. Estranho, não? Não é. Uma String é um array de chars com uma característica particular: deve ter um caracter de terminação, o '\0'. Existe uma panóplia de métodos na biblioteca string que nos facilita trabalhar com estes "meninos".

Desta forma, alpha é um endereço de memória que indica o início de uma String. Uma vez que não defini um tamanho para ela, o compilador trata de o calcular, além de inserir por mim o caracter de terminação '\0' no final (daí eu não o ter escrito).

Ora, o caracter 'A' está (hipoteticamente falando) na posição 1234 da memória, o 'B' no 1235 e por aí em diante. Isto é verdade porque um char tem 1 byte. Se tivesse por exemplo 2 bytes a história mudava de figura: o 'B' estaria 2 posições à frente uma vez que o 'A' estava a ocupar 2 bytes. Mas felizmente este não é o caso aqui, mas convém referir.

Então, o strchr vai-me devolver o endereço do caracter! Se eu inserir 'C', e se alpha começar no endereço 1234, então vou obter o endereço 1236 como resultado.

Como posso fazer cálculos com apontadores, faço pos-alpha que é o mesmo que 1236-1234. Obtenho o resultado pretendido: 2.

Neste caso eu decidi somar 1... por força de hábito 😄

Tu queres que o 'A' seja 0, portanto não é para somar 1.

Aquela sintaxe "marada"... pos == NULL ? -1 : pos - alpha. Este é o único operador ternário do C. Esta é a sua sintaxe:

condicao ? verdade : falso;

E é o equivalente de:

if (condicao)
  verdade;
else
  falso;

A vantagem de usar este operador neste caso é que evito de ter este pequeno comboio:

if (pos == NULL)
  printf("%d", -1);
else
  printf("%d", pos - alpha);

Assim fica mais bonito e prático:

printf("%d", pos == NULL ? -1 : pos - alpha);

Portanto, imagina que o utilizador não premiu uma letra mas sim um número. O número não está em alpha. O que devolve a função? Devolve NULL, ou seja, um apontador para nada.

Ora, se eu obtenho NULL, significa que obtive um input inválido. Neste caso, imprimo um resultado "sem sentido" que indica erro: -1. Não há nenhuma posição negativa, e "-1" é um valor muito tradicional de se usar nestes casos.

Pronto, acho que o principal está aqui. Se alguém quiser acrescentar ou corrigir algo, faça as honras da casa. 😄

@Loki, espero que tenhas aprendido coisas novas. 🙂

Cumprimentos.

Edited by thoga31
  • Vote 1

Knowledge is free!

Posted (edited)

Se alguém quiser acrescentar ou corrigir algo, faça as honras da casa. 😄

é possível executar várias operações dentro de um dos ramos do operador ternário (mesmo que não se use as chavetas) usando o separador de instruções ",". a única coisa que se deverá ter em contra é que o valor rvalue da operação será sempre o valor da última instrução:

int foo() { return 22; }
int bar() { return 23; }

int main() {
 int i = 0, j;

 j = (i == 0 ?
        foo(), i = 10 :
        bar());
 printf("j = %d\n", j); // j = 22

 return 0;
}

int foo() { return 22; }
int bar() { return 23; }

int main() {
 int i = 0, j;

 j = (i == 0 ?
          i = 10, foo() :
          bar());
 printf("j = %d\n", j); // j = 1

 return 0;
}
Edited by HappyHippyHippo
IRC : sim, é algo que ainda existe >> #p@p

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