Ir ao conteúdo
  • Cadastre-se
Lhikki

C É possível colorir a saída de um único elemento de um vetor? Se sim, como?

Posts recomendados

Olá, pessoal! Pesquisei bastante sobre o meu problema na internet, mas não achei especificamente o que eu quero.

 

Eu gostaria de saber se, dado um vetor com n elementos, seria possível atribuir uma cor qualquer a UM elemento só (e aí imprimir o vetor inteiro, só que com este elemento colorido).

 

Por exemplo:

 

char vetor[n];
for(i=0; i<n; i++){
	if(vetor[n]=='V'){ //se o elemento for igual a V, por exemplo, mas poderia ser qualquer letra, ou até mesmo um número
    		//Atribui uma cor ao elemento na posição n, mas não imprime ainda
    
    	}else if(vetor[n]=='M'){
        	//Atribui outra cor ao alemento na posição n, mas não imprime ainda
    	}
}
//Aí imprime TODOS os elementos do vetor. O esperado é que, no caso deste exemplo, todos os elementos tenham a cor padrão, exceto os elementos que forem iguais a V ou M

 

Isso é possível?? É possível fazer o que estou querendo ou algo similar a isso?

 

O ideal é que funcione tanto no Linux como no Windows, mas se não puder funcionar no Windows não tem problema (eu preciso que funcione pelo menos no Linux).

 

Agradeço imensamente a quem puder me ajudar!!!

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

C e C++ não tem esse tipo de possibilidade nativamente, para Windows você pode usar bibliotecas que são usadas para desenvolvimento daqueles jogos RPG em modo console.

 

Essa por ex: https://tapiov.net/rlutil/

 

exemp.png.784c610dcf557562028ebaf7392a2447.png

 

Esse código gera o exemplo acima..

 

#include "rlutil.h"
#include <stdlib.h> // for srand() / rand()
#include <stdio.h>
#include "math.h"

#ifndef min
#define min(a,b) (((a)<(b))?(a):(b))
#endif // min

/// Tiles
#define FLOOR 0
#define WALL 1
#define COIN (1 << 1)
#define STAIRS_DOWN (1 << 2)
#define TORCH (1 << 4)

#define MAPSIZE 15

/// Globals
int x, y;
int coins = 0, moves = 0, torch = 30, level = 1;
int lvl[MAPSIZE][MAPSIZE];

/// Generates the dungeon map
void gen(int seed) {
	srand(seed);
	int i, j;
	for (j = 0; j < MAPSIZE; j++) {
		for (i = 0; i < MAPSIZE; i++) {
			if (i == 0 || i == MAPSIZE-1 || j == 0 || j == MAPSIZE-1 ||
			  rand() % 10 == 0) lvl[i][j] = 1;
			else if (rand() % 20 == 0) lvl[i][j] = COIN;
			else if (rand() % 100 == 0) lvl[i][j] = TORCH;
			else lvl[i][j] = 0;
		}
	}
	#define randcoord (1+rand()%(MAPSIZE-2))
	x = randcoord;
	y = randcoord;
	lvl[randcoord][randcoord] = STAIRS_DOWN;
	#undef randcoord
}

/// Draws the screen
void draw() {
	cls();
	locate(1, MAPSIZE + 1);
	setColor(YELLOW);
	printf("Coins: %d\n", coins);
	setColor(RED);
	printf("Torch: %d\n", torch);
	setColor(MAGENTA);
	printf("Moves: %d\n", moves);
	setColor(GREEN);
	printf("Level: %d\n", level);
	locate(1, 1);
	int i, j;
	for (j = 0; j < MAPSIZE; j++) {
		for (i = 0; i < MAPSIZE; i++) {
			if (0); //(i == x && j == y) printf("@");
			else if (abs(x-i)+abs(y-j)>min(10,torch/2)) printf(" ");
			else if (lvl[i][j] == 0) { setColor(BLUE); printf("."); }
			else if (lvl[i][j] & WALL) { setColor(CYAN); printf("#"); }
			else if (lvl[i][j] & COIN) { setColor(YELLOW); printf("o"); }
			else if (lvl[i][j] & STAIRS_DOWN) { setColor(GREEN); printf("<"); }
			else if (lvl[i][j] & TORCH) { setColor(RED); printf("f"); }
		}
		printf("\n");
	}
	locate(x+1, y+1);
	setColor(WHITE);
	printf("@");
	fflush(stdout);
}

