Afinal QUAL é a Tabela ASCII Extendida correta?

1. Afinal QUAL é a Tabela ASCII Extendida correta?

Steve
Steve

(usa Slackware)

Enviado em 14/05/2018 - 04:48h

Estou procurando na Internet uma Tabela ASCII Extendida... Mas existem versões diferentes delas, cada uma informa diferente e agora não sei QUAL é a verdadeira!

Tentando saber qual o Código DECIMAL da tecla ç cada lugar informa diferente.
1) Site Aldeia numa boa diz que é 231 (http://www.numaboa.com.br/escolinha/garranchos/146-informatizados/351-ascii)
2) Esse Site também diz que é 231 (http://www.din.uem.br/sica/material/ascii.php)
3) Aqui diz que é 135 (http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf)
4) Aqui também diz 135 (https://desenvolvedorinteroperavel.wordpress.com/2011/09/11/tabela-ascii-completa/)

Então? QUAL Dessas Tabelas ASCII Extendidas está realmente correta?
Se alguém possuir um código pra Linux que informe as Teclas Extendidas eu também agradeceria, pq não consegui imprimir essas teclas e nem dar um retorno delas pra saber seu Cod ASCII, só consigo imprimir ou capturar o cód dos caracteres básicas da Tabela ASCII. Programa em C. no Slackware.


  


2. Depende do sistema operacional e aplicação.

Carlos Vinícius
CarlosVinicius

(usa Debian)

Enviado em 14/05/2018 - 06:57h

No Prompt de comando do Windows em português o ASCII estendido correto é o Code page 850.
https://en.wikipedia.org/wiki/Code_page_850
Ç = 80
ç = 87

No Bloco de notas em português não sei.

Nas distribuições Linux na maioria das vezes o ASCII estendido é o UTF-8.
https://www.utf8-chartable.de/
c3 87 = Ç
c3 a7 = ç


3. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Paulo
paulo1205

(usa Ubuntu)

Enviado em 14/05/2018 - 15:48h

Steve escreveu:

Estou procurando na Internet uma Tabela ASCII Extendida...


Por uma idiossincrasia do Português, o verbo estender, junto com todas as formas conjugadas, é com s, ainda que o substantivo extensão e os adjetivos extenso e extensivo sigam mais fielmente as formas latina extendo (verbo), extentio (substantivo), extensus, extensiuus (adjetivos).

Mas existem versões diferentes delas, cada uma informa diferente e agora não sei QUAL é a verdadeira!


Não existe “a” verdadeira.

Qualquer um pode estender um padrão, inclusive você ou eu. E o padrão original não tem nenhuma obrigação para com as extensões criadas.

ASCII é um padrão que define 128 diferentes caracteres, correspondentes a códigos numéricos inteiros na faixa [0, 127], usando, portanto, sete bits. Desses caracteres, 33 (de 0 a 31, mais o 127) são caracteres de controle, um é o espaço em branco (32), e os demais incluem alguns sinais de pontuação, algarismos indo-arábicos, os 26 caracteres sem marcas diacríticas do alfabeto latino moderno em letras maiúsculas e os 26 correspondentes minúsculos, e alguns outros símbolos de tipografia comuns nas máquinas de escrever de meados do século XX (tais como asteriscos e sinais para gerar texto sublinhado). Qualquer coisa fora disso, quer por alterar um dos caracteres definidos pelo ASCII, quer por usar caracteres acima de 127 (portanto com oito bits ou mais), não é ASCII.

Se alguma coisa pode ser aproximar de extensão oficial de jure do ASCII, essas seriam talvez os padrões de conjunto de caracteres recomendados pela ISO e cujos primeiros 128 caracteres coincidem com os caracteres do ASCII. Os principais desses conjuntos de caracteres são as famílias do ISO-8859, que trazem novos caracteres de controle na faixa de 128 a 159 e caracteres tipográficos entre 160 e 255, e o ISO-10646, mantido em conjunto com o Unicode Consortium. Em particular, antes da adoção do símbolo do Euro (“”), e desprezando-se ligaduras usadas em Francês, tais como “œ” e “Œ”, o ISO-8859-1 (também conhecido como Latin–1) era o conjunto de caracteres de oito bits geralmente mais aceito para comunicação entre sistemas em línguas europeias ocidentais. ISO-10646 e Unicode utilizam o ISO-8859-1 como base para seus primeiros 256 caracteres, mas suplementam esse padrão com até 31 bits para representar caracteres de quase todos os idiomas e sistemas de escrita conhecidos, além de símbolos matemáticos, musicais e decorativos de uso comum.

A adoção de Unicode vem ganhando cada vez mais espaço. Contudo, até hoje são comuns conjuntos de caracteres que suplementam o ASCII de modos particulares, com cada fabricante oferecendo seus próprios modelos. Há também conjuntos de caracteres que não guardam nenhuma relação com ASCII (por exemplo: até hoje mainframes da IBM empregam o conjunto de caracteres particular dessa empresa, conhecido como EBCDIC).

Entre os padrões de facto, existem múltiplos conjuntos de caracteres de oito bits usados pelo PC-DOS/MS-DOS em diferentes combinações geográficas, idiomáticas e culturais. Cada um desses diferentes conjuntos de caracteres recebia uma designação de code[ page, sendo que as code pages mais comuns eram a 437 (Inglês dos EUA, com os códigos de 128 a 255 usados principalmente para símbolos gráficos, desenho de molduras e blocos, e alguns poucos caracteres acentuados para palavras provenientes de outras línguas mas de uso comum nos EUA, tais como façade, naïve ou piñata), a 850 (para línguas europeias ocidentais, e que aumentava a quantidade de caracteres acentuados em detrimento de parte dos caracteres para desenho de molduras e de blocos, além de alguns símbolos gráficos) e, no nosso caso, a 860 (Português, preservando desenho de moldura, blocos e símbolos da CP437, mas substituindo os caracteres acentuados de palavras emprestadas do Inglês pelos acentos comuns em Português). Nenhuma dessas code pages era compatível com o ISO-8859 (e, consequentemente, também não com o Unicode). Como essas CPs eram usadas principalmente em aplicações para o console dos PCs com DOS, os caracteres de 0 a 31 podiam produzir conteúdo gráfico, em lugar dos controles do ASCII, quando escritos diretamente na memória de vídeo, em lugar de usar a impressão feita pelos caminhos normais do sistema operacional.

Com o Windows, outras code pages começaram a ser empregadas. Por se supor que interfaces gráficas poderiam tratar de tarefas como o desenho de molduras e outras decorações, mais espaço foi dedicado para letras acentuadas, ligaduras e sinais e pontuação. Para línguas da Europa Ocidental e Américas, a CP mais comum com o Windows é a CP1252, que é parcialmente compatível com a ISO-8859-1: todos os caracteres imprimíveis da ISO-8859-1 figuram com mesmo código na CP1252, mas os caracteres de 128 a 159, que são de controle na ISO-8859-1, são alocados para caracteres imprimíveis na CP1252, com códigos diferentes, também, do que esses caracteres têm na ISO-10646/Unicode.

Entretanto, o Windows têm uma situação meio obscura: frequentemente a CP usada em aplicações para console não coincide com a CP do ambiente gráfico. Assim, se você digitar um texto em Português no Notepad, e depois usar um programa de console para ler e imprimir o mesmo texto na tela, pode acabar com caracteres estranhos no lugar dos caracteres fora do ASCII.

Tentando saber qual o Código DECIMAL da tecla ç cada lugar informa diferente.


Tecla não tem necessariamente nada a ver com o caráter que ela representa. Além disso, não existe uma forma padronizada de ler teclas, porque o padrão do C imagina um computador genérico, sem se preocupar com periféricos específicos, tais como teclado, tela, mouse ou impressora. Essas coisas, do ponto de vista do C, são detalhes de implementação e, portanto, fora de escopo.

1) Site Aldeia numa boa diz que é 231 (http://www.numaboa.com.br/escolinha/garranchos/146-informatizados/351-ascii)
2) Esse Site também diz que é 231 (http://www.din.uem.br/sica/material/ascii.php)
3) Aqui diz que é 135 (http://iris.sel.eesc.usp.br/sel433a/ASCII.pdf)
4) Aqui também diz 135 (https://desenvolvedorinteroperavel.wordpress.com/2011/09/11/tabela-ascii-completa/)

Então? QUAL Dessas Tabelas ASCII Extendidas está realmente correta?


231 é o código Unicode/ISO-8859-1/CP1252 do caráter “ç” (c-cedilha minúsculo). 135 é seu código nas CP437, CP850 e CP860.

Se a resposta à tecla vai corresponder com algum desses códigos de conjunto de caracteres, vai depender da função usada para ler o teclado. Dependendo do hardware e da nível de abstração (ou falta de abstração), você pode receber diretamente códigos de varredura do teclado, ou mesmo múltiplos bytes produzidos por uma tecla só.

Se alguém possuir um código pra Linux que informe as Teclas Extendidas eu também agradeceria, pq não consegui imprimir essas teclas e nem dar um retorno delas pra saber seu Cod ASCII, só consigo imprimir ou capturar o cód dos caracteres básicas da Tabela ASCII. Programa em C. no Slackware.


Aqui apareceu um pouco mais de contexto, mas ainda falta coisa para apontar uma resposta final.

Como você está tentando ler? Quer que a solução funcione só em modo gráfico, ou também no console de texto? Que locale e conjunto de caracteres você está usando? Pode trabalhar com wide-characters (wchar_t) ou tem de usar apenas char tradicional?


4. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Steve
Steve

(usa Slackware)

Enviado em 14/05/2018 - 20:33h

paulo1205 escreveu: Aqui apareceu um pouco mais de contexto, mas ainda falta coisa para apontar uma resposta final.
Como você está tentando ler? Quer que a solução funcione só em modo gráfico, ou também no console de texto? Que locale e conjunto de caracteres você está usando? Pode trabalhar com wide-characters (wchar_t) ou tem de usar apenas char tradicional?


Primeiramente obrigado também pela aula de português, aprender é sempre importante!
Obrigado também pela AULA sobre ASCII, acredito que agora compreendo melhor essa confusão sobre caracteres e a Tabela ASCII, sua explicação bastante detalhada do assunto me ajuda muito!

A Forma para ler os caracteres para mim é indiferente seja char ou wchar_t (NOVO para mim neste momento)
No Momento estou usando somente o Konsole (KDE) na Interface gráfica do XFCE, no Slackware x64 Current.

Meu Locale atual deste Konsole:
bash-4.4$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE=C
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=

Eu estou estudando a Linguagem C por conta própria, pegando exemplos na Internet, vendo como funcionam, criando pequenos programinhas para testes e ver seus resultados para melhorar seus códigos e aprender mais com eles, reduzindo seus tamanhos e etc... Também estudando essas funções, criando elas sozinhas e analisando seus resultados. Estudando formas diferentes de pegar um texto, escrever ele na tela, analisando seus resultados também.

Ao mesmo tempo que TUDO aquilo que se torna útil e eficiente, SALVO anotado como exemplo pra mim, para que eu possa usar como referências em futuros programas que eu talvez queira desenvolver para mim mesmo!

No Caso da minha dúvida em relação a tabela ASCII eu venho tentando formas diferentes de fazer imprimir ç á (Acentos e tal) E tem sido um fracasso, vou mostrar abaixo o que já tentei fazer:

EXEMPLO I - Programinha que inverte um texto
PROBLEMA: Ao inverter o Texto ele não imprime caracteres acentuados ou ç. Ele coloca um ? no lugar
Sei que o motivo é porque estou usando %c mas não sei o que eu poderia usar no lugar!

#include <stdio.h>
#include <string.h>
void main() {
int x, TamanhoVetor;
char Nome[TamanhoVetor]; //Iniciando uma variável sem definir seu tamanho e permitindo definir depois pelo código

printf("Informe o Texto: ");
scanf("%[^\n]", Nome);

printf("\n A palavra escrita foi: %s", Nome); //Aqui imprime com acentos corretamente
printf("\n A palavra de trás pra frente é: ");

for (x = strlen(Nome) - 1; x >= 0; x--)
printf("%c",Nome[x]); //BUG Aqui ele não imprime corretamente os acentos ele coloca ? no lugar
printf("\n\n");
}


EXEMPLO II - Tentei pegar o Cód da Tecla ASCII mas ele informa errado nesse exemplo também, Sito a ç que entendo que deveria ser 135. Tentei usando char e unsigned char

#include <stdio.h>
void main () {
char Caracter; //Aqui ele informa o ç = -61
// unsigned char Caracter; //Aqui ele informa o ç = 195
//Ao que entendi o ç deveria ser igual a 135
scanf("%c", &Caracter);
printf("O Decimal da tecla %c é: %d\n", Caracter, Caracter);
}


EXEMPLO III - Esse foi o melhor que consegui fazer, mas nesse caso, trata-se de EU informar o código Unicode que encontrei uma tabela em um Site para ser digitado pelo teclado. Ele digita o coração aqui, e ou qualquer outra coisa trocando o código u2665 para de outro caracter que eu escolher

#include <wchar.h>
#include <locale.h>
void main() {
setlocale(LC_ALL, "");
wprintf(L"\u2665\n"); //Tecla &#9829;
}


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);
}


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

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.
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 ç
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

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.

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

