Проверьте программу на Си

Модератор: Модераторы разделов

Ответить
unixlike
Сообщения: 14

Проверьте программу на Си

Сообщение unixlike »

Начал изучать Си и для тренировки написал программу копирования файлов cp.c

Код:

#include <stdlib.h> #include <stdio.h> #include <fcntl.h> #include <stdlib.h> #include <unistd.h> #define BUFFER_SIZE 4096 int main (int argc, char * argv[]) { int finput1, foutput2, closef1, closef2; int read_bytes; char buffer[BUFFER_SIZE+1]; if (argc < 3) { fprintf (stderr, "Lack of arguments\n"); exit (1); } finput1 = open (argv[1], O_RDONLY); if (finput1 < 0) { fprintf (stderr, "Cannot open file-Read\n"); exit (1); } foutput2 = open (argv[2], O_WRONLY|O_CREAT|O_EXCL, 0600); if (foutput2 < 0) { fprintf (stderr, "Cannot open file-Write\n"); exit (1); } while ((read_bytes = read (finput1, buffer, BUFFER_SIZE)) > 0) { write (foutput2, buffer, read_bytes); } if (read_bytes < 0) { fprintf (stderr, "cp: Cannot read file\n"); exit (1); } closef1=close (finput1); if (closef1 < 0) { fprintf (stderr, "Cannot close file-Read\n"); exit (1); } closef2=close (foutput2); if (closef2 < 0) { fprintf (stderr, "Cannot close file-Write\n"); exit (1); } exit (0); }


компилировал
gcc -o cp cp.c -std=c99 -Wall в консоли тишина

проверьте все ли там правильно.
Спасибо сказали:
Аватара пользователя
Janik
Сообщения: 850
Статус: Оператор вычислительных машин
ОС: Debian

Re: Проверьте программу на Си

Сообщение Janik »

Если gcc ничего не вернул, то компиляция прошла успешно. А вот в самой программе ошибки скорее всего будут. Вы её хоть пробовали запустить?
Кто ищет, тот всегда найдет!
Опыт - это когда все получается с первого раза.
Спасибо сказали:
Аватара пользователя
Фантом
Сообщения: 452
ОС: openSUSE

Re: Проверьте программу на Си

Сообщение Фантом »

Вполне нормально. Только зачем нужны два последних #include (один из которых повторяет уже имеющийся) и зачем указывать при компиляции C99 (и совершенно не использовать его в самой программе)?
Спасибо сказали:
unixlike
Сообщения: 14

Re: Проверьте программу на Си

Сообщение unixlike »

Вы её хоть пробовали запустить?

да, работает как бы нормально, сравнение оригинала с копией cmp говорит ОК.
Только зачем нужны два последних #include (один из которых повторяет уже имеющийся) и зачем указывать при компиляции C99

повторение #include <stdlib.h> ошибка - перестарался
а #include <unistd.h> чтоб не было варниннгов при компиляции с флагом -std=c99 без unistd.h gcc ругался.
ну и c99 указал для более строгой проверки формальной корректности кода или это не поможет?
Спасибо сказали:
Аватара пользователя
Janik
Сообщения: 850
Статус: Оператор вычислительных машин
ОС: Debian

Re: Проверьте программу на Си

Сообщение Janik »

По-умолчанию используется старый стандарт, вроде как.
Поправте, если заблуждаюсь
Кто ищет, тот всегда найдет!
Опыт - это когда все получается с первого раза.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Проверьте программу на Си

Сообщение drBatty »

unixlike писал(а):
14.08.2012 19:40
проверьте все ли там правильно.

форматирование сделайте нормальное. так не видно.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Аватара пользователя
Janik
Сообщения: 850
Статус: Оператор вычислительных машин
ОС: Debian

Re: Проверьте программу на Си

Сообщение Janik »

Кстати, можно проверить программу на то, как она обрабатывает неправильные аргументы или ситуации.
Кто ищет, тот всегда найдет!
Опыт - это когда все получается с первого раза.
Спасибо сказали:
unixlike
Сообщения: 14

Re: Проверьте программу на Си

Сообщение unixlike »

форматирование сделайте нормальное. так не видно.

нормальное это как?

Я кстати похоже нашел логические ошибки. Неправильно же сразу exit(1); везде ставить, нужно открытые файлы закрыть сначала.

И еще такой момент, первое копирование 200Мб файла на тот же диск примерно 5 сек, это нормально. А вот повторное 1.2-1.6 сек явно не реально. Чтение с диска макс. 87Мб/сек. Добавлял sync() в программу время повторного копирования не изменилось. Может потому что sync() ничего не возвращает и программа не ждет результата.

Тогда как гарантированно сбросить данные на диск до закрытия программы?
Спасибо сказали:
unixlike
Сообщения: 14

Re: Проверьте программу на Си

Сообщение unixlike »