/// Main loop and input handling
int main() {
	hidecursor();
	saveDefaultColor();
	gen(level);
	setColor(2);
	printf("Welcome! Use WASD to move, ESC to quit.\n");
	setColor(6);
	anykey("Hit any key to start.\n");
	draw();
	while (1) {
		// Input
		if (kbhit()) {
			char k = getkey();

			int oldx = x, oldy = y;
			if (k == 'a') { --x; ++moves; }
			else if (k == 'd') { ++x; ++moves; }
			else if (k == 'w') { --y; ++moves; }
			else if (k == 's') { ++y; ++moves; }
			else if (k == KEY_ESCAPE) break;
			// Collisions
			if (lvl[x][y] & WALL) { x = oldx; y = oldy; }
			else if (lvl[x][y] & COIN) { coins++; lvl[x][y] ^= COIN; }
			else if (lvl[x][y] & TORCH) { torch+=20; lvl[x][y] ^= TORCH; }
			else if (lvl[x][y] & STAIRS_DOWN) gen(++level);
			// Drawing
			draw();
			// Die
			if (--torch <= 0) break;
		}
	}

	cls();
	resetColor();
	showcursor();

	return 0;
} 

 

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

No windows cada letra num programa de console tem um atributo que dá a cor e a intensidade. No Linux e no MacOS que é Linux que um dia foi Unix não tem esse conceito de console, mas no terminal você controla os atributos em efeito para a próxima letra, como nos '80 quanto o terminal era, digamos, um terminal mesmo. No "novo" terminal do windows 10 é igual ao Unix. E os atributos são controlados por sequências de Escape estilo VT-100

  • Curtir 2

Compartilhar este post


Link para o post
Compartilhar em outros sites

Entendi.

 

Agradeço pelas respostas!

 

Não existiria alguma outra alternativa para fazer algo similar ao que eu quero no terminal do Linux? Talvez alguma biblioteca que ajude nisso ou algo do gênero?

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Não precisa disso se só quer tratar a cor.

 

Na console do Windows

 

Como eu disse, no Unix/Linux/MacOS não tem console, mas no Windows pode usar isso

BOOL WINAPI SetConsoleTextAttribute(
  _In_ HANDLE hConsoleOutput,
  _In_ WORD   wAttributes
);

E ver os parämetros em https://docs.microsoft.com/en-us/windows/console/setconsoletextattribute. ~E trivial.

 

Ou pode usar uma função como essa: 

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

Só pra ficar mais curtinho. E essas constantes

// define para as cores para simplificar
#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

 

Para não ter que usar os números, porque é muito chato. Teste essa função em sua máquina:

