Ir ao conteúdo
  • Cadastre-se

C problema em centralização em c


yuri_carneiro

Posts recomendados

boa noite sou novo em c e estou desenvolvendo um programa em console application , e gostaria de sabe se exite algum comando ou metodo 

 

para que quando rodasse  o programa  as informações ficariam centralizada  ao centro da tela exemplo

 

igual no word tem a opções  alinha a esquerda e de centralizar gostaria que meu programa centralizasse. tem alguma forma de fazer isso

 

int main() { 

 

  • Amei 1
Link para o comentário
Compartilhar em outros sites

@yuri_carneiro @yuri_carneiro     a linguagem  c  foi criada nos idos de 1972 , e naquela época não havia essas coisas de alinhamentos e e centralizações  não ,  e aí muitos anos depois alguém , usuário , criou uma função  que ele mesmo determinou que se chamasse gotoxy  ,  e com essa função consegue-se posicionar o cursor em qualquer  posição da tela do console , respeitando seus limites , que são  25 linhas com 80 colunas cada uma , e com isso na hora de imprimir nessa tela do console você pode usar essa função  gotoxy  e fazer o alinhamento que quiser  , para esquerda , direita ou centralizar ,  então nesse tópico você pode ver mais sobre esse gotoxy  , aqui chamado de gotoxy_2 , pois segue parâmetros diferentes da original e por isso em programas que usem a função chamada apenas de gotoxy não funcionaria do mesmo jeito causado erros , e talvez você ache útil também a função textcolor , aqui também modificada da original , que creio que seja mais apropriada do que a original , pois numa mesma função pode-se modificar tanto a cor das  letras como também a cor do fundo da tela  :

 

Link para o comentário
Compartilhar em outros sites

Citação

a linguagem  c  foi criada nos idos de 1972 , e naquela época não havia essas coisas de alinhamentos e e centralizações  não ,  e aí muitos anos depois alguém , usuário , criou uma função  que ele mesmo determinou que se chamasse gotoxy  ,  e com essa função consegue-se posicionar o cursor em qualquer  posição da tela do console , respeitando seus limites , que são  25 linhas com 80 colunas cada uma , e com isso na hora de imprimir nessa tela do console você pode usar essa função  gotoxy  e fazer o alinhamento que quiser  , para esquerda , direita ou centralizar ,  então nesse tópico você pode ver mais sobre esse gotoxy  , aqui chamado de gotoxy_2 , pois segue parâmetros diferentes da original e por isso em programas que usem a função chamada apenas de gotoxy não funcionaria do mesmo jeito causado erros , e talvez você ache útil também a função textcolor

 

Então, sobre essas coisas, @devair1010 @yuri_carneiro acho que seria o caso de recorrer a livros e revistas dessa época, ou a pessoas que programavam computadores na ocasião.

 

Não era nada assim

Citação

naquela época não havia essas coisas de alinhamentos e e centralizações  não

 

Pois é, havia e era mais comum do que é hoje. Hoje uma expressão virou de uso comum: "imprimir" virou mostrar algo na tela, e imprimir de fato desapareceu, como se as impressoras não existissem mais. Basta perguntar a algum "moderno programador" para que serve o caracter form-feed, ASCII 12 e vai ver a distância entre eles e os velhos tempos em que control-p imprimia o conteúdo da tela. NA IMPRESSORA. E o FF pula para a próxima página na impressora e então tinha que ter alguém atento --- se chamavam operadores na época e era uma profissão --- porque se um programa começasse a imprimir lixo na impressora e tivesse muitos desses FF uma caixa de papel ia parar do lado errado da impressora em um instantinho :D 
Nos anos 70 a saída de um programa de computador era quase que sempre a impressora. E claro que era muito importante alinhar texto, centralizar os relatórios e preparar as tabelas. A gente até comprava formulários --- sim, papel --- específicos para isso, na verdade. E as impressoras em geral imprimiam linhas de 132 colunas, e a maioria não tinha letras minúsculas. Outro tamanho comum era de 80 colunas e que passou a ser usado também quando começaram a surgir os terminais, já nos anos 80 eu diria. 

As páginas tinham sempre 66 linhas, em alguns casos 88. Veja por exemplo a impressora mãe de todas, a  IBM 1403 Line Printer e vai ver do que estou falando. A folha de papel via de regra tinha 11 polegadas de altura e como se usavam 6 ou raramente 8 linhas por polegada aí está o número de linhas por página. E o papel era o formulário contínuo pre-picotado e de boa qualidade porque as impressoras eram muito rápidas e meio estúpidas na hora de puxar o papel. 600 a 1100 linhas por minuto era um número comum. E como o nome já diz elas imprimiam uma linha inteira de cada vez.

 

Citação

muitos anos depois alguém , usuário , criou uma função  que ele mesmo determinou que se chamasse gotoxy  ,  e com essa função consegue-se posicionar o cursor em qualquer  posição da tela do console , respeitando seus limites , que são  25 linhas com 80 colunas.

 

Não era bem assim, e faz tempo que não é. Veja hoje o padrão: 120 colunas por 40 linhas, mas internamente 120 colunas e 9001 linhas. Sim 9001 linhas e você pode ir para trás e para frente no que está lá.

 

658169954_consolepadrao.png.f85a3d812a63ac2017d52d4d1a8c932d.png

 

Nessa história estão faltando uns 15 anos. Essas funções que vejo toda hora citadas aqui no forum ---  e que eu não conhecia --- foram introduzidas numa biblioteca chamada conio que era fornecida com o compilador C da Borland, turbo C, e que começou a ser vendido em 1987, PARA MS-DOS. Na cola do Turbo Pascal que tinha saído uns dois anos antes com enorme sucesso. Comprei várias licenças desses.

 

Computadores e sistemas operacionais e linguagens de programação nada tem a ver com Windows e DOS. Windows 1.0 saiu em 1985, e se programavam computadores já nos anos 50.

 

Cursor e console são coisas dos anos 80 e os terminais tinham 24 linhas não 25.

 

As referências históricas de terminais importantes foram mesmo a linha IBM-3278 e claro os DEC VT-52 VT-100 e VT-220 de onde vem todas as sequências de comando usadas hoje no Unix e derivados. Usei muito esses :( vou acabar ficando deprimido

vt-100.png.540027b5d1cedf01f4107bed81a84df8.png

 

 

Não seria justo não lembrar que os terminais do Linux se chamam tty por causa dos terminais, TeleTYpe. E o DEC LA36 seria um exemplo perfeito, provavelmente um dos que Dennis Ritchie usou no DEC PDP-8 e depois PDP-11 que usou para desenvolver a linguagem C e o próprio Unix dos '70 em diante. Veja um aí com o formulário de 132 colunas. Usei muito esse.

Ele treinava você a se sentar com cuidado para não pisar no papel e rasgar tudo e ficar todo mundo zoando você enquanto ajustava tudo de novo.

 

la36.thumb.jpg.333885a82331610930c029433991dbd9.jpgIBM-3278.png.1ce098c9a95fefa353b2884bf9b184ca.png

 

 

gotoxy() e textcolor()

Muitas vezes já escrevi e falei sobre isso, mesmo aqui neste forum: essas funções nada acrescentam e não são de fato o modelo de programação recomendado no Windows nos últimos 30 anos. E esse modelo está mudando como eu também já falei aqui. O "novo" terminal do Windows é muito melhor e usa outro modelo de programação, muito embora vá continuar aceitando esse modo antigo para todo o sempre por causa do imenso número de programas que foi criado em torno disso.

 

Porque importa o novo terminal? 

Em especial porque ele é muito, muito mais rápido. Porque? Porque usa novas tecnologias, DirectX como nos games, e a janela da console é processada pela placa de vídeo --- GPU --- e não mais pelas funções do Windows. E trata Unicode nativamente para processar caracteres em qualquer idioma, muito além do super chato suporte aos caracteres acentuados que se tem hoje com as modestas code pages. Bem como emojis e coisas assim. E tabs.

E é compatível com o modo de programação do Unix, de modo que os programas para console do Unix agora podem rodar no Windows.

Diretamente.

Foi escrito em C++ e o código fonte está disponível em https://github.com/microsoft/terminal. Sim, o código do Terminal do Windows é agora de domínio público. O código atual. E o WSL --- sistema que roda Linux no Windows --- também está disponível de graça para rodar no Windows. Na loja do Windows você pode baixar por exemplo Ubuntu 18 e SUSE 15 de graça. E entra em uns 5 segundos ou menos em um computador comum, sem mexer no Windows 10. Sem dual boot, sem máquina virtual, sem grub... 

 

Exemplo

Veja o novo terminal no Windows 10 rodando aquele gabarito que eu postei outro dia com o programa que escrevi para mostrar as combinações de cores da console, mais uma aba com o Ubuntu 18 e outra com o SUSE Linux 15 e ,mais uma console...

20191202-NovoTerminal.thumb.png.1f62ab35771fa91a4d66e71df3f74383.png

 

Documentação da programação da console em Windows

https://docs.microsoft.com/en-us/windows/console/

 

Documentação sobre as mudanças no Terminal sempre está disponível a partir do link na própria tela do Windows. Veja nas propriedades do prompt de comando:

 

1145951527_sobrenovotermINl.png.f01efac71aa1f3d49785085ab9220bb7.png

 

 

Espero que ajude a ilustrar como eram os velhos tempos e como pode ser agora

 

  • Curtir 1
  • Obrigado 1
Link para o comentário
Compartilhar em outros sites

@yuri_carneiro    você já conseguiu resolver ?  olha lá no código daquele tópico tem uma linha lá que está escrito 

gotoxy_2(30,12);/* o 30 é a coluna e o 12 é a linha da tela */

então para você posicionar o que vai escrever no console , aquela tela preta ,  antes de colocar o comando printf , você precisa colocar o gotoxy para que o cursor fique na posição escolhida ,  e as letras ou números ou mesmo os caracteres especiais serão desenhados na tela a partir dessa posição em diante até terminar todos os caracteres que estiverem dentro das aspas duplas do comando printf , e aí se for muitos caracteres eles passarão pela borda direita da tela e começarão a ser desenhados na linha imediatamente de baixo , indo assim até que sejam desenhados todos os caracteres , depois se você quiser imprimir naquela mesma coluna , para que esse novo texto seja centralizado também . você precisa colocar outro gotoxy informado a nova posição como na anterior , e assim vai até escrever tudo que você quiser ,  então poste o código que você está usando para escrever esses textos , pois não posso te dar um código pronto pois é contra as regras do fórum   .

Link para o comentário
Compartilhar em outros sites

1 hora atrás, yuri_carneiro disse:

@devair1010

 

@devair1010 ola boa noite podeira me mada o codigo que você  esta falando

 

Você entendeu o que eu expliquei @yuri_carneiro?

 

De volta ao tópico:

Escrever texto centralizado na tela não tem muito a ver com programação e sim com aritmética. É a mesma coisa que chegar em uma sala para pendurar um quadro na parede: você vai lá e

  • mede a parede
  • mede o quadro
  • faz as contas
  • coloca um prego na posição certa
  • pendura o quadro

 

Como medir a janela da console do Windows? Pergunte ao Windows, 3 linhas: 

     HANDLE    H = GetStdHandle(STD_OUTPUT_HANDLE);
     CONSOLE_SCREEN_BUFFER_INFO        info;
     GetConsoleScreenBufferInfo(H, &info);

Você declara essa variável H para pegar o endereço da console em que seu programa está rodando e declara essa estrutura info aí. Elá é assim, como está no manual:

typedef struct _CONSOLE_SCREEN_BUFFER_INFO
{
  COORD      dwSize;
  COORD      dwCursorPosition;
  WORD       wAttributes;
  SMALL_RECT srWindow;
  COORD      dwMaximumWindowSize;
} CONSOLE_SCREEN_BUFFER_INFO;

Aí você chama essa rotina GetConsoleScreenBufferInfo() e ela faz a gentileza de preencher essa tal info com os valores certos. Isso porque enquanto seu programa está rodando alguém pode ir lá e mudar o  tamanho da console.

 

Não vou explicar tudo de novo como está no manual, mas em resumo

 

wAttributes 

tem os valores de cor das letras e cor de fundo em uso. Se não vai mudar, esqueça

dwSize

tem o tamanho da janela e é bem maior em geral que a que está na tela. Você pode ver nas propriedades da janela do prompt de comando do Windows e em geral é de 120 colunas por 9001 linhas porque assim você pode rolar a janela para textos que já saíram da tela. Veja essa no computador que estou usando agora:

484103064_consolepadrao.png.83ec4d6ddc26f1021f8f6902426b3b6d.png

 

Isso quer dizer que a janela da console tem 40 linhas de 120 colunas no momento

srWindow

Essa é a parte da janela que está na tela no momento e é aí que você vai escrever seu texto, no modo simples de fazer.

 

E essa p$%%a de COORD?

 Bem, assim é como são guardadas as coordenadas na console do windows. Direto do manual:

typedef struct _COORD
{
    SHORT X;
    SHORT Y;
} COORD;

E é só isso: coluna e linha. Sim isso é um porre porque (x,y) é a notação para um gráfico cartesiano por exemplo, com x no eixo horizontal e y na vertical. Só que na tela você espera ver linha e coluna, o contrário.

 

E é só isso.

Em info vem tudo preenchido então antes de escrever você "mede a parede":

    int linhas = info.srWindow.Bottom - info.srWindow.Top + 1; // altura da parede
    int colunas = info.srWindow.Right - info.srWindow.Left + 1; // largura da parede

Se o seu texto está em char* texto:

 

você "mede o quadro"

    int largura = strlen(texto);

E aí calcula onde vai escrever, linha e coluna. "Faz as contas":

    int centroL = linhas / 2; // altura do quadro
    int centroC = colunas / 2 - largura/2; // distancia da margem da parede

"Põe o prego"

    gotoYX(centroL, centroC); // posiciona

Essa rotina gotoYX() não é necessária e acaba atrapalhando, já expliquei isso antes. Mas não vou ficar insistindo. Apenas entenda que ao aceitar usar essa gotoxy() que circula desde os anos 80 vai acabar tendo que toda vez ficar invertendo esses valores, como eu expliquei e o @devair1010 te falou. E vai ficar longe das funções que na verdade fazem o mesmo trabalho e que são o padrão dos programas que você vai encontrar :) fora desses foruns

 

E se a função foi escrita a partir das funções do Windows porque diabo não inverter logo isso e usar linha e coluna? Então vou deixar um exemplo de uma 

void    gotoYX(int linha, int coluna);

que ao menos faz mais sentido porque você passa logo linha e coluna na ordem. É bem simples. Veja:

void    gotoYX(int linha, int coluna)
{
    HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
    static COORD    coord;
    coord.X = coluna; coord.Y = linha;
    SetConsoleCursorPosition(console, coord);
    return;
};    // gotoYX()

Note que a função SetConsoleCursorPostion() é a que movimenta o cursor na console no Windows.

 

"Pendurar o quadro"

    printf("%s", texto); // mostra o texto

Pois é. Só isso. O printf() imprime o texto na posição certa, depois do que a gente calculou

 

Programar a console é complexo e não compensa a menos que seja um curso ou um início de aprendizado OU você não tenha mesmo uma interface gráfica. 

 

Ao usar essas coisas em geral você vai ter que manter uma imagem da tela toda na memória e desenhar a tela de novo toda hora para ter mais controle sobre o que está lá

 

text_color e as cores

como você vê em todo canto nesses forums parece haver uma tendência em manter viva essa função text_color() ou mesmo ressuscitar a mesma na forma de text_color_2() e é uma função besta que você chama com a cor das letras e a cor de fundo que quer usar e ela tem efeito imediato. De onde vem isso? Agora você já sabe: é o valor de wAttributes naquela estrutura info.


Postei um programa que gera um gabarito para esses valores e que você pode copiar. Não sei agora  o tópico mas é só pesquisar no forum o que eu postei nos últimos dias. De todo modo eis as constantes que importam, e uma própria text_color_2() mais resumida que eu escrevi

#define        _preto_            0
#define        _azul_             1
#define        _verde_            2
#define        _ciano_            3
#define        _vermelho_         4
#define        _magenta_          5
#define        _marron_           6
#define        _cinza_claro_      7
#define        _cinza_escuro_     8
#define        _azul_claro_       9
#define        _verde_claro_     10
#define        _ciano_claro_     11
#define        _vermelho_claro_  12
#define        _magenta_claro_   13
#define        _amarelo_         14
#define        _branco_          15

#define textcolor_2( letras,  fundo)       \
    SetConsoleTextAttribute(               \
        GetStdHandle(STD_OUTPUT_HANDLE),   \
        (letras|(fundo<<4))                   \
    )

por exemplo usando isso:

textcolor_2( _vermelho_claro_, _amarelo_ );

Acontece o esperado e passa a escrever em vermelho claro em fundo amarelo.

 

Eis o gabarito de que falei. Pode usar os números direto nessa função depois de escolher no gabarito.

 

ch-191128-gabarito-1010.thumb.png.5e0b93207043a2e04256e1538ff94c4a.png

 

Isso quer dizer que pode escrever em seu programa

textcolor_2( 12,7); para usar vermelho em fundo cinza como está aí acima

 

E como limpar a tela?

Pois é. Quanto você começa a usar essas coisas de cursor para todo lado acaba sendo mais simples reescrever as coisas e então precisa limpar a tela toda hora.

Limpar a tela é a mesma coisa que centralizar o texto. Você vai lá, vê o tamanho da tela e apaga tudo escrevendo espaços na tela inteira. Como o computador é mais rápido que os olhos... Você vai achar que apagou mesmo tudo. No windows você usa aquele comando CLS então faria sentido usar uma função com o mesmo nome. Veja uma:

void    cls()
{    // limpa a tela no windows, do jeito oficial
    CONSOLE_SCREEN_BUFFER_INFO        info;
    HANDLE       H = GetStdHandle(STD_OUTPUT_HANDLE);
    COORD        origem = { 0,0 };
    int          total;
    if (H == INVALID_HANDLE_VALUE) return;
    GetConsoleScreenBufferInfo(H, &info);
    int r = FillConsoleOutputCharacter(H, (TCHAR)' ',
        info.dwSize.X * info.dwSize.Y,
        origem, &total);
    int s = FillConsoleOutputAttribute(
        H, info.wAttributes,
        info.dwSize.X * info.dwSize.Y,
        origem, &total);
    SetConsoleCursorPosition(H, origem);
    return;
};    // cls()

É igualzinho ao caso de escrever no meio da tela: 

  • identifica a console
  • preenche a estrutura com as informações
  • vê o tamanho da tela e as cores em uso
  • chama essas funções FillConsole_xyz aí de cima pra escrever espaços na tela toda e já era.

Um programa de exemplo

Vou mostrar um programa porque estive até procurando e não há um exemplo simples de como fazer algo assim. O programa faz o que já expliquei, mas para ficar mais óbvio tem uma função borda() que desenha uma borda na janela toda usando a letra que você escolher, e uma função mostra() que imprime uma única linha na posição central da tela.

Rode isso em seu computador e volte a escrever para a gente saber se entendeu...

 

main()

int main(int argc, char** argv)
{
    cls();
    borda('*');
    mostra("Bem no meio da tela");
};    // main()

Sim, só isso.

cls() limpa a tela

borda('*')  desenha um asterisco na borda da tela para a gente conferir se está certinho o tamanho

mostra() escreve o texto bem no centro da tela, considerando o tamanho da tela no momento em que você chama a função

 

O resultado

 

exemplo.png.10d994636de67d1483377ec0ae761e2e.png

 

Só isso.Eis o programa de teste

#define			_CRT_SECURE_NO_WARNINGS

#define		_preto_            0
#define		_azul_             1
#define		_verde_            2
#define		_ciano_            3
#define		_vermelho_         4
#define		_magenta_          5
#define		_marron_           6
#define		_cinza_claro_      7
#define		_cinza_escuro_     8
#define		_azul_claro_       9
#define		_verde_claro_     10
#define		_ciano_claro_     11
#define		_vermelho_claro_  12
#define		_magenta_claro_   13
#define		_amarelo_         14
#define		_branco_          15

#define textcolor_2( letras,  fundo)       \
    SetConsoleTextAttribute(	           \
        GetStdHandle(STD_OUTPUT_HANDLE),   \
        (letras|(fundo<<4))	               \
    )

#include <stdio.h>
#include <windows.h>

void	borda(char);
void	cls();
void	gotoYX(int, int);
void	mostra(char);
void	text_color(int, int);


int main(int argc, char** argv)
{
	cls();
	borda('*');
	mostra("Bem no meio da tela");
};	// main()


void		borda(char c)
{	// desenha o caracter c em toda a borda da console
	// para testar os limites. Nao usa a ultima linha
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO		info;

	GetConsoleScreenBufferInfo(H, &info);
	int linhas = 1 - info.srWindow.Top + info.srWindow.Bottom;
	int colunas = 1 + info.srWindow.Right - info.srWindow.Left;
	printf("Buffer: %d linhas, %d colunas em Console Windows\n", info.dwSize.Y, info.dwSize.X);
	printf("Viewport: upper-left: (%d,%d) bottom-right: (%d,%d) = (%d,%d)\n",
		info.srWindow.Top, info.srWindow.Left,
		info.srWindow.Bottom, info.srWindow.Right,
		linhas, colunas
	);
	char* barra = (char*)malloc(1 + sizeof(char) * colunas);
	memset(barra, c, colunas);
	*(colunas + barra) = 0;	// termina a string

	cls();

	gotoYX(0, 0);
	printf("%s\n", barra);

	for (int i = 1; i < linhas - 2; i++)
	{
		gotoYX(i, 0);
		printf("*");
		gotoYX(i, colunas - 1);
		printf("*");
	}

	gotoYX(linhas - 2, 0);
	printf("%s\n", barra);
	free((void*)barra);
	return;
};	// borda()


void		cls()
{	// limpa a tela no windows, do jeito oficial
	CONSOLE_SCREEN_BUFFER_INFO		info;
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD		origem = { 0,0 };
	int			total;
	if (H == INVALID_HANDLE_VALUE) return;
	GetConsoleScreenBufferInfo(H, &info);
	int r = FillConsoleOutputCharacter(H, (TCHAR)' ',
		info.dwSize.X * info.dwSize.Y,
		origem, &total);
	int s = FillConsoleOutputAttribute(
		H, info.wAttributes,
		info.dwSize.X * info.dwSize.Y,
		origem, &total);
	SetConsoleCursorPosition(H, origem);
	return;
};	// cls()


void		gotoYX(int linha, int coluna)
{
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
	static COORD	coord;
	coord.X = coluna; coord.Y = linha;
	SetConsoleCursorPosition(console, coord);
	return;
};	// gotoYX()


void		mostra(char* texto)
{
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO		info;
	GetConsoleScreenBufferInfo(H, &info);
	int linhas = info.srWindow.Bottom - info.srWindow.Top + 1; // altura da parede
	int colunas = info.srWindow.Right - info.srWindow.Left + 1; // largura da parede
	int largura = strlen(texto);
	int centroL = linhas / 2; // altura do quadro
	int centroC = colunas / 2 - largura; // distancia da margem da parede
	text_color(_branco_, _preto_);
	gotoYX(centroL, centroC); // posiciona
	printf("%s", texto); // mostra o texto
	char c = getc(stdin);
	return;
};	// mostra()


void		text_color(int letras, int fundo)
{
	SetConsoleTextAttribute(
		GetStdHandle(STD_OUTPUT_HANDLE),
		letras | (fundo << 4)
	);
}	// text_color

 

  • Curtir 1
  • Obrigado 2
Link para o comentário
Compartilhar em outros sites

@arfneto    muito bom esse código , gostei ,  no Dev c++   4.9.9.2 não quis rodar creio que por que ele usa o compilador gcc , e no codeblocks 16.01 funcionou , ele usa o compilador minGW , mas precisei inserir um " * " , asterisco ,  na declaração do protótipo da função mostra 

void	mostra(char*);

e na função borda comentei o cls; 

GetConsoleScreenBufferInfo(H, &info);
	int linhas = 1 - info.srWindow.Top + info.srWindow.Bottom;
	int colunas = 0 + info.srWindow.Right - info.srWindow.Left;/* zero senão empurra a tela para cima e perde a 1ª linha */
	printf("\n\n  Buffer: %d linhas, %d colunas em Console Windows\n", info.dwSize.Y, info.dwSize.X);
	printf("  Viewport: upper-left: (%d,%d) bottom-right: (%d,%d) = (%d,%d)\n",
		info.srWindow.Top, info.srWindow.Left,
		info.srWindow.Bottom, info.srWindow.Right,
		linhas, colunas
	);
	char* barra = (char*)malloc(1 + sizeof(char) * colunas);
	memset(barra, c, colunas);
	*(colunas + barra) = 0;	// termina a string
    /* de onde veio os Asteriscos da barra ? */
    Sleep(2000);
	//cls();

	gotoYX(0, 0);

pois senão ele passa direto e nem dá para ver o que fez ali ,  e coloquei zero na soma das colunas pois senão empurra a tela para cima e perde se a 1ª linha , e de onde vieram os Asteriscos da barra

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

3 horas atrás, devair1010 disse:

muito bom esse código , gostei ,  no Dev c++   4.9.9.2 não quis rodar creio que por que ele usa o compilador gcc , e no codeblocks 16.01 funcionou , ele usa o compilador minGW , mas precisei inserir um " * " , asterisco ,  na declaração do protótipo da função mostra 

 

O MinGW é o GCC(GNU Compiler Collection) dos sistemas Unix/Linux portado para Windows, a versão do MinGW/GCC usada pelo DevCpp 4.9.9.2 se não me engano é a 3 e no Codeblocks é a 4. O grupo de trabalho do C parece estar parado mas tivemos o C11 em 2007 que atualizou e acrescentou muitos recursos na linguagem e no ano passado saiu a versão C18 com correções e melhorias técnicas. Vale a pena dar uma atualizada nas ferramentas de compilação.

  • Curtir 2
Link para o comentário
Compartilhar em outros sites

    char* barra = (char*)malloc(1 + sizeof(char) * colunas);
    memset(barra, c, colunas);
    *(colunas + barra) = 0;	// termina a string
    /* de onde veio os Asteriscos da barra ? */

@devair1010 A origem dos asteriscos

	borda('*');		//trata-se do argumento

ao chamar

    void    borda(char);

Não são asteriscos. Trata-se do parâmetro c na chamada de memset()

 

:) A verdade sobre o programa

 

