Ich habe nach einer Möglichkeit gesucht, die Terminalbreite aus meinem C-Programm herauszubekommen. Was mir immer wieder einfällt, ist etwas in der Art von:
Aber jedes Mal, wenn ich es versuche, bekomme ich es
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.)
Ist dies der beste Weg, dies zu tun, oder gibt es einen besseren Weg? Wenn nicht, wie kann ich das zum Laufen bringen?
Keine der vorgeschlagenen Antworten ist mehr als halb richtig.
– Thomas Dickey
18. April 2019 um 8:10 Uhr
@ThomasDickey, wo ist dann deine Antwort?
– Alexis Wilke
15. Juli 2019 um 6:42 Uhr
Johannes T
Haben Sie darüber nachgedacht, zu verwenden getenv() ? Es ermöglicht Ihnen, die Umgebungsvariablen des Systems zu erhalten, die die Spalten und Zeilen der Terminals enthalten.
Wenn Sie alternativ mit Ihrer Methode sehen möchten, was der Kernel als Terminalgröße sieht (besser, wenn die Größe des Terminals geändert wird), müssen Sie TIOCGWINSZ verwenden, im Gegensatz zu Ihrer TIOCGSIZE, wie folgt:
#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
}
Ja, aber die Begriffsbreite ist keine Umgebungsvariable, sondern statisch für den Begriff.
– Austin
21. Juni 2009 um 1:42 Uhr
Es bietet Ihnen nicht die aktuell Terminalgröße, wenn jemand während der Ausführung des Programms die Größe des Terminals ändert.
– C. K. Young
21. Juni 2009 um 1:42 Uhr
@Debashish Hängt davon ab. ZB unterstützt Linux diese Felder überhaupt nicht.
– Melpomen
5. Juli 2019 um 22:07 Uhr
Obwohl wir das sehen können LINES und COLUMNS Variablen in der Umgebung, sie scheinen nicht exportiert zu werden. Also nicht von Ihrem C-Programm aus zugänglich.
– Alexis Wilke
14. Juli 2019 um 21:59 Uhr
Ich bin gerade über diese Antwort gestolpert, und mir fiel die Kinnlade herunter, als ich das erkannte getenv("COLUMNS") funktioniert perfekt, wenn man unter Aufsicht läuft (1). Also habe ich jetzt eine Reihe von Fallbacks, alle von der TIOCWINSZ ioctl, um getenv, wenn nicht ein tty, bis zum klassischen ANSI-Escape “move cursor to 9999,9999 and the query cursor pos. Der letzte funktioniert auf seriellen Konsolen für eingebettete Systeme 🙂
– Troglobit
23. Dezember 2020 um 8:54 Uhr
Dieses Beispiel ist etwas langatmig, aber ich glaube, es ist die portabelste Art, die Terminalabmessungen zu erkennen. Dies behandelt auch Größenänderungsereignisse.
Wie tim und rlbond andeuten, verwende ich ncurses. Es garantiert eine große Verbesserung der Terminalkompatibilität im Vergleich zum direkten Lesen von Umgebungsvariablen.
#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);
}
Aber ist es wirklich sicher, initscr und endwin von einem Signal-Handler aus aufzurufen? Sie sind zumindest nicht unter den asynchronsignalsicheren APIs in aufgeführt man 7 signal
– Navi
6. August 2013 um 18:16 Uhr
Das ist ein guter Punkt @nav, ich habe noch nie daran gedacht! Wäre es vielleicht eine bessere Lösung, den Signalhandler ein Flag setzen zu lassen und dann den Rest der Operationen in der Hauptschleife auszuführen?
– gamen
3. Oktober 2013 um 9:55 Uhr
@gamen, ja, das wäre besser 😉 – auch die Verwendung von sigaction anstelle von signal wäre auch besser.
– Bodo Thiesen
30. Juli 2015 um 16:07 Uhr
Sind also COLS und LINES globale Variablen?
– einpoklum
28. Februar 2016 um 12:12 Uhr
@AlexisWilke: Einschließlich OK und ERR. Wie “nett” von ihnen, uns zu helfen, diese Lücke in unserem Leben zu füllen 🙁
– einpoklum
15. Juli 2019 um 8:10 Uhr
#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;
}
Muss mit kompiliert werden -ltermcap . Es gibt viele andere nützliche Informationen, die Sie mit termcap erhalten können. Überprüfen Sie das Termcap-Handbuch mit info termcap für mehr Details.
Sie können es auch mit -lcurses kompilieren.
– Kambus
19. April 2011 um 10:12 Uhr
Ich weiß, dass dieser Kommentar 6 Jahre später kommt, aber bitte erklären Sie Ihre magische Zahl von 2048 …
– einpoklum
20. Februar 2016 um 14:35 Uhr
@einpoklum Das ist noch fast drei Jahre später, aber ist es nicht ziemlich klar, dass 2048 nur eine willkürliche Größe für den Puffer ist, der “wahrscheinlich groß genug sein sollte” für jede Eingabezeichenfolge, die dorthin geht?
– Roflcopter4
12. Dezember 2018 um 6:32 Uhr
Tatsächlich macht diese Antwort zu viele Annahmen, um richtig zu sein.
– Thomas Dickey
8. Mai 2019 um 8:26 Uhr
Für alle Neugierigen wird die Puffergröße von 2048 in der GNU-Termcap-Dokumentation hier erklärt: gnu.org/software/termutils/manual/termcap-1.3/html_mono/… Es gibt auch eine Menge anderer Dinge darin, die Leute, die diesen Beitrag lesen, nützlich finden könnten.
– Benutzer5739133
11. Mai 2020 um 22:10 Uhr
Wenn Sie ncurses installiert haben und verwenden, können Sie verwenden getmaxyx() um die Abmessungen des Terminals zu finden.
Um eine vollständigere Antwort hinzuzufügen, habe ich herausgefunden, dass es für mich funktioniert, die Lösung von @ John_T mit einigen hinzugefügten Bits zu verwenden Rosetta-Code, zusammen mit einigen Fehlerbehebungen, um Abhängigkeiten herauszufinden. Es mag ein bisschen ineffizient sein, aber mit intelligenter Programmierung können Sie es zum Laufen bringen und müssen nicht ständig Ihre Terminaldatei öffnen.
Wenn Sie sicherstellen, dass Sie nicht alles aufrufen, aber vielleicht hin und wieder sollte es Ihnen gut gehen, es sollte sogar aktualisiert werden, wenn der Benutzer die Größe des Terminalfensters ändert (weil Sie die Datei öffnen und lesen jeder Zeit).
Warum würden Sie zurückkehren size_t *? Erstellen Sie einfach eine Struktur dafür und geben Sie den Strukturwert zurück. Auf diese Weise gibt es keine malloc() und nein free() beteiligt.
– Mecki
21. Juli 2021 um 18:13 Uhr
Für Personen, die diesen Code verwenden: 0_RDWR im Aufruf an open muß sein O_RDWR (O statt 0).
– pschulz
17. Januar um 7:57 Uhr
Peter Mortensen
Angenommen, Sie verwenden Linux, ich denke, Sie möchten die verwenden ncurses Bibliothek statt. Ich bin mir ziemlich sicher, dass das ttysize-Zeug, das Sie haben, nicht in stdlib ist.
Warum würden Sie zurückkehren size_t *? Erstellen Sie einfach eine Struktur dafür und geben Sie den Strukturwert zurück. Auf diese Weise gibt es keine malloc() und nein free() beteiligt.
– Mecki
21. Juli 2021 um 18:13 Uhr
Für Personen, die diesen Code verwenden: 0_RDWR im Aufruf an open muß sein O_RDWR (O statt 0).
– pschulz
17. Januar um 7:57 Uhr
RajnishCoder
Also hier keine Antwort vorschlagen, aber:
linux-pc:~/scratch$ echo $LINES
49
linux-pc:~/scratch$ printenv | grep LINES
linux-pc:~/scratch$
Ok, und ich stelle fest, dass, wenn ich die Größe des GNOME-Terminals verändere, die Variablen LINES und COLUMNS folgen.
Irgendwie scheint das GNOME-Terminal diese Umgebungsvariablen selbst zu erstellen?
Und natürlich wird es nicht an C-Code weitergegeben. getenv(“LINES”) gibt NULL zurück.
– Scott Franco
18. April 2019 um 6:47 Uhr
Variablen sind ein Shell-Ding, kein Terminal-Ding.
– Melpomen
5. Juli 2019 um 22:07 Uhr
14220900cookie-checkTerminalbreite in C abrufen?yes
Keine der vorgeschlagenen Antworten ist mehr als halb richtig.
– Thomas Dickey
18. April 2019 um 8:10 Uhr
@ThomasDickey, wo ist dann deine Antwort?
– Alexis Wilke
15. Juli 2019 um 6:42 Uhr