How to do terminal loading effect on just one line?

Asked

Viewed 2,449 times

4

How can I do a loading effect by refreshing a terminal line when running a program in c?

Example:

carrying...

points are increasing.

I can do this effect in a while loop but just cleaning the screen with the command

system("clear");

I would just like to update a line.

3 answers

5


You can print a CR (\r, Carriage Return, which returns the cursor to the beginning of the line), clear the line and then continue printing its points, as in the example below:

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

void main() {
    printf("Hello world\n");
    for (int i = 0; i < 10; i++) {
        printf("Carregando %d", i);
        for (int j = 0; j < 40; j++) {
            printf(".");
            Sleep(20);
        }
        printf("\r");
        for (int j = 0; j < 60; j++) {
            printf(" "); // apaga a linha anterior
        }
        printf("\r");
    }
    printf("\nGoodbye\n");
}
  • Vlw your implementation helped me base myself. Thank you

3

If you are using Linux (as seems to be the case given your attempt to call clear), an interesting solution* is to use the X-Term commands to clear the screen and move the cursor to row 0 and column 0. For example:

#include <stdio.h>

void cls(void)
{
    printf("\033[2J");   // Limpa a tela
    printf("\033[0;0H"); // Devolve o cursor para a linha 0, coluna 0
}

int main(void)
{
    printf("Esta é uma linha de texto\n");
    cls();
    printf("Esta é uma nova linha de texto\n");
    return 0;
}

If your idea is just to "animate" a loading message, instead of clearing the screen it is more practical and fast to simply move the cursor back to the home column. Here’s an example that animates the dots:

#include <stdio.h>
#include <signal.h>
#include <sys/time.h>

int dots = 1;
void reset();
unsigned int alarm();
void animation(int signo);


int main(void)
{
    printf("\n\n\n\n      Carregando");
    signal(SIGALRM, animation);
    alarm(1);

    while(1)
        getchar();

    return 0;
}

void reset(void)
{
    printf("\033[10D");         /* Move 10 colunas para a esquerda */
    printf("          ");       /* Imprime 10 espaços em branco */
    printf("\033[10D");         /* Move 10 colunas para a esquerda */
}

unsigned int alarm (unsigned int seconds)
{
    struct itimerval old, new;
    new.it_interval.tv_usec = 0;
    new.it_interval.tv_sec = 0;
    new.it_value.tv_usec = 0;
    new.it_value.tv_sec = (long int) seconds;
    if (setitimer (ITIMER_REAL, &new, &old) < 0)
        return 0;
    else
        return old.it_value.tv_sec;
}

void animation(int signo)
{
    signal(SIGALRM, animation);
    alarm(1);

    (void)(signo); /* apenas ignora o parâmetro */

    printf(".");
    dots++;
    if(dots > 10)
    {
        dots = 1;
        reset();
    }
}

Note that this solution does not work on Windows. If you want to use something more standardized to emulate your own terminal, worth evaluating the ncurses (which also has a port for Windows).

* My answer was created with help of this SOEN response.

  • Thanks Luis but the result did not come out as expected here.

  • Not at all. : ) But then it is not clear enough in your question what you really expected. I honestly don’t see why @carlosfigueira’s answer doesn’t fit, since there are virtually no significant differences from it to the one you were wheezing after. It’s unclear what the "problem as i grows".

  • When I found the solution I hadn’t seen the @carlosfigueira response, I had based myself on the link I mentioned in my reply, and as the content of the carlosfigueira is almost the same as what is on the link, I gave the credits to him tbm saying that I basing myself on his, And one more thing, and I decided to answer also with my solution, because it is for linux, and therefore somewhat different, you can see some different functions that without it would not work. So I decided to answer

  • 1

    Regarding when the i is bigger I preciptei when saying about carlos' response, this is only for the content of the link I mentioned.

  • 1

    Okay, I get it, thanks for the clarification. : ) I only asked because if there is something wrong it is important to be corrected so that the content of the question and the answers also serve to help other people besides you.

  • 1

    Vlw @Luiz Vieira, thanks for your help :)

Show 1 more comment

0

I appreciate the answers but it didn’t work with me, I use linux, I tried to adapt, but still the result didn’t come out as intended.

I got it fixed, I adapted it from this code and the @carlosfigueira code, analyzing the link code you can see that there is a problem in it as i increases.

So I had to understand the workings of a printf, the \r and only in this way could I formulate a solution.

The solution is this:

  #include <stdio.h>
  #include <time.h>

  void limpa_linha(void);

  int main (int argc, char **argv){    
     int i, j;

     system ("clear");//limpa tela
     printf ("\n\nCarregando: \n\n");          

     for (i = 0; i <= 100; i++){             
        printf ("%d%%  ", i);      
        fflush (stdout);//garante a escrita de dados imediatamente na tela                  
        //repare mod 10, eu limito a qtd de pontos q serao gerados
        for (j = 0; j < i%10; j++){
           printf(".");
        }  
        fflush (stdout);//garante a escrita de dados imediatamente na tela
        usleep(500000);//função espera por tempo, parametro em microsegundos.
        limpa_linha();                    
     }                 
     printf ("\n\n Fim\n\n");            
     return 0;
  }

  void limpa_linha(){
     int i;//indice do caracter na linha
     int max_caracter=50;//indica o maximo de caracter que a linha pode chegar a ter, para linhas com mt texto, coloque um nmr bem maior
     printf("\r");//retorna para o inicio da linha que pretende reutilizar, isso não limpa a linha, apenas posiciona cursor ao inicio da linha

     //Agora precisamos limpar a linha,
     //substitui todos os caracteres existentes por espaço em branco
     for(i=0;i<max_caracter;i++){
        printf(" ");//vai preenchendo a linha com espaços em branco
     }

     printf("\r");//volta ao inicio da linha , dessa vez ela está em branco.

  }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.