|
Программирование >> Арифметические и логические операции
Мне необходима случайная величина, имеющая два значения true/false. Я использую rand() % 2, но получается неслучайная последовательность: 0,1,0,1,0... Некачественные генераторы случайных чисел (попавшие, к несчастью, в состав некоторых компиляторов) не очень то случайны, когда речь идет о младших битах. Попробуйте использовать старшие биты. Я все время получаю сообщения об ошибках - не определены библиотечные функции, но я включаю все необходимые головные файлы Иногда (особенно для нестандартных функций) следует явно указывать, какие библиотеки нужны при компоновке программы. Я по-прежнему получаю сообщения, что библиотечные функции не определены, хотя и использую ключ -l, чтобы явно указать библиотеки во время компоновки Многие компоновщики делают один проход по списку объектных файлов и библиотек, которые вы указали, извлекая из библиотек только те функции, удовлетворяющие ссылки, которые к этому моменту оказались неопределенными. Следовательно, порядок относительно объектных файлов, в котором перечислены библиотеки, важен; обычно просмотр библиотек нужно делать в самом конце. (Например, в операционной системе UNIX помещайте ключи -l в самом конце командной строки). Мне необходим исходный текст программы, которая осуществляет поиск заданной строки Ищите библиотеку regesp (поставляется со многими UNIX-систе-мами) или достаньте пакет regexp Генри Спенсера (Henry Spencer). Как разбить командную строку на разделенные пробельными литерами аргументы (что-то вроде argc и argv в main)? В большинстве компиляторов имеется функция strtok, хотя она требует хитроумного обращения, а ее возможности могут вас не удовлетворить (например, работа в случае кавычек). Вот я написал программу, а она ведет себя странно. Что в ней не так? Попробуйте сначала запустить lint (возможно, с ключами -a, -c, -h, -p). Многие компиляторы С выполняют на самом деле только половину задачи, не сообщая о тех подозрительных местах в тексте программы, которые не препятствуют генерации кода. Как мне подавить сообщение warning: possible pointer alignment problem ( предупреждение: возможна проблема с выравниванием указателя ), которое выдает lint после каждого вызова malloc? Проблема состоит в том, что lint обычно не знает, и нет возможности ему об этом сообщить, что malloc возвращает указатель на область памяти, которая должным образом выровнена для хранения объекта любого типа . Возможна псевдореализация malloc с помощью #define внутри #ifdef lint, которая удалит это сообщение, но слишком прямолинейное применение #define может подавить и другие осмысленные сообщения о действительно некорректных вызовах. Возможно, будет проще игнорировать эти сообщения, может быть, делать это автоматически с помощью grep -v. Где найти ANSI-совместимый lint? Программа, которая называется FlexeLint (в виде исходного текста с удаленными комментариями и переименованными переменными, пригодная для компиляции на почти любой системе) может быть заказана по адресу: Gimpel Software 3207 Hogarth Lane Collegeville, PA 19426 USA (+1) 610 584 4261 gimpel@netaxs.com Lint для System V release 4 ANSI-совместим и может быть получен (вместе с другими C утилитами) от UNIX Support Labs или от дилеров System V. Другой ANSI-совместимый LINT (способный также выполнять формальную верификацию высокого уровня) называется LCLint и доступен через: ftp: larch.lcs.mit.edu: pub/Larch/lclint/. Ничего страшного, если программы lint нет. Многие современные компиляторы почти столь же эффективны в выявлении ошибок и подозрительных мест, как и lint. Может ли простой и приятный трюк if(!strcmp(s1, s2)) служить образцом хорошего стиля? Стиль не особенно хороший, хотя такая конструкция весьма популярна. Тест удачен в случае равенства строк, хотя по виду условия можно подумать, что это тест на неравенство. Есть альтернативный прием, связанный с использованием макро- #define Streq(s1, s2) (strcmp((s1), (s2)) == 0) Вопросы стиля программирования, как и проблемы веры, могут обсуждаться бесконечно. К хорошему стилю стоит стремиться, он легко узнаваем, но не определим. Каков наилучший стиль внешнего оформления программы? Не так важно, чтобы стиль был идеален . Важнее, чтобы он применялся последовательно и был совместим (со стилем коллег или общедоступных программ). Так трудно определимое понятие хороший стиль включает в себя гораздо больше, чем просто внешнее оформление программы; не тратьте слишком много времени на отступы и скобки в ущерб более существенным слагаемым качества. У меня операции с плавающей точкой выполняются странно, и на разных машинах получаются различные результаты Сначала убедитесь, что подключен головной файл <math.h> и правильно объявлены другие функции, возвращающие тип double. Если дело не в этом, вспомните, что большинство компьютеров используют форматы с плавающей точкой, которые хотя и похоже, но вовсе не идеально имитируют операции с действительными числами. Потеря значимости, накопление ошибок и другие свойственные ЭВМ особенности вычислений могут быть весьма болезненными. Не нужно предполагать, что результаты операций с плавающей точкой будут точными, в особенности не стоит проверять на равенство два числа с плавающей точкой. (Следует избегать любых ненужных случайных факторов.) Все эти проблемы одинаково свойственны как Си, так и другим языкам программирования. Семантика операций с плавающей точкой определяется обычно так, как это выполняет процессор ; иначе компилятор вынужден бы был заниматься непомерно дорогостоящей эмуляцией правильной модели вычислений. Я пытаюсь проделать кое-какие вычисления, связанные с тригонометрией, включаю <math.h>, но все равно получаю сообщение: undefined: sin во время компиляции Убедитесь в том, что компоновщику известна библиотека, в которой собраны математические функции. Например, в операционной системе UNIX часто необходим ключ -lm в самом конце командной строки. Почему в языке С нет оператора возведения в степень? Потому что немногие процессоры имеют такую инструкцию. Вместо этого можно, включив головной файл <math.h>, использовать функцию pow(), хотя часто при небольших целых порядках явное умножение предпочтительней. Как округлять числа? Вот самый простой и честный способ: (int)(x + 0.5) Хотя для отрицательных чисел это не годится. Как выявить специальное значение IEEE NaN и другие специальные значения? Многие компиляторы с высококачественной реализацией стандарта IEEE операций с плавающей точкой обеспечивают возможность (например, макрос isnan()) явной работы с такими значениями, а Numerical C Extensions Group (NCEG) занимается стандартизацией таких средств. Примером грубого, но обычно эффективного способа проверки на NaN служит макрос: #define isnan(x) ((x) != (x)) хотя не знающие об IEEE компиляторы могут выбросить проверку в процессе оптимизации. У меня проблемы с компилятором Turbo C. Программа аварийно завершается, выдавая нечто вроде floating point formats not linked Некоторые компиляторы для мини-эвм, включая Turbo C (а также компилятор Денниса Ритчи для PDP-11), не включают поддержку операций с плавающей точкой, когда им кажется, что это не понадобится. В особенности это касается версий printf и scanf, когда для экономии места не включается поддержка %e, %f и %g. Бывает так, что эвристической процедуры Turbo C, которая определяет - использует программа операции с плавающей точкой или нет, оказывается недостаточно, и программист должен лишний раз вызвать функцию, использующую операции с плавающей точкой, чтобы заставить компилятор включить поддержку таких операций. Как прочитать с клавиатуры один символ, не дожидаясь новой строки? Вопреки популярному убеждению и желанию многих, этот вопрос (как и родственные вопросы, связанные с дублированием символов) не относится к языку Си. Передача символов с клавиатуры программе, написанной на Си, осуществляется операционной системой, эта опера- ция не стандартизирована языком Си. Некоторые версии библиотеки curses содержат функцию cbreak(), которая делает как раз то, что нужно. Если вы пытаетесь прочитать пароль с клавиатуры без вывода его на экран, попробуйте getpass(). В операционной системе UNIX используйте ioctl для смены режима работы драйвера терминала (CBREAK или RAW для классических версий; ICANON, c cc[VMIN] и c cc[VTIME] для System V или Posix). В системе MS-DOS используйте getch(). В системе VMS попробуйте функции управления экраном (SMG$) или curses, или используйте низкоуровневые команды $QIO с кодами IO$ READ-VBLK (и, может быть, IO$M NOECHO) для приема одного символа за раз. В других операционных системах выкручивайтесь сами. Помните, что в некоторых операционных системах сделать нечто подобное невозможно, так как работа с символами осуществляется вспомогательными процессорами и не находится под контролем центрального процессора. Вопросы, ответы на которые зависят от операционной системы, неуместны в comp.lang.c. Ответы на многие вопросы можно найти в FAQ таких групп как comp.unix.questions и comp.os.msdos.programmer. Имейте в виду, что ответы могут отличаться даже в случае разных вариантов одной и той же операционной системы. Если вопрос касается специфики операционной системы, помните, что ответ, пригодный в вашей системе, может быть бесполезен всем остальным. Как определить - есть ли символы для чтения (и если есть, то сколько?) И наоборот, как сделать, чтобы выполнение программы не блокировалось, когда нет символов для чтения? Ответ на эти вопросы также целиком зависит от операционной системы. В некоторых версиях curses есть функция nodelay(). В зависимости от операционной системы вы сможете использовать неблокирующий ввод/вывод или системный вызов select или ioctl FIONREAD, или kbhit(), или rdchk(), или опцию O NDELAY функций open() или fcntl(). Как очистить экран? Как выводить на экран негативное изображение? Это зависит от типа терминала (или дисплея). Можете использовать такую библиотеку как termcap или curses, или какие-то другие функции, пригодные для данной операционной системы. Как программа может определить полный путь к месту, из которого она была вызвана? argv[0] может содержать весь путь, часть его или ничего не содержать. Если имя файла в argv[0] имеется, но информация не полна, возможно повторение логики поиска исполнимого файла, используемой интерпретатором командного языка. Гарантированных или мобильных решений, однако, не существует. Как процесс может изменить переменную окружения родительского процесса? В общем, никак. Различные операционные системы обеспечивают сходную с UNIX возможность задания пары имя/значение. Может ли программа с пользой для себя поменять окружение, и если да, то как - все это зависит от операционной системы. В системе UNIX процесс может модифицировать свое окружение (в некоторых системах есть для этого функции setenv() и/или putenv()) и модифицированное окружение обычно передается дочерним процессам но не распространяется на родительский процесс. Как проверить, существует ли файл? Мне необходимо спрашивать пользователя перед тем как переписывать существующие файлы В UNIX-подобных операционных системах можно попробовать функцию access(), хотя имеются кое-какие проблемы. (Применение access() может сказаться на последующих действиях, кроме того, возможны особенности исполнения в setuid-программах). Другое (возможно, лучшее) решение - вызвать stat(), указав имя файла. Единственный универсальный, гарантирующий мобильность способ состоит в попытке открыть файл. Как определить размер файла до его чтения? Если размер файла - это количество литер, которое можно прочитать, то, вообще говоря, это количество заранее неизвестно. В операционной системе Unix вызов функции stat дает точный ответ, и многие операционные системы поддерживают похожую функцию, которая дает приблизительный ответ. Можно c помощью fseek переместиться в конец файла, а затем вызвать ftell, но такой прием немобилен (дает точный ответ только в системе Unix, в других же случаях ответ почти точен лишь для определенных стандартом ANSI двоичных файлов). length. В некоторых системах имеются подпрограммы filesize или file-
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0
При копировании материалов приветствуются ссылки. |