Вот прогнал через форматирование:

Код: Выделить всё

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

#define BUFFER_SIZE 4096

int main(int argc, char *argv[])
{
    int finput1, foutput2, closef1, closef2;

    int read_bytes;

    char buffer[BUFFER_SIZE + 1];

    if (argc < 3)
    {
        fprintf(stderr, "Lack of arguments\n");
        exit(1);
    }

    finput1 = open(argv[1], O_RDONLY);
    if (finput1 < 0)
    {
        fprintf(stderr, "Cannot open file-Read\n");
        exit(1);
    }

    foutput2 = open(argv[2], O_WRONLY | O_CREAT | O_EXCL, 0600);
    if (foutput2 < 0)
    {
        fprintf(stderr, "Cannot open file-Write\n");
        exit(1);
    }

    while ((read_bytes = read(finput1, buffer, BUFFER_SIZE)) > 0)
    {
        write(foutput2, buffer, read_bytes);
    }

    if (read_bytes < 0)
    {
        fprintf(stderr, "cp: Cannot read file\n");
        exit(1);
    }

    closef1 = close(finput1);
    if (closef1 < 0)
    {
        fprintf(stderr, "Cannot close file-Read\n");
        exit(1);
    }

    closef2 = close(foutput2);
    if (closef2 < 0)
    {
        fprintf(stderr, "Cannot close file-Write\n");
        exit(1);
    }

    exit(0);
}
Спасибо сказали:
Аватара пользователя
Janik
Сообщения: 850
Статус: Оператор вычислительных машин
ОС: Debian

Re: Проверьте программу на Си

Сообщение Janik »

Во-во, так надо форматировать текст.
Кто ищет, тот всегда найдет!
Опыт - это когда все получается с первого раза.
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Проверьте программу на Си

Сообщение drBatty »

unixlike писал(а):
15.08.2012 13:56
Я кстати похоже нашел логические ошибки. Неправильно же сразу exit(1); везде ставить, нужно открытые файлы закрыть сначала.

по стандарту ЕМНИП при exit() все открытые файлы сами закрываются (в отличие от abort(3)).
unixlike писал(а):
15.08.2012 13:56
Тогда как гарантированно сбросить данные на диск до закрытия программы?

проще юзать потоки (stream), тогда закрыть все файлы можно fcloseall(3)
(для гарантии можно проверить return value)
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
unixlike
Сообщения: 14

Re: Проверьте программу на Си

Сообщение unixlike »

по стандарту ЕМНИП при exit() все открытые файлы сами закрываются (в отличие от abort(3)).


А перед нормальным выходом из программы таки нужно закрыть?

проще юзать потоки (stream), тогда закрыть все файлы можно fcloseall(3)


этой стадии просветления пока не достиг
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Проверьте программу на Си

Сообщение drBatty »

unixlike писал(а):
15.08.2012 19:58
А перед нормальным выходом из программы таки нужно закрыть?

нет. Но для совместимости и вообще... Короче, я закрываю, и вам советую. К файлам отношение должно быть как к памяти:

Код: Выделить всё

FILE *fs = fopen(file_name, mode);
if(!fs)
{// обработка ошибки открытия файла
}
function(fs);// тут работаем с открытым файлом
if(fclose(fs) != 0)
{// ошибка закрытия. Тоже бывает
}

для выяснения КАКАЯ была ошибка, подойдёт переменная errno.
unixlike писал(а):
15.08.2012 19:58
этой стадии просветления пока не достиг

а это проще, чем ваше write/read. Файлы в данном случае сродни потокам в обычной unix-shell. Это более высокий уровень абстракции, для большинства задач этого хватает за глаза.
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
unixlike
Сообщения: 14

Re: Проверьте программу на Си

Сообщение unixlike »

применил
fprintf(stderr, "Cannot open file '%s' %s\n", argv[1], strerror(errno));
работает: Cannot open file 'testfile' -No such file or directory

а где почитать про этот (stream) понятное объяснение я не пойму как с этим работать
Спасибо сказали:
Аватара пользователя
drBatty
Сообщения: 8735
Статус: GPG ID: 4DFBD1D6 дом горит, козёл не видит...
ОС: Slackware-current
Контактная информация:

Re: Проверьте программу на Си

Сообщение drBatty »

unixlike писал(а):
15.08.2012 21:05
работает: Cannot open file 'testfile' -No such file or directory

ессно.
unixlike писал(а):
15.08.2012 21:05
а где почитать про этот (stream) понятное объяснение я не пойму как с этим работать

K&R
подробности реализации
man 3 fopen
man 3 fread
man 3 fwrite
man 3 fclose
man 3 errno
man 3 strerror
http://emulek.blogspot.ru/ Windows Must Die
Учебник по sed зеркало в github

Скоро придёт
Осень
Спасибо сказали:
Ответить