Eu escrevi um programa mínimo para mostrar a maneira oficial usando as funções de console do windows. Mas aí a função mostra tinha mais dois parâmetros, um int e um char, e ela desenhava n bordas coloridas com um char em torno da mensagem centralizada na tela.

 

Só que na hora de postar achei muito complicado para um iniciante ler e apaguei essa parte toda. E aí sumiu por exemplo o asterisco no protótipo :D

 

Esses comandos

    printf("\n\n  Buffer: %d linhas, %d colunas em Console Windows\n", info.dwSize.Y, info.dwSize.X);
    printf("  Viewport: upper-left: (%d,%d) bottom-right: (%d,%d) = (%d,%d)\n",
		info.srWindow.Top, info.srWindow.Left,
		info.srWindow.Bottom, info.srWindow.Right,
		linhas, colunas
	);

tinham outro

	char c = getc(stdin);

depois.

 

Então era pra ter apagado TUDO e esqueci desses printf(). Tinha mais na verdade, porque eu mostrava a estrutura info toda porque entender aquilo é essencial para entender como a console funciona no Windows. E Sleep() não serviria porque não se sabe quando tempo o cara vai levar para ler os valores todos. E acho que já sabe que Sleep() não é confiável e pode ser interrompida, o que é algo bem engraçado :D

 

