LINUX.ORG.RU

Селектор программ на C (заготовка).

 


1

2

Не все идеи, конечно стоит воплощать. Но мне интересно было попытаться: на самом «начальном» C написать селектор для запуска часто используемых программ.

Вроде получилось, но, честно говоря, тот случай, когда можно заблудиться в трёх соснах.

Оказалось, что в общем возможно. Но, например, чтобы сэмулировать нажаите Enter, пришлось придумать трюк с двойным scanf.

Работает так: 1) названия программ пишутся в текстовый файл. Что-то вроде базы, которая пока составляется руками. Выбор пока тоже ограничен :) (заготовка, так сказать) 2) Запуск и выбор

Update. switch сокртил: https://gitflic.ru/project/dcc0/mix-c-89-php/blob?file=select_no_switch.c&branch=master

P.P.S. Если оставить попытки читатать из файла, то вроде бы селектор получается без ошибок: https://gitflic.ru/project/dcc0/mix-c-89-php/blob/?file=select_and_normal.c&branch=master

Спасибо всем комментаторам!

Итог (а как же без него?!): все ошибки вроде бы отловил, switch, убрал, вызов теперь через execl, лишний символ в начале строки убрал. Все это оставил в комментариях. Скрипт отредактирован относительно начального варианта. Единственное: оставил clear через system, так как через execl совсем другое поведение.

P.P.P.S Нашлось у меня полезное применение этой идеи, так можно выводить выбор .bash_history: https://gitflic.ru/project/dcc0/select-and-run/blob/?file=select_and_run_history.c&branch=master

Как работает система для history: https://www.youtube.com/shorts/wf4EsUPMKuo



Последнее исправление: AnonymUser (всего исправлений: 7)
    switch (input) {
    case 1:
      select = 1;
      run_program = print_select(select);
      if (confirm_choice() == 0) {
        printf("Выполним программу 1\n");
        printf("%s", run_program);
        system(run_program);
      }
      break;
    case 2:
      select = 2;
      run_program = print_select(select);
      if (confirm_choice() == 0) {
        printf("Выполним программу 2\n");
        system(run_program);
      }
      break;

Ой щас тебя порвут) Если все кейсы в свитче одинаковы, он не нужен же.

goingUp ★★★★★
()

dmenu написан на С вроде как. Чем не нравится? Или хочется именно своё?

Я вот тоже сделал себе запуск по списку из файла, плюс автодобавление по путям:

https://notabug.org/bfgeshka/apps/src/master/menu/dmenu_most_used

https://notabug.org/bfgeshka/apps/src/master/menu/dmenuconf

Bfgeshka ★★★★★
()
Последнее исправление: Bfgeshka (всего исправлений: 1)

Ну-с, как-то такое себе. Запускать не пробовал, разобраться в коде сложно, уже сломался на строчке:

  print_select(select);

Которое вызывает char * print_select(int select); Почему не пользуемся возвращаемым значением? :-)

Ну ладно, обижать каждый умеет. А вы хотите именно через стандартный ввод вывод выбирать часто используемые программы? Я бы глянул в сторону TUI интерфейса с использованием ncurses или вот недавно в новостях сайта видел termbox2.

Jullyfish
()
Ответ на: комментарий от Jullyfish

char * print_select(int select) Передаёт туда выбор целым числом. Возвращаемое значение и используется для запуска (в конце функции переменная p).

P.S. Так уж сложилось, что сначала я написал сам селектор, а потом решил прикрутить запуск программ

И небольшой ступор вышел (как это обычно бывает) select начинается с 1, а строки из файла в массиве с 0 индекса. А так, да, - запутанно получилось.

AnonymUser
() автор топика
Ответ на: комментарий от AnonymUser

P.S. Так уж сложилось, что сначала я написал сам селектор, а потом решил прикрутить запуск программ

А так, да, - запутанно получилось.

Представляете, у вас не 100 модулей, на >100 000 строк кода суммарно, а 200 строк кода и только один модуль, а у вас уже сложилось. Вот что вы будете делать, когда строк уже будет хотя бы 1000? Ладно травмированные теперь форумчане, как ВЫ его будете в дальнейшем читать?

Мне одна птичка нашептала, что программный код пишут в первую очередь для человека, а для компьютера во вторую.

Jullyfish
()

ты б хоть опции навроде -Wall включил.

у тебя там функции не возвращают результат, и компилятор это пропускает.

int confirm_choice () {
        char input_confirm;
        /*Используем двойной scanf, чтобы подтвердить нажатие*/
        printf("Нажмите Enter");
        scanf( "%c", &input_confirm );
        scanf( "%c", &input_confirm );
        if (input_confirm =='\n')
         return 0;
 }