Mas isso também ainda estou estudando melhor pra definir o que é melhor de ser usado, eu dei meio que uma pausa sobre essa função.

Obrigado pela Ajuda!


5. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Paulo
paulo1205

(usa Ubuntu)

Enviado em 15/05/2018 - 19:57h

Steve escreveu:

A Forma para ler os caracteres para mim é indiferente seja char ou wchar_t (NOVO para mim neste momento)


De certa forma, é “novo” (apesar de já existir há um bom tempo) para quase todo mundo. Eu acho que nunca vi um programa em C (nem em C++, na verdade) usando wchar_t que não fosse um programa de teste (e a maioria deles feita por mim mesmo).

No Momento estou usando somente o Konsole (KDE) na Interface gráfica do XFCE, no Slackware x64 Current.

Meu Locale atual deste Konsole:
bash-4.4$ locale
LANG=en_US.UTF-8
LC_CTYPE="en_US.UTF-8"
LC_NUMERIC="en_US.UTF-8"
LC_TIME="en_US.UTF-8"
LC_COLLATE=C
LC_MONETARY="en_US.UTF-8"
LC_MESSAGES="en_US.UTF-8"
LC_PAPER="en_US.UTF-8"
LC_NAME="en_US.UTF-8"
LC_ADDRESS="en_US.UTF-8"
LC_TELEPHONE="en_US.UTF-8"
LC_MEASUREMENT="en_US.UTF-8"
LC_IDENTIFICATION="en_US.UTF-8"
LC_ALL=


