LINUX.ORG.RU

Системный вызов open() close()

 


0

3

Создать процесс, создающий 4 файла A, B, C D, отрывающий и закрывающий их следующим образом:

Открыть А, закрыть А; откр. B, закр. B; откр. C, закр. C; откр. D, закр. D.

это мой прог:

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
 
int main(void) {

        int fd_a;
        int fd_b;
        int fd_c;
        int fd_d;

        fd_a = open("baobab.txt", O_CREAT | O_RDWR , 0664);

        if(fd_a == -1) {
                perror("open");
                exit(EXIT_FAILURE);
        }
        close(fd_a);

        if(fd_a == -1) {
                perror("close");
                exit(EXIT_FAILURE);
        }

        ...

        exit(EXIT_SUCCESS);
}

прога рабочая.

Мне кажется ,что мой прог слишком длинная если я буду для каждаго файла писать.

Нелзя ли сделать ее по короче?

Перемещено leave из general

Заключи код в теги code, а то читать невозможно.

awesomebuntu ()

Во-первых, причём тут «bash»? Во-вторых сделайте функцию xopen, где и будете открывать, ругаться что не получилось и завершаться.

vodz ★★★★★ ()

Почему ты проверяешь после close() значение дескриптора, а не то, что возвращает функция?

post-factum ★★★★★ ()

Все в функции main? Вопрос как-то странно поставлен. Да, длинно, да, ужасно. Но я думаю, что ты и сам это знаешь.

narkoman228 ()
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>

int touch(const char *file) {
	int fd;
	return ((fd = open(file, O_CREAT | O_RDWR , 0664)) == -1 ||
			close(fd) == -1) ? -1 : 0;
}

int main(int argc, char *argv[]) {
	if(argc < 2) {
		fprintf(stderr, "Usage: %s file1 file2 ... fileN\n", argv[0]);
		exit(EXIT_FAILURE);
	}
	while(++argv, *argv) {
		if(touch(*argv) == -1) {
			perror("touch");
			exit(EXIT_FAILURE);
		}
	}
	exit(EXIT_SUCCESS);
}
./touch A B C D
Nietzsche ()
Ответ на: комментарий от anonymous

Тебя так оператор запятая испугала? По-моему, смотрится куда эстетичней, чем for( ; *argv; ++argv)

Nietzsche ()
  1. Вынеси общий код в функцию
  2. Используй цикл
KennyMinigun ★★★★★ ()
Ответ на: комментарий от Nietzsche

Это клеймо не отмыть

Где так учат, что main() надо обязательно завершать exit(EXIT_SUCCESS) ? Головы бы таким поотрывать.

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

Совершенно нормальный код.

Это извращение: оптимизация количества строк под сиюминутную задачу. Завтра вам понадобиться не только тупо делать open+close, и всё придётся переписывать.

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

Код у ТС делает exit(EXIT_SUCCESS), может, это требование преподавателя. К тому же, где еще, как не в main() уместно делать exit(EXIT_SUCCESS) ?

Nietzsche ()
Ответ на: комментарий от vodz
Завтра вам понадобиться не только тупо делать open+close, и всё придётся переписывать.

Задача не подразумевает расширения, поэтому было бы ошибкой делать зазор на будущее.

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

Нечитаемое говно. Даже ссаный однострочник

return close(open(...));

лучше, т.к. один черт на обработку ошибок положен болт, а читается в разы легче.

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

К тому же, где еще, как не в main() уместно делать exit(EXIT_SUCCESS) ?

Это тоже у того преподавателя услышали? А это ничего, что main() как раз и возвращает int, который и используется для exit в libc, и потому exit служит для принудительного завершения программы. Завтра вам понадобиться расширить функционал программы, вы вынесете этот код из распухшего main в my_cool_open_close() и вдруг окажется, что все exit надо вычищать.

vodz ★★★★★ ()
Ответ на: комментарий от staseg
на обработку ошибок положен болт

В моем коде причину ошибки можно получить из errno, что и делает perror().

Nietzsche ()
Ответ на: комментарий от vodz
Это тоже у того преподавателя услышали?