Pode escrever mostra() assim

void		mostra(char* texto)
{
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO		info;
	GetConsoleScreenBufferInfo(H, &info);
	int linhas = info.srWindow.Bottom - info.srWindow.Top + 1; // altura da parede
	int colunas = info.srWindow.Right - info.srWindow.Left + 1; // largura da parede
	int largura = strlen(texto);
	int centroL = linhas / 2; // altura do quadro
	int centroC = colunas / 2 - largura/2; // distancia da margem da parede
	text_color(_branco_, _preto_);
	gotoYX(centroL, centroC); // posiciona
	printf("%s", texto); // mostra o texto
	char c = getc(stdin);
	return;
};	// mostra()

Claro que não precisava dessas variáveis todas mas é um exemplo para iniciantes

 

4 horas atrás, devair1010 disse:

Dev c++   4.9.9.2 não quis rodar creio que por que ele usa o compilador gcc , e no codeblocks 16.01 funcionou , ele usa o compilador minGW , mas precisei inserir um " * " , asterisco ,  na declaração do protótipo da função mostra 

 

O asterisco estava faltando mesmo porque cortei a mais quando apaguei os outros parâmetros quando a mostra() era mais "circense" digamos e escrevia as n bordas coloridas :D . Meu compilador aceitou porque de todo modo ela está declarada depois e o linker acabou resolvendo a referência, mas devia mesmo ter dado erro

 

