Saya telah mencari cara untuk mendapatkan lebar terminal dari dalam program C saya. Apa yang terus saya temukan adalah sesuatu di sepanjang baris:
#include <sys/ioctl.h>
#include <stdio.h>
int main (void)
{
struct ttysize ts;
ioctl(0, TIOCGSIZE, &ts);
printf ("lines %d\n", ts.ts_lines);
printf ("columns %d\n", ts.ts_cols);
}
Tapi setiap kali saya mencoba itu saya dapatkan
austin@:~$ gcc test.c -o test
test.c: In function ‘main’:
test.c:6: error: storage size of ‘ts’ isn’t known
test.c:7: error: ‘TIOCGSIZE’ undeclared (first use in this function)
test.c:7: error: (Each undeclared identifier is reported only once
test.c:7: error: for each function it appears in.)
Apakah ini cara terbaik untuk melakukan ini, atau adakah cara yang lebih baik? Jika tidak, bagaimana saya bisa membuat ini bekerja?
EDIT: kode tetap adalah
#include <sys/ioctl.h>
#include <stdio.h>
int main (void)
{
struct winsize w;
ioctl(0, TIOCGWINSZ, &w);
printf ("lines %d\n", w.ws_row);
printf ("columns %d\n", w.ws_col);
return 0;
}
Jawaban:
Sudahkah Anda mempertimbangkan untuk menggunakan getenv () ? Ini memungkinkan Anda untuk mendapatkan variabel lingkungan sistem yang berisi kolom dan baris terminal.
Sebagai alternatif menggunakan metode Anda, jika Anda ingin melihat apa yang dilihat kernel sebagai ukuran terminal (lebih baik jika terminal diubah ukurannya), Anda perlu menggunakan TIOCGWINSZ, sebagai lawan TIOCGSIZE Anda, seperti:
struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
dan kode lengkapnya:
#include <sys/ioctl.h> #include <stdio.h> #include <unistd.h> int main (int argc, char **argv) { struct winsize w; ioctl(STDOUT_FILENO, TIOCGWINSZ, &w); printf ("lines %d\n", w.ws_row); printf ("columns %d\n", w.ws_col); return 0; // make sure your main returns int }
sumber
ws_xpixel
danws_ypixel
, Tapi itu hanya mencetak nol!Contoh ini agak panjang, tetapi saya yakin ini adalah cara paling portabel untuk mendeteksi dimensi terminal. Ini juga menangani acara pengubahan ukuran.
Seperti yang disarankan tim dan rlbond, saya menggunakan ncurses. Ini menjamin peningkatan besar dalam kompatibilitas terminal dibandingkan dengan variabel lingkungan membaca secara langsung.
#include <ncurses.h> #include <string.h> #include <signal.h> // SIGWINCH is called when the window is resized. void handle_winch(int sig){ signal(SIGWINCH, SIG_IGN); // Reinitialize the window to update data structures. endwin(); initscr(); refresh(); clear(); char tmp[128]; sprintf(tmp, "%dx%d", COLS, LINES); // Approximate the center int x = COLS / 2 - strlen(tmp) / 2; int y = LINES / 2 - 1; mvaddstr(y, x, tmp); refresh(); signal(SIGWINCH, handle_winch); } int main(int argc, char *argv[]){ initscr(); // COLS/LINES are now set signal(SIGWINCH, handle_winch); while(getch() != 27){ /* Nada */ } endwin(); return(0); }
sumber
man 7 signal
OK
danERR
. Betapa "baik" mereka untuk membantu kita mengisi celah itu dalam hidup kita :-(#include <stdio.h> #include <stdlib.h> #include <termcap.h> #include <error.h> static char termbuf[2048]; int main(void) { char *termtype = getenv("TERM"); if (tgetent(termbuf, termtype) < 0) { error(EXIT_FAILURE, 0, "Could not access the termcap data base.\n"); } int lines = tgetnum("li"); int columns = tgetnum("co"); printf("lines = %d; columns = %d.\n", lines, columns); return 0; }
Perlu dikompilasi dengan
-ltermcap
. Ada banyak informasi berguna lainnya yang bisa Anda peroleh dengan menggunakan termcap. Periksa manual termcap menggunakaninfo termcap
untuk lebih jelasnya.sumber
Jika Anda telah menginstal ncurses dan menggunakannya, Anda dapat menggunakan
getmaxyx()
untuk mencari dimensi terminal.sumber
Dengan asumsi Anda menggunakan Linux, saya rasa Anda ingin menggunakan pustaka ncurses sebagai gantinya. Saya cukup yakin barang ttysize yang Anda miliki tidak ada di stdlib.
sumber
ioctl
caranya lebih sederhana dan lebih bersih, karena Anda tidak perlu menginisialisasi kutukan, dll.Jadi tidak menyarankan jawaban di sini, tetapi:
linux-pc:~/scratch$ echo $LINES
49
linux-pc:~/scratch$ printenv | grep LINES
linux-pc:~/scratch$
Ok, dan saya perhatikan bahwa jika saya mengubah ukuran terminal GNOME, variabel LINES dan COLUMNS mengikutinya.
Agaknya terminal GNOME membuat variabel lingkungan ini sendiri?
sumber
Untuk menambahkan jawaban yang lebih lengkap, apa yang menurut saya berhasil untuk saya adalah menggunakan solusi @ John_T dengan beberapa bit yang ditambahkan dari Rosetta Code , bersama dengan beberapa pemecahan masalah yang mencari tahu dependensi. Ini mungkin sedikit tidak efisien, tetapi dengan pemrograman cerdas Anda dapat membuatnya bekerja dan tidak membuka file terminal Anda sepanjang waktu.
#include <stdio.h> #include <stdlib.h> #include <sys/ioctl.h> // ioctl, TIOCGWINSZ #include <err.h> // err #include <fcntl.h> // open #include <unistd.h> // close #include <termios.h> // don't remember, but it's needed size_t* get_screen_size() { size_t* result = malloc(sizeof(size_t) * 2); if(!result) err(1, "Memory Error"); struct winsize ws; int fd; fd = open("/dev/tty", 0_RDWR); if(fd < 0 || ioctl(fd, TIOCGWINSZ, &ws) < 0) err(8, "/dev/tty"); result[0] = ws.ws_row; result[1] = ws.ws_col; close(fd); return result; }
Jika Anda memastikan untuk tidak memanggil semuanya tetapi mungkin sesekali Anda akan baik-baik saja, itu bahkan harus diperbarui ketika pengguna mengubah ukuran jendela terminal (karena Anda membuka file dan membacanya setiap saat).
Jika Anda tidak menggunakan,
TIOCGWINSZ
lihat jawaban pertama di formulir ini https://www.linuxquestions.org/questions/programming-9/get-width-height-of-a-terminal-window-in-c-810739/ .Oh, dan jangan lupa untuk
free()
yangresult
.sumber
Berikut adalah panggilan fungsi untuk variabel lingkungan yang sudah disarankan:
int lines = atoi(getenv("LINES")); int columns = atoi(getenv("COLUMNS"));
sumber
SIGWINCH
sinyal, sehingga mereka dapat menjaga variabel tetap mutakhir (mereka juga membutuhkannya sehingga mereka akan melakukan penggabungan baris yang tepat di editor input).getenv()
mengembalikan NULL atau tidak dan itu terjadi di terminal Linux saya (karena variabel-variabel itu tidak diekspor.) Juga bahkan jika shell memperbarui variabel-variabel itu, Anda tidak akan melihat berubah saat program Anda berjalan (bukan tanpa Anda memilikiSIGWINCH
penangan sendiri ).