ТС предпочитает использовать exit(), я не вижу в этом ничего страшного.

В своем коде я стараюсь придерживаться одного стиля, поэтому если по какой-то причине выбран exit() вместо return, то он будет везде.

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

придерживаться одного стиля,

Вы так говорите, как-будто стиль не может быть дурацким. Вот у меня 35 лет назад был испорченным из-за экономии бумаги, потом трудно было переучиваться.

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

Вы так говорите, как-будто стиль не может быть дурацким.

Вы правы, но я предпочту дурацкий стиль, чем отсутствие стиля вовсе. Будет ли return лучше смотреться в этом коде? Определенно, да. Но только, если он будет везде.

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

Коммит принимается! :)

Ну слава Богу! А то я уж думал, на кодревью зарежут.

А ещё можно

 while(*++argv) 

вместо

 while(++argv, *argv) 

И exit'ы из main'а я бы тоже убрал, exit всё-таки предназначен для катапультирования из высоких глубин, да ещё и с вызовом обработчика, а тут обычный выход из функции. Зачем катапультироваться, когда уже пришвартовался?

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

Тю. Я тупой, короче, но тута не соглашусь. Ва першых, exit - эта лишняя функция тута. Так чта return смотрится не только лучше, но оправданней. Паправте мну, о ВелИкиЕ Гуру! Но exit прекращает работу сразу? А return должен «выплыть» из вложений в main? Или я чота не понимаю?

vombat ()

Ну начни, что-ли с замены

int fd_a;
        int fd_b;
        int fd_c;
        int fd_d;
на
int fd_a, fd_b, fd_c, fd_d;

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

Чего вы все ко мне прицепились? Я уже написал, что ТС предпочитает юзать exit(). Я лишь соблюл его стилистику.

Я не считаю использование exit() в main() ошибкой, потому как знаю, что код возврата из main() СРАЗУ ЖЕ прередается в системный вызов exit().

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

ТС учитсо. Мы не прицепилися, репейнички-с. Проста для exit() нада sdtlib падключать? Ежели да, то нада указать, что не нада так без надобности делать (си же). Асобенна, когда нЭт выхода пасреди рекурсии. Чиста стиль гуд, но изящьна - это пилотаж (Я им не владею, да-да., но пока).

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

Можно и не подключать, скомпилится и без этого. Главное, чтобы с libc линковалось.

Чтобы окончательно закрыть тему, привожу один из вариантов реализации __libc_start_main, из которого вызывается main()

int __libc_start_main(
	int (*main)(int, char **, char **), int argc, char **argv,
	int (*init)(int, char **, char **), void (*fini)(void),
	void (*ldso_fini)(void))
{
	char **envp = argv+argc+1, **auxv = envp;

	__environ = envp;
	do auxv++; while (*auxv);
	libc.auxv = (void *)++auxv;
	libc.ldso_fini = ldso_fini;
	libc.fini = fini;

	__init_security((void *)auxv);

	/* Execute constructors (static) linked into the application */
	if (init) init(argc, argv, envp);

	/* Pass control to to application */
	exit(main(argc, argv, envp));
	return 0;
}

Это легковесная реализация. В glibc оно жирнее в разы, но суть такая же ---> exit(main(argc, argv, envp)); Напомню, в треде речь идет про сишечку, RAII - мимо.

Nietzsche ()

В рамках пятницы...

#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

typedef int (*FileProcedure)(int fd);

int
with_new_file(char* path, FileProcedure proc) {
	int fd = open(path, O_CREAT | O_RDWR , 0664);
	if (fd == -1) {
		return -1;
	}
	int err = proc(fd);
	close(fd);
	return err;
}

int
do_nothing(int fd) {
	return 0;
}

int
main(int argc, char** argv) {
	for (int i = 1; i < argc; i++) {
		int err = with_new_file(argv[i], do_nothing);
		if (err != 0) {
			return err;
		}
	}
	return 0;
}
korvin_ ★★★★★ ()
Последнее исправление: korvin_ (всего исправлений: 1)
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.