Eu fiquei curioso por esse lance do compilador de que falou. Isso não pode dar erro em Windows. O que aconteceu? Eu me comprometi a não usar as máquinas Linux e não usar outros compiladores quando comecei a postar neste forum, mas estou quase instalando esse outro. Onde arrumo essa versão se eu resolver instalar isso?

 

O programa de teste de novo

#define			_CRT_SECURE_NO_WARNINGS

#define		_preto_            0
#define		_azul_             1
#define		_verde_            2
#define		_ciano_            3
#define		_vermelho_         4
#define		_magenta_          5
#define		_marron_           6
#define		_cinza_claro_      7
#define		_cinza_escuro_     8
#define		_azul_claro_       9
#define		_verde_claro_     10
#define		_ciano_claro_     11
#define		_vermelho_claro_  12
#define		_magenta_claro_   13
#define		_amarelo_         14
#define		_branco_          15

#define textcolor_2( letras,  fundo)       \
    SetConsoleTextAttribute(	           \
        GetStdHandle(STD_OUTPUT_HANDLE),   \
        (letras|(fundo<<4))	               \
    )

#include <stdio.h>
#include <windows.h>

void	borda(char);
void	cls();
void	gotoYX(int, int);
void	mostra(char*);
void	text_color(int, int);


int main(int argc, char** argv)
{
	cls();
	borda('*');
	mostra("Bem no meio da tela");
};	// main()