результат возвращается в условном операторе. если условие есть ложь - возвращается мусор. такое и в других местах есть. return результата из функции(которая не void) должет быть явным в любом случае. это тебе не функциональщина какая нить

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
    37	     //Пишем строку  посимвольно в отдельный массив
    38	     for (j = 0; str[j] != '\n'; j++) {
    39	       arr1[z][j] = str[j];
    40	       //Добавим пробел, иначе в начале строки будет лишний символ
    41	       str[0] = ' ';
    42	     }

Зачем при каждой итерации str[0] присваивать пробел?

P.S:

$ cc -Wall -Wextra select_and_run.c -o select_and_run
select_and_run.c:18:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
   18 | }
      | ^
select_and_run.c:85:9: warning: result of comparison against a string literal is unspecified (use an explicit string comparison function instead) [-Wstring-compare]
   85 |   if (p != "")
      |         ^  ~~
select_and_run.c:87:1: warning: non-void function does not return a value in all control paths [-Wreturn-type]
   87 | }
      | ^
select_and_run.c:69:7: warning: variable 'p' is used uninitialized whenever 'if' condition is false [-Wsometimes-uninitialized]
   69 |   if (select > 0) {
      |       ^~~~~~~~~~
select_and_run.c:85:7: note: uninitialized use occurs here
   85 |   if (p != "")
      |       ^
select_and_run.c:69:3: note: remove the 'if' if its condition is always true
   69 |   if (select > 0) {
      |   ^~~~~~~~~~~~~~~
select_and_run.c:66:11: note: initialize the variable 'p' to silence this warning
   66 |   char * p;
      |           ^
      |            = NULL
4 warnings generated.
$ ./select_and_run 
Ошибка сегментации(core dumped)
iron ★★★★★
()
Ответ на: комментарий от LINUX-ORG-RU

Не знаю что может сподвигнуть выкладывать учебные полурабочие примеры под видом полезных прог. Да и поздновато для обучения, он на лоре 12 лет назад зареген и в профиле заявляет что в 2010 году кастомно генту собирал.

firkax ★★★★★
()
Последнее исправление: firkax (всего исправлений: 2)
Ответ на: комментарий от firkax

Не знаю что может сподвигнуть выкладывать учебные полурабочие примеры под видом полезных прог.

Тоже самое, что и маленький ребенок тащит найденный на дороге камешек папке с радостным криком: «смотри какое я сокровище нашел».

Для кого-то это странно, а для него большая победа написать программулину на безумно сложном низкоуровневым ЯП, на котором Линукс написан. В конце концов, все мы такими были… :)

iron ★★★★★
()
Ответ на: комментарий от firkax

С датой реги не сходится.

Возраст не препятствует радоваться как ребенок своим персональным маленьким и не очень победам. Как ребенок радуется камешку, так и пожилой человек радуется впервые научившись ездить на велосипеде. «восторг первооткрытия» как поток захватывает человека и этим состоянием хочется поделиться со всем миром. Собственно, что и сделал топикстартер.

iron ★★★★★
()
Ответ на: комментарий от u5er

Вроде через execl получилось сделать вызов программы, но оно абсолютные пути просит.

P.S. При формировании массива строк в начало каждой добавляется символ лишний, не очень понятно, почему. Вроде пофиксил. Но фикс не очень внятный. Если добавить косую черту, то работает, но как-то не очень красиво. Можно закомментировать, конечно, тоже вроде работает.

str[0]='/';

А вот у clear через exec другое поведение.

AnonymUser
() автор топика
Ответ на: комментарий от AnonymUser

А если юзер передумает?

Логичнее проверять что он нажал: если число, то переход, если Ентер, то выбор.

#include <stdio.h>

int main(){
  int x;
  char c;
  scanf("%c", &c);
  if( (c >= '0')&&(c <= '9') ){
    ungetc(c, stdin);
    scanf("%i", &x);
    printf("Number: %i\n", x);
  }else{
    printf("Char: [%c](%i)\n", c, (int)x&0xFF);
  }
}

Но лучше бы уж сделали нормальную навигацию стрелочками вверх - вниз. И выбранный пункт подсвечивать. Либо ESC-последовательностью, либо просто рисовать

  предыдущий_пункт
> выбранный_пункт  <
  следующий_пункт
COKPOWEHEU
()
Последнее исправление: COKPOWEHEU (всего исправлений: 2)
Ответ на: комментарий от AnonymUser

Правду сказал кто-то однажды, что если что-то упустил, пропустил, сделал перерыв большой, потом будто все заново.

Прям как в поговорке: хорошо иметь склероз, про него всегда можно забыть.

iron ★★★★★
()
Ответ на: комментарий от Loki13

Открыл для себя terminos.h (c ним работает getch через non-canonical режим ввода). Хотя он за пределами вроде C89.

https://my.mail.ru/list/mol0t/video/_myvideo/1.html

С ним вообще по-разному можно сделать.

P.S. Понял, как это визуально правильно должно работать: https://pastecode.io/s/q00iszn1

AnonymUser
() автор топика
Последнее исправление: AnonymUser (всего исправлений: 1)