16

I would like to know if there is a way in C to overwrite an existing value that has already been printed instead of creating a new line every time or just moving over a space. I need to obtain real time data from a sensor and would like it to just sit there and keep updating the existing values without any scrolling. Is this possible?

UPDATE: ADDED CODE

#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdint.h>
#include <time.h>

#include <wiringPi.h>
#include <wiringPiI2C.h>

#define CTRL_REG1 0x20
#define CTRL_REG2 0x21
#define CTRL_REG3 0x22
#define CTRL_REG4 0x23


int fd;
short x = 0;
short y = 0;
short z = 0;
int main (){



    fd = wiringPiI2CSetup(0x69); // I2C address of gyro
    wiringPiI2CWriteReg8(fd, CTRL_REG1, 0x1F); //Turn on all axes, disable power down
    wiringPiI2CWriteReg8(fd, CTRL_REG3, 0x08); //Enable control ready signal
    wiringPiI2CWriteReg8(fd, CTRL_REG4, 0x80); // Set scale (500 deg/sec)
    delay(200);                    // Wait to synchronize

void getGyroValues (){
    int MSB, LSB;

    LSB = wiringPiI2CReadReg8(fd, 0x28);
    MSB = wiringPiI2CReadReg8(fd, 0x29);
    x = ((MSB << 8) | LSB);

    MSB = wiringPiI2CReadReg8(fd, 0x2B);
    LSB = wiringPiI2CReadReg8(fd, 0x2A);
    y = ((MSB << 8) | LSB);

    MSB = wiringPiI2CReadReg8(fd, 0x2D);
    LSB = wiringPiI2CReadReg8(fd, 0x2C);
    z = ((MSB << 8) | LSB);
}
    for (int i=0;i<10;i++){
    getGyroValues();
    // In following Divinding by 114 reduces noise
    printf("Value of X is: %d\r", x/114);
//  printf("Value of Y is: %d", y/114);
//  printf("Value of Z is: %d\r", z/114);
    int t = wiringPiI2CReadReg8(fd, 0x26);
    t = (t*1.8)+32;//convert Celcius to Fareinheit
    int a = wiringPiI2CReadReg8(fd,0x2B);
    int b = wiringPiI2CReadReg8(fd,0x2A);
//  printf("Y_L equals: %d\r", a);
//  printf("Y_H equals: %d\r", b);
    int c = wiringPiI2CReadReg8(fd,0x28);
    int d = wiringPiI2CReadReg8(fd,0x29);
//  printf("X_L equals: %d\r", c);
//  printf("X_H equals: %d\r", d);
    int e = wiringPiI2CReadReg8(fd,0x2C);
    int f = wiringPiI2CReadReg8(fd,0x2D);
//  printf("Z_L equals: %d\r", e);
//  printf("Z_H equals: %d\r", f); 

//  printf("The temperature is: %d\r", t); 
    delay(2000);
}
};
Yamaha32088
  • 3,656
  • 8
  • 36
  • 84

8 Answers8

27

You should add \r to your printf as others have said. Also, make sure you flush stdout, as stdout stream is buffered & will only display what's in the buffer after it reaches a newline.

In your case:

for (int i=0;i<10;i++){
    //...
    printf("\rValue of X is: %d", x/114);
    fflush(stdout);
    //...
}
Zaxter
  • 2,539
  • 3
  • 24
  • 44
26

You're looking for a carriage return. In C, that's \r. This will take the cursor back to the start of the current line without starting a new line (linefeed)