void		borda(char c)
{	// desenha o caracter c em toda a borda da console
	// para testar os limites. Nao usa a ultima linha
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO		info;

	GetConsoleScreenBufferInfo(H, &info);
	int linhas = 1 - info.srWindow.Top + info.srWindow.Bottom;
	int colunas = 1 + info.srWindow.Right - info.srWindow.Left;

	char* barra = (char*)malloc(1 + sizeof(char) * colunas);
	memset(barra, c, colunas);
	*(colunas + barra) = 0;	// termina a string

	cls();

	gotoYX(0, 0);
	printf("%s\n", barra);

	for (int i = 1; i < linhas - 2; i++)
	{
		gotoYX(i, 0);
		printf("*");
		gotoYX(i, colunas - 1);
		printf("*");
	}

	gotoYX(linhas - 2, 0);
	printf("%s\n", barra);
	free((void*)barra);
	return;
};	// borda()


void		cls()
{	// limpa a tela no windows, do jeito oficial
	CONSOLE_SCREEN_BUFFER_INFO		info;
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	COORD		origem = { 0,0 };
	int			total;
	if (H == INVALID_HANDLE_VALUE) return;
	GetConsoleScreenBufferInfo(H, &info);
	int r = FillConsoleOutputCharacter(H, (TCHAR)' ',
		info.dwSize.X * info.dwSize.Y,
		origem, &total);
	int s = FillConsoleOutputAttribute(
		H, info.wAttributes,
		info.dwSize.X * info.dwSize.Y,
		origem, &total);
	SetConsoleCursorPosition(H, origem);
	return;
};	// cls()