OK. Você está usando idioma Inglês, com conjunto de caracteres Unicode, codificado como UTF-8 (caracteres são representados em bytes, o que implica que os caracteres de 128 em diante requerem mais de um byte para serem representados).

Eu estou estudando a Linguagem C por conta própria, pegando exemplos na Internet, vendo como funcionam, criando pequenos programinhas para testes e ver seus resultados para melhorar seus códigos e aprender mais com eles, reduzindo seus tamanhos e etc... Também estudando essas funções, criando elas sozinhas e analisando seus resultados. Estudando formas diferentes de pegar um texto, escrever ele na tela, analisando seus resultados também.

Ao mesmo tempo que TUDO aquilo que se torna útil e eficiente, SALVO anotado como exemplo pra mim, para que eu possa usar como referências em futuros programas que eu talvez queira desenvolver para mim mesmo!

No Caso da minha dúvida em relação a tabela ASCII eu venho tentando formas diferentes de fazer imprimir ç á (Acentos e tal) E tem sido um fracasso, vou mostrar abaixo o que já tentei fazer:


Saliento novamente que ASCII não inclui c-cedilha. Felizmente para você, como você mostrou acima, sua locale não se restringe a ASCII, mas você usa Unicode.

EXEMPLO I - Programinha que inverte um texto
PROBLEMA: Ao inverter o Texto ele não imprime caracteres acentuados ou ç. Ele coloca um ? no lugar
Sei que o motivo é porque estou usando %c mas não sei o que eu poderia usar no lugar!
#include <stdio.h>
#include <string.h>
void main() {


Usar void como tipo de retorno de main() é um erro. Se você viu tal erro em alguma apostila, marque tal apostila como deficiente.

O padrão do C define dois tipos de máquinas genéricas capazes de rodar programas em C: máquinas com um um ambiente de execução hospedado (hosted, considerando que existe alguma coisa semelhante a um sistema operacional que efetivamente tem o controle total da máquina, e que pode disparar um programa em C a qualquer momento), e máquinas em que o programa em C executa por conta própria (freestanding, significando que o programa é quem controla a máquina). Nossos PCs com Linux ou Windows são casos de ambientes hospedados.

Em ambientes de execução hospedados, o programa em C deve ser capaz de se comunicar com o ambiente que o executa, e essa comunicação acontece através da função main(). Além disso, a comunicação é nos dois sentidos: o ambiente de execução pode passar argumentos à função na forma de um vetor de strings (onde cada string no vetor corresponde a um argumento diferente), e a função deve devolver um código de retorno inteiro ao ambiente. Isso implica que a função main(), em ambientes hospedados, pode ter uma das seguintes formas:
int main(void)  // Caso o programa não esteja interessado em receber os argumentos do ambiente de execução.

int main(int argc, char **argv)  // Recebe quantidade de argumento argc, que estão contidos nos elementos do vetor argv.


   int x, TamanhoVetor;
char Nome[TamanhoVetor]; //Iniciando uma variável sem definir seu tamanho e permitindo definir depois pelo código


Aqui vai um erro grave. Fazendo desse jeito, você fica com um valor indefinido em TamanhoVetor e usa esse valor indefinido para alocar espaço para o vetor Nome. Se seu programa funcionar, é por puro AZAR (e não sorte — sorte seria se você visse que dá erro e, então, tratasse de consertar).

   printf("Informe o Texto: ");
scanf("%[^\n]", Nome);

printf("\n A palavra escrita foi: %s", Nome); //Aqui imprime com acentos corretamente
printf("\n A palavra de trás pra frente é: ");

for (x = strlen(Nome) - 1; x >= 0; x--)
printf("%c",Nome[x]); //BUG Aqui ele não imprime corretamente os acentos ele coloca ? no lugar
printf("\n\n");
}