void mostra_grade_256_cores()
{
	cls();
	text_color(15, 0);	/* preto sobre branco */
	printf("Gabarito (Frente|Fundo) escrito na linha 5 coluna 10\n");
	printf("    os numeros sao das cores que o windows usa\n\n\n");

	for (int letra = 0; letra < 16; letra += 1)
	{
		for (int fundo = 0; fundo < 16; fundo += 1)
		{
			text_color(letra, fundo);
			printf(" %2d %2d ", letra, fundo);
			text_color(_branco_, _preto_);
			printf("  ");
		}
		text_color(_branco_, _preto_);
		printf(" \n");
	}

Por exemplo. Ela vai mostrar esse gabarito clássico
 

grade.png.c3db1bbe727367b7b304b7e46b9d74a1.png

 

E tem os números das cores pra você escolher e saber o que usar.
 

Claro, os tempos mudaram e os programas de console hoje podem usar não 256 mas 16.7 milhões de cores. Mas isso não é importante eu acho.

E pode até usar pra testar com a versão Linux

 

Unix e as cores no terminal

 

Nos tempos do Unix o terminal era de verdade, um terminal. E quando as core surgiram entraram no mesmo modo de programação dos atributos de vídeo. E é o mesmo modo usado pelo Virtual Terminal no Windows Terminal hoje, no Windows 10 a partir de 2018.

 

Está documentado aqui por exemplo https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences

 

Linux e SGR

 

Para mudar as cores no Linux você usa essas sequências chamadas de SGR --- de Set GRaphics Rendition --- e são coisas mesmo dos velhos tempos. Mas estão aí. E voltando até em alguns casos, devido à migração dos computadores para a nuvem: muitas máquinas agora são virtuais e não tem interface gráfica... Muitas mesmo. E caras.

 

São simples sequências de escape, como se usava naquela época também para programar o cursor e as impressoras (matriciais). Por exemplo ESC [ 31 m seleciona texto com fundo vermelho, ESC[32m escreve em verde, e provavelmente pode combinar com ESC [ 31;32m e escrever em verde sobre vermelho.

 

Tudo é feito assim. Se mandar a letra sai a letra. Se mandar um ESC o terminal fica esperando até receber o comando todo. Lembre-se: era um terminal de verdade... Com teclado e tudo. Veja um ai

vt-100b.thumb.jpg.c45db3074a7f696bf07eabf668f22889.jpg

 

 

 

 

Espero que tenha entendido.

 

Se programar a console assim no Windows seu programa fica absolutamente portável.

 

Não que eu recomende escrever programas em modo texto a menos que paguem bem ou tenha uma boa nota envolvida

 

A programação em si é trivial  e chata.

 

Citação

E entenda que os modelos são diferentes: enquanto no Unix a console era um terminal e a cpu mandava e lia cada letra que ia pra cada terminal, sem memória do que tinha mandado, o Windows tem um "retrato" das ultimas 9100 linhas mostradas na console, com os atributos e tudo.

 

adicionado 5 minutos depois
12 minutos atrás, herbertbahia disse:

eu nunca usei linux mas já ouvir falar que tem a biblioteca  ncurses.h que resolve o seu problema

 

ncurses, sucessora de curses, roda em Windows também. Mas é um jeito de guardar imagens de telas inteiras, janelas na console, e tratar teclado e tal. É como um gerenciador de janelas na console, para terminais em modo texto. 

 

cores e atributos, tipo reverso, sublinhado, amarelo e tal, são tratados por simples sequências de ESCape, as tais SGR, ESC depois [ depois algum comando, como descritos em https://docs.microsoft.com/en-us/windows/console/console-virtual-terminal-sequences ou https://vt100.net/ 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
#include <iostream>

using namespace std;

int main()
{
    int n = 6;
    char vetor[n] = {'V','M','V','M','V','M'};
    for(int i=0; i<n; i++){
        if(vetor[i]=='V'){ //se o elemento for igual a V, por exemplo, mas poderia ser qualquer letra, ou até mesmo um número
    		
    		printf("\033[31m%c", vetor[i]);//Atribui uma cor ao elemento na posição n, mas não imprime ainda
    
    	}else if(vetor[i]=='M'){
    	    printf("\033[32m%c", vetor[i]);
        	//Atribui outra cor ao alemento na posição n, mas não imprime ainda
    	}
    }
    return 0;
}

Veja se isso lhe server. Para fazer funcionar no windows talvez tenha que alterar as configurações do terminal.

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
11 minutos atrás, Flávio Pedroza disse:

char vetor[n] = {'V','M','V','M','V','M'};

 

n deve ser uma constante

adicionado 1 minuto depois

O que significa esse lance de "não imprime ainda"? 

  • Curtir 1

Compartilhar este post


Link para o post
Compartilhar em outros sites
6 horas atrás, arfneto disse:

 

n deve ser uma constante

Sim, tem razão

6 horas atrás, arfneto disse:

 

O que significa esse lance de "não imprime ainda"? 

Isso veio do posto original, quando copiei e colei.

  • Curtir 1
  • Obrigado 1

Compartilhar este post


Link para o post
Compartilhar em outros sites

Crie uma conta ou entre para comentar

Você precisar ser um membro 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...

Aprenda a ler resistores e capacitores

EBOOK GRÁTIS!

CLIQUE AQUI E BAIXE AGORA MESMO!