void		gotoYX(int linha, int coluna)
{
	HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
	static COORD	coord;
	coord.X = coluna; coord.Y = linha;
	SetConsoleCursorPosition(console, coord);
	return;
};	// gotoYX()


void		mostra(char* texto)
{
	HANDLE		H = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_SCREEN_BUFFER_INFO		info;
	GetConsoleScreenBufferInfo(H, &info);
	int linhas = info.srWindow.Bottom - info.srWindow.Top + 1; // altura da parede
	int colunas = info.srWindow.Right - info.srWindow.Left + 1; // largura da parede
	int largura = strlen(texto);
	int centroL = linhas / 2; // altura do quadro
	int centroC = colunas / 2 - largura/2; // distancia da margem da parede
	text_color(_branco_, _preto_);
	gotoYX(centroL, centroC); // posiciona
	printf("%s", texto); // mostra o texto
	char c = getc(stdin);
	return;
};	// mostra()


void		text_color(int letras, int fundo)
{
	SetConsoleTextAttribute(
		GetStdHandle(STD_OUTPUT_HANDLE),
		letras | (fundo << 4)
	);
}	// text_color

 

  • Curtir 1
Link para o comentário
Compartilhar em outros sites

6 horas atrás, devair1010 disse:

pois senão ele passa direto e nem dá para ver o que fez ali ,  e coloquei zero na soma das colunas pois senão empurra a tela para cima e perde se a 1ª linha , e de onde vieram os Asteriscos da barra

 