Yaniv
  • 981
  • 6
  • 13
  • 2
    One interesting problem would be if the new line to be printed is shorter than the previously printed line. In this case, there will be some part of the previous line also visible on the screen. – Ganesh Mar 04 '13 at 00:03
  • 1
    @Ganesh Then just print an additional whitespace for every char. –  Mar 04 '13 at 00:06
  • 1
    @Armin Yes that is a solution.The program would have to know the string length and subsequently do some math to add spaces to make it look proper. The challenge is if there is any other way to effectively `flush` the line. – Ganesh Mar 04 '13 at 00:12
  • I have updated my question and added code I am not getting any kind of output when using the `\r` I have commented all other lines except for one inside the `for` loop but all I will get is a blinking cursor – Yamaha32088 Mar 04 '13 at 00:17
  • 1
    @Yamaha32088 try putting the `\r` at the beginning of the `printf` string rather than at the end of it. It's possible that the carriage return is wiping the line on your terminal. – Yaniv Mar 04 '13 at 00:19
  • @Yamaha32088 - you also need a `fflush` as noted by Zaxter below. – BeeOnRope Nov 08 '16 at 17:52
5

You can do it by using "\r" instead of "\n".

Gorbag
  • 233
  • 1
  • 8
3

Printed where?

If your are outputting data to the standard output, you can't generally come back and change anything that has already been written. If your standard output is directed to terminal, you can try outputting \r character that will move the cursor to the beginning of the line on some terminals (the effect is platform-dependent), so that the subsequent output line will overwrite what was printed in that line previously. This will produce a visual effect of old data being replaced with new data. However, this does not really "replace" the old data in the stream, meaning that if you redirect the standard output to file, the file will store everything that was printed. Keep in mind again, that \r will force you overwrite the entire line on the terminal.

If you output your data to a file, then you can use fseek function to go back to some previously visited point and "start over" from there, overwriting the data in the process.

AnT
  • 291,388
  • 39
  • 487
  • 734
1

Have you tested the '\b' character (backspace)? Maybe works depending on your console.

Josh Petitt
  • 8,633
  • 10
  • 50
  • 95
0

You can print out as many newlines as the console screen has. This will effectively clear the screen.

This is a great link about clearing screen in different ways.

-1

Refer to the sample code to understand:

#include <stdio.h>
#include <pthread.h>

void myThread(void* ptr) {
    printf("Hello in thread\n");
    int i=0;    
    for(;i<10;i++)
    {
        sleep(1);
        printf(". ");
        fflush(stdout);  //comment this, to see the difference in O/P
    }
    printf("sleep over now\n");
}

int main(void) {
    pthread_t tid;
    printf("creating a new thread\n");
    pthread_create(&tid, NULL, (void*)myThread, 0);
    printf("going to join with child thread..\n");
    pthread_join(tid, NULL);
    printf("joined..!!\n");
    return 0;
}

Reference Blog

parasrish
  • 3,084
  • 22
  • 28
-3

In addition to answers above, \r is actually a code of the terminal. c seems don't provide a way to change whatever program has already put into stdout stream.

#include<stdio.h>
int main(){
    freopen("output.txt", "w", stdout);
    printf("somthing");
    printf("\r other thing");
}

in output.txt, something doesn't change, cause \r doesn't mean anything for a txt file. But for the terminal, \r is meaningful. It handles format and displays well.

Using terminal codes could do some fun things. like below

#include<iostream>
#include<bits/stdc++.h>
#include<unistd.h>

int main(){
std::string processBar[] {
    "00%: [                     ]",
    "05%: [#                    ]",
    "10%: [##                   ]",
    "15%: [###                  ]",
    "20%: [####                 ]",
    "25%: [#####                ]",
    "30%: [######               ]",
    "35%: [#######              ]",
    "40%: [########             ]",
    "45%: [#########            ]",
    "50%: [##########           ]",
    "55%: [###########          ]",
    "60%: [############         ]",
    "65%: [#############        ]",
    "70%: [##############       ]",
    "75%: [###############      ]",
    "80%: [################     ]",
    "85%: [#################    ]",
    "90%: [###################  ]",
    "95%: [#################### ]",
    "100%:[#####################]",
};

int n = sizeof(processBar)/ sizeof(*processBar);
// pretty fanny
for(int i{0}; i<n; ++i){
    fprintf(stdout, "\e[%d;1H \e[2K \r \a%s", i, processBar[i].c_str());
    fflush(stdout);
    sleep(1);
}

}