paulo1205
(usa Ubuntu)
Enviado em 16/05/2018 - 12:53h
Steve escreveu:
Esses exemplos eu guardo, pq podem ser úteis no futuro em alguma coisa. Mas o que eu gostaria seria mesmo imprimir a tabela ASCII com todos os seus caracteres nela imprimíveis, como o ç = 135 | Eu precisei parar no 126 pq a partir dai não imprime mais corretamente.
Um Exemplo que tenho para listar a tabela ASCII é:
#include <stdio.h>
void main () {
for (int i = 32; i <= 126; i++)// Imprimo do 32 até o 126 da Tabela ASCII (Que são todos os caracteres imprimiveis)
printf("%c - %d\n", i, i);
}
Conforme eu mostrei na mensagem anterior, você tem de começar definindo a locale em uso, e depois você deve imprimir o dado do tipo
wchar_t , por meio da conversão
"%lc" , em lugar de apenas
"%c" .
Tenho tentando fazer isso somente pelo Konsole conforme expliquei. Estou usando o Kate para programar (Pois uso outras funções dele para uso meu também) Possuo o Eclipse C/C++ instalado mas quase não uso, pois através dele em seu DEBUG que pude entender o valor das variáveis char como elas eram salvas exemplo: 72 'H'
Compilo sempre de forma básica pelo terminal o arquivo.c usando apenas gcc nome_arquivo.c nem uso complementos do tipo -o ou -Wall ou coisas do tipo, uso bem simples mesmo! E rodo pelo terminal usando ./a.out que costuma ser o arquivo compilado
Quando eu perguntei sobre onde você deseja que o programa execute, foi porque todos esses resultados dependem do ambiente em que o programa é executado. Eu não tenho certeza de que um programa preparado para usar Unicode funcione no console de texto do Linux (i.e. com ambiente gráfico totalmente desligado), e muito menos num terminal serial. Quanto mais genérico você quiser ser, menos recursos vai poder usar.
Esse sistema de não ter Strings em C é novo para mim, e antes eu achava que guardava somente o texto mesmo, descobri o que é um char através das respostas que me deram aqui no VOL e ainda estou anotando resultados de variáveis char, como melhor declará-las seus funcionamentos e etc...
No Momento, meu Objetivo final inicial é montar um sistema simples de criptografia, onde eu leio um texto grande e criptografo ele, já tenho idéias prontas de como vou fazer, mas esse problema com caracteres acentuados e ç atrapalharia o funcionamento do meu pequeno programa de criptografia.
Você vai fazer criptografia baseada em caracteres? Porque o comum é ter criptografia baseada em bytes, independentemente do sentido ou do encadeamento desses bytes.
Tenho usado para ler Textos no Terminal o comando: scanf("%[^\n]", Texto);
Pois esse comando pega os textos corretamente e coloca na variável corretamente, acentos e ç
Não conheço detalhes de funcionamento de
scanf () com caracteres largos, nem se você poderia colocar um caráter não-ASCII como argumento da conversão
"%[" — ainda mais quando se deixa de usar
setlocale () para instruir o programa a considerar a locale do seu ambiente, como você mesmo deixou de fazer.
Como você viu no exemplo acima, eu achei mais seguro usar
fgetws (), e, mesmo assim, somente depois de usar
setlocale ().
Imprimo na Tela do Terminal assim: printf("O Nome armazenado foi: %s\n", Nome);
Ele imprime corretamente TODOS os caracteres acentuados e com ç
Entendi que funciona porque uso o %s para imprimir = String
Pois é, mas isso aconteceu porque nem
scanf () nem, depois,
printf () tentaram interpretar os bytes recebidos. Conforme já vimos, como você usa UTF-8, um glifo fora do ASCII consome mais de um byte. Quem converteu o c-cedilha em dois bytes na hora da leitura, e depois os dois bytes de volta num único símbolo na tela foi o emulador de terminal, não foi o seu programa.
Você pode confirmar isso. Se você fizer algo como “
int n=strlen("ç"); ” num sistema configurado como UTF-8, é bem provável que
n receba o valor 2, não 1. Se mandar imprimir o tamanho de uma
string lida que contenha acentos, verá que o tamanho impresso deve ser maior que a quantidade de caracteres que aparecem na tela.
Já disse isso numa outra mensagem (em outro tópico, se não me engano), mas repito: o fato do tipo de dados do C se chamar “
char ” não significa que ele e capaz de representar todos os caracteres imagináveis (ou aqueles que nossos micros podem imprimir). Esse nome é uma relíquia de uma época em que a palavra
byte ainda não tinha sentido claro de ser sempre um conjunto de exatamente oito bits, e de quando esse conjunto de oito bits, que era a menor quantidade endereçável do computador onde o C foi criado e, ao mesmo tempo, era suficiente para representar ASCII, que era o conjunto de caracteres que tal computador e seus periféricos usavam. Mais ainda, como os terminais desse computador eram impressoras com mecanismos semelhantes aos das antigas máquinas de escrever, se alguém quisesse imprimir uma letra
a com acento agudo, ele imprimia um apóstrofo, seguido do caráter de controle
backspace , e depois imprimia a letra
a na mesma posição do papel em que o apóstrofo já estava impresso. Ninguém ali via muita necessidade de ter um caráter só para poder imprimir “
á ”.
O Problema é que pensei em usar algo como printf("%c",Nome[x]); com um laço para trocar os caracteres entende? E não vou conseguir fazer isso com acentos e ç.
Então estou estudando uma forma de entender e fazer funcionar corretamente a captura do texto colocar ele numa variável temporária mas com seus valores corretos, trabalhar esse texto e enviar para tela, sem ele aparecer ? no lugar do texto! kkkkkkk
Então pensei: Eu aprendendo a imprimir na tabela ASCII ou trabalhar com isso corretamente, eu poderei fazer mais. Afinal sou Brasileiro e aqui usamos acentos e ç!
Você fala wide-characters (wchar_t) isso é novidade pra mim, nunca mechi nesse novo TIPO e nem sabia de sua existencia se tiver um exemplo e se ele trabalha bem com ç é legal pra mim. Peço apenas que seja em C Puro, sem código de C++ pq quero conhecer o C primeiro, dominar bem a Linguagem C, para depois me dedicar a Linguagem C++ no futuro caso eu for precisar dela, por enquanto, inclusive no futuro qdo eu dominar melhor o Terminal, ainda vou escrever depois para o X usando C ainda.
Eu não sei o que motivou você a fazer essa escolha, mas, embora a respeite, discordo dela. Para mim, a única boa justificativa para se preferir C a C++ num caso geral é se você quiser que seu programa possa ser levado para uma máquina que não disponha de C++, mas, por óbvio, tal justificativa não se aplica aos nossos PCs, quer rodem Windows, quer Linux, quer qualquer outro UNIX. De resto, a maioria das outras justificativas que conheço, por mais elaboradas que sejam, acabam recaindo em gosto pessoal, que passa longe de ser um critério objetivo.
O próprio tratamento de caracteres acaba sendo melhor em C++ do que C. Desde primeiro padrão publicado para o C++ (em 1998),
wchar_t sempre foi um tipo de pleno direito, distinto de qualquer outro tipo. Em C, no entanto, ele é apenas um apelido de
int , que nem ao menos é definido se não se incluir o cabeçalho <wchar.h> (eu deveria, inclusive, escrever
wchar_t , em vez de
wchar_t ). E mesmo o vetusto tipo
char é tratado de modo melhor em C++ do que em C. Sabia que, em C, o tipo de uma constante de caráter, na forma “
'C' ”, não é
char , mas sim
int , do mesmo modo que a constante de caracteres largos, na forma “
L'C' ”? No C++, essa confusão não existe: constantes de caracteres são do tipo
char , e constantes de caracteres largos são do tipo
wchar_t , ambas distintas do tipo
int , mas podendo ser convertidas para
int .
No padrão de 2017, o C++ deu um passo além e introduziu o tipo
byte . Eu não gostei muito da forma como foi definido, mas pode ser um passo para eliminar a parte da relíquia histórica de usar
char para representar valores numéricos de 8 bits.
Não estou fazendo um Curso de C, pq não posso pagar, então estou estudando lendo Livros e Apostilas, e estudando os exemplos que encontro na Internet em Sites que oferecem material de estudo gratuito, vejo um exemplo legal, baixo, limpo seu código com o que aprendi, testo pra entender melhor, modifico pra entender melhor, e escolhe no fim qual a melhor forma que usarei.
Exemplo disso, é que até então eu decidi usar a main por exemplo assim:
void main () {
}
Motivo é que pensei: Porque usaria INT? Se não preciso de um retorno de nada? assim fica um comando a menos dentro da minha função, ou seja não tenho que escrever sempre return 0;
Coloquei void no início, também pra evitar reclamação do gcc
Já comentei um pouco sobre isso, que você possivelmente viu em algumas das apostilas obsoletas que viu na Internet ou livros desatualizados. Isso nunca foi válido.
E mais: o GCC não reclama disso porque você, como disse acima, não usou nenhuma das opções de diagnóstico recomendadas para diagnóstico de código com erros que vão além do que a sintaxe estrita, mas incluem aspectos que envolvem escolhas de plataforma e até aspectos semânticos.
Experimente compilar, antes de fazer qualquer correção, um desses programas com as seguintes opções do GCC:
-pedantic-errors -O2 (e talvez, também,
-std=c11 ). Diga qual o resultado.