@devair1010 :D acho que entendeu que não era pra ver mais o que faz ali. Eu tinha apagado uma boa parte do código e esqueci essas linhas. Achei difícil de ler. Acho que sabe de onde vem os asteriscos agora.

 

Não disse o que acontece com esse outro compilador... O que passa afinal?

 

Isso não deveria ter diferença em Windows. Como sabe eu postei uma tela do resultado.

Mas isso é mesmo um inferno mesmo, programas para a console no Windows. E um inferno no Linux, ou quase, porque não tem console nem nada. E já foi muito pior até o Unix criar o terminfo.

Pode depender no Windows de como a console está configurada, ou da particular versão de Windows, mas não deveria fazer diferença o compilador.

Como eu já disse aqui sobre esses programas, é muito melhor usar o novo terminal do windows, que é mais confiável e usa a aceleração da placa de vídeo

Link para o comentário
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisa ser um usuário para fazer um comentário

Criar uma conta

Crie uma nova conta em nossa comunidade. É fácil!

Crie uma nova conta

Entrar

Já tem uma conta? Faça o login.

Entrar agora

Sobre o Clube do Hardware

No ar desde 1996, o Clube do Hardware é uma das maiores, mais antigas e mais respeitadas comunidades sobre tecnologia do Brasil. Leia mais

Direitos autorais

Não permitimos a cópia ou reprodução do conteúdo do nosso site, fórum, newsletters e redes sociais, mesmo citando-se a fonte. Leia mais

×
×
  • Criar novo...