Causa do problema: ao usar a codificação UTF-8, o caráter “ç” ocupa dois bytes, e esses bytes têm de obedecer a um formato específico; como as strings tradicionais do C, com elementos do tipo char (que, apesar do nome, representa apenas um byte, não realmente um caráter) não têm conhecimento a respeito dessa codificação, ao inverter esses bytes a regra de codificação é quebrada, e os dois bytes podem ficar sem sentido.

EXEMPLO II - Tentei pegar o Cód da Tecla ASCII mas ele informa errado nesse exemplo também, Sito a ç que entendo que deveria ser 135. Tentei usando char e unsigned char
#include <stdio.h>
void main () {
char Caracter; //Aqui ele informa o ç = -61
// unsigned char Caracter; //Aqui ele informa o ç = 195
//Ao que entendi o ç deveria ser igual a 135
scanf("%c", &Caracter);
printf("O Decimal da tecla %c é: %d\n", Caracter, Caracter);
}


135 não está na tabela ASCII, porque tal tabela tem todos os índices estritamente menores que 128.

A tabela que você tem de consultar é a tabela da sua locale. No caso, é o Unicode, de modo que o índice que você quer é 231. Contudo, como você está usando uma codificação com quantidade variável de bytes por caráter, tem de transformar esse 231 na sequência de bytes adequada para codificá-lo.

Para ver como transformar um valor de índice na sequência de bytes necessária para o representar, veja, por exemplo, o que diz a Wikipedia (https://en.wikipedia.org/wiki/UTF-8).

EXEMPLO III - Esse foi o melhor que consegui fazer, mas nesse caso, trata-se de EU informar o código Unicode que encontrei uma tabela em um Site para ser digitado pelo teclado. Ele digita o coração aqui, e ou qualquer outra coisa trocando o código u2665 para de outro caracter que eu escolher
#include <wchar.h>
#include <locale.h>
void main() {
setlocale(LC_ALL, "");
wprintf(L"\u2665\n"); //Tecla &#9829;
}


Cuidado com a designação de “tecla”. Você não quis dizer caráter?

Como diz o artigo da Wikipedia que eu indiquei acima, o UTF-8 tem muitas vantagens, entre as quais se destacam a economia de memória para que vai usar majoritariamente caracteres comuns ao ASCII, que ocupam apenas um byte, e letras acentuadas também na parte baixa da tabela, e para sistemas que necessariamente fazem entrada e saída de dados orientadas a bytes.

Entretanto, algoritmos que tenham de manipular caracteres podem ter um mau momento ao tentar realizar operações sobre bytes individuais se tais bytes forem apenas parte de uma estrutura semântica que requer múltiplos bytes apropriadamente ordenados para que o valor semântico seja mantido.

Uma alternativa é desvincular caracteres de bytes de oito bits, passando a usar caracteres que possam manipular conjuntos de caracteres mais amplos. Essa é a razão de ser do tipo wchar_t.

Seu primeiro exemplo provavelmente poderia ser reescrito do seguinte modo.

#include <errno.h>
#include <locale.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>

#define MAX_SIZE 100

int main(void) {
int x;
wchar_t Nome[MAX_SIZE];

setlocale(LC_ALL, ""); // Necessário para que o sistema saiba qual o conjunto de caracteres a usar.

printf("Informe o Texto: ");
if(!fgetws(Nome, MAX_SIZE, stdin)){ // Sempre teste o valor de retorno para saber se leitura foi bem sucedida.
fprintf(stderr, "Erro de leitura: %s.\n", strerror(errno));
return 1; // Sai do programa com código de erro.
}

x=wcslen(Nome); // wcslen() é a equivalente a strlen() quando se usa um vetor de wchar_t.
if(Nome[x-1]==L'\n')
Nome[--x]=L'\0'; // Remove quebra de linha no final da string.

printf("%d wide-characters lidos.\n", x);

printf("\n A palavra escrita foi: %ls", Nome);
printf("\n A palavra de trás pra frente é: ");

while(x-- > 0)
printf("%lc", Nome[x]);
printf("\n\n");

return 0; // Sai do programa indicando sucesso.
}


Mais tarde eu comento o resto da sua mensagem.


6. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Paulo
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.


7. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Carlos Vinícius
CarlosVinicius

(usa Debian)

Enviado em 16/05/2018 - 13:24h

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.


Por que atualizam o padrão da linguagem C se C++ é melhor que C?
Deveriam enterrar a linguagem C, já estamos na revisão C11.
https://en.wikipedia.org/wiki/C11_(C_standard_revision)


8. Re: Afinal QUAL é a Tabela ASCII Extendida correta?

Paulo
paulo1205

(usa Ubuntu)

Enviado em 16/05/2018 - 16:15h

CarlosVinicius escreveu:

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.


Peço desculpa por um esquecimento grave. Existe uma outra boa razão para se preferir C: dar manutenção e fazer mudanças pequenas em um sistema que já está em C.

Por que atualizam o padrão da linguagem C se C++ é melhor que C?
Deveriam enterrar a linguagem C, já estamos na revisão C11.
https://en.wikipedia.org/wiki/C11_(C_standard_revision)


Note que eu não excluo minha colocação original da qualidade de subjetiva — e até tive de fazer uma reparação a ela, acima.

Mas há algumas boas razões para um padrão novo para o C. No caso do padrão de 2011, eis alguns claros pontos positivos:

  • trazer para o nível de linguagem algumas especificações necessárias para programas de baixo nível, tais como definições de alinhamento de dados em memória e comportamento do compilador (em lugar de cada compilador adotar sua própria sintaxe, frequentemente incompatível com a de outros compiladores);
  • desfazer confusões criadas pelo padrão anterior (de 1999);
  • transformar em opcionais certas partes controversas do padrão de 1999 (e que eram usadas como justificativa por alguns fabricantes para manter seus compiladores ainda no padrão de 1990);
  • melhor suporte a Unicode (que não existia em 1990 e não fora devidamente explorado em 1999);
  • modelo de memória para aplicações multithreaded;
  • melhor alinhamento e maior compatibilidade com C++ (finalmente pararam com a picuinha gratuita do comitê do C com relação ao comitê do C++).

Mesmo de acordo com a última revisão de seu padrão, C é uma linguagem muito mais simples do que C++, tanto para quem a usa quanto, principalmente, para quem a implementa. Mas o sentido de “simples”, aqui, não se refere à facilidade de realizar tarefas de programação com a linguagem, mas principalmente à quantidade de elementos que têm de ser aprendidos para se ter domínio da linguagem. No mesmo sentido, Assembly é mais simples que C: a linguagem é bem menos elaborada, o que não significa que seja mais fácil programar um sistema complexo em Assembly do que em C — na verdade, o que frequentemente ocorre é que, quanto mais simples a linguagem, maior é o trabalho manual do programador para realizar tarefas complexas com ela.

C++ não é Java. Nem tudo tem de envolver classes ou programação orientada a objetos. É plenamente possível usar C++ para programação estruturada, quase como se fosse C. E um dos princípios por trás do C++ é que aquilo que você não usa não deve lhe causar ônus. Logo, em princípio, dois programas funcionalmente equivalentes em C e C++ devem ter executáveis muito parecidos, se não idênticos (visto que, em muitas implementações de diversos fabricantes, o compilador em C e o compilador em C++ compartilham grandes partes da infraestrutura de geração de código).

O reverso dessa moeda é que se o meu programa é simples o bastante para ser implementado de modo estruturado em C++, tanto como em C, eu poderia optar por implementá-lo em C, sem ônus relevante de complexidade de código que eu tenha de escrever.

No meu dia-a-dia, eu uso as duas linguagens no desenvolvimento de ferramentas de administração. Se eu antevejo que não vou precisar de nenhuma conveniência do C++, eu fico com C, até porque um dos principais servidores com os quais trabalho não usa Linux, mas uma versão relativamente limitada de um UNIX comercial. Quando, porém, começa a aparecer realocação de memória para todo lado, necessidade de usar arrays associativos, ou execução de operações semelhantes sobre dados ligeiramente diferentes, que são bem modelados por uma hierarquia de classes com funções virtuais, não tenho dúvidas quanto a usar C++. E, às vezes, uso C++ desde o começo só pela conveniência de usar strings mais flexíveis e com uma sintaxe menos arcana.






Patrocínio

Site hospedado pelo provedor HostGator.
Linux banner
Linux banner
Linux banner

Artigos

Dicas

Viva o Android

Tópicos

Top 10 do mês

Scripts