|
Программирование >> Арифметические и логические операции
не приводит к каким-то проблемам. Этот довод, широко распространенный компилятором pcc и принятый стандартом ANSI, означает, что выражение: r = fp(); работает одинаково правильно, независимо от того, что такое fp - функция или указатель на нее. (Имя всегда используется однозначно; просто невозможно сделать что-то другое с указателем на функцию, за которым следует список аргументов, кроме как вызвать функцию.) Явное задание * безопасно и все еще разрешено (и рекомендуется, если важна совместимость со старыми компиляторами). Где может пригодиться ключевое слово auto? Нигде, оно вышло из употребления. Что плохого в таких строках: char c; while((c = getchar())!= EOF)... Во-первых, переменная, которой присваивается возвращенное getchar значение, должна иметь тип int. getchar и может вернуть все возможные значения для символов, в том числе EOF. Если значение, возвращенное getchar присваивается переменной типа char, возможно либо обычную литеру принять за EOF, либо EOF исказится (особенно если использовать тип unsigned char) так, что распознать его будет невозможно. Как напечатать символ % в строке формата printf? Я попробовал \%, но из этого ничего не вышло Просто удвойте знак процента %%. Почему не работает scanf( %d ,i)? Для функции scanf необходимы адреса переменных, по которым будут записаны данные, нужно написать scanf( %d , Почему не работает double d; scanf( %f , &d); scanf использует спецификацию формата %lf для значений типа double и %f для значений типа float. (Обратите внимание на несходство с printf, где в соответствии с правилом расширения типов аргументов спецификация %f используется как для float, так и для double). Почему фрагмент программы while(!feof(infp)) { fgets(buf, MAXLINE, infp); fputs(buf, outfp); } дважды копирует последнюю строку? Это вам не Паскаль. Символ EOF появляется только после попытки прочесть, когда функция ввода натыкается на конец файла. Чаще всего необходимо просто проверять значение, возвращаемое функцией ввода, (в нашем случае fgets); в использовании feof() обычно вообще нет необходимости. Почему все против использования gets()? Потому что нет возможности предотвратить переполнение буфера, куда читаются данные, ведь функции gets() нельзя сообщить его размер. Почему переменной errno присваивается значение ENOTTY после вызова printf()? Многие реализации стандартной библиотеки ввода/вывода несколько изменяют свое поведение, если стандартное устройство вывода - терминал. Чтобы определить тип устройства, выполняется операция, которая оканчивается неудачно (с сообщением ENOTTY), если устройство вывода - не терминал. Хотя вывод завершается успешно, errno все же содержит ENOTTY. Запросы моей программы, а также промежуточные результаты не всегда отображаются на экране, особенно когда моя программа передает данные по каналу (pipe) другой программе Лучше всего явно использовать fflush(stdout), когда непременно нужно видеть то, что выдает программа. Несколько механизмов пытаются в нужное время осуществить fflush, но, похоже, все это правильно работает в том случае, когда stdout - это терминал. При чтении с клавиатуры функцией scanf возникает чувство, что программа зависает, пока я перевожу строку Функция scanf была задумана для ввода в свободном формате, необходимость в котором возникает редко при чтении с клавиатуры. Что же касается ответа на вопрос, то символ \n в форматной строке вовсе не означает, что scanf будет ждать перевода строки. Это значит, что scanf будет читать и отбрасывать все встретившиеся подряд пробельные литеры (т.е. символы пробела, табуляции, новой строки, возврата каретки, вертикальной табуляции и новой страницы). Похожее затруднение случается, когда scanf застревает , получив неожиданно для себя нечисловые данные. Из-за подобных проблем часто лучше читать всю строку с помощью fgets, а затем использовать sscanf или другие функции, работающие со строками, чтобы интерпретировать введенную строку по частям. Если используется sscanf, не забудьте проверить возвращаемое значение для уверенности в том, что число прочитанных переменных равно ожидаемому. Я пытаюсь обновить содержимое файла, для чего использую fopen в режиме r+ , далее читаю строку, затем пишу модифицированную строку в файл, но у меня ничего не получается Непременно вызовите fseek перед записью в файл. Это делается для возврата к началу строки, которую вы хотите переписать; кроме того, всегда необходимо вызвать fseek или fflush между чтением и записью при чтении/записи в режимах + . Помните также, что литеры можно заменить лишь точно таким же числом литер. Как мне отменить ожидаемый ввод, так, чтобы данные, введенные пользователем, не читались при следующем запросе? Поможет ли здесь fflush(stdin)? fflush определена только для вывода. Поскольку определение flush ( смывать ) означает завершение записи символов из буфера (а не отбрасывание их), непрочитанные при вводе символы не будут уничтожены с помощью fflush. Не существует стандартного способа игнорировать символы, еще не прочитанные из входного буфера stdio. Не видно также, как это вообще можно сделать, поскольку непрочитанные символы могут накапливаться в других, зависящих от операционной системы, буферах. Как перенаправить stdin или stdout в файл? Используйте freopen. Если я использовал freopen, то как вернуться назад к stdout (stdin)? Если необходимо переключаться между stdin (stdout) и файлом, наилучшее универсальное решение - не спешить использовать freopen. Попробуйте использовать указатель на файл, которому можно по желанию присвоить то или иное значение, оставляя значение stdout (stdin) нетронутым. Как восстановить имя файла по указателю на открытый файл? Это проблема, вообще говоря, неразрешима. В случае операционной системы UNIX, например, потребуется поиск по всему диску (который, возможно, потребует специального разрешения), и этот поиск окончится неудачно, если указатель на файл был каналом (pipe) или был связан с удаленным файлом. Кроме того, обманчивый ответ будет получен для файла со множественными связями. Лучше всего самому запоминать имена при открытии файлов (возможно, используя специальные функции, вызываемые до и после fopen). Почему strncpy не всегда завершает строку-результат символом \0? strncpy была задумана для обработки теперь уже устаревших структур данных - строк фиксированной длины, не обязательно завершающихся символом \0. И, надо сказать, strncpy не совсем удобно использовать в других случаях, поскольку часто придется добавлять символ \0 вручную. Я пытаюсь сортировать массив строк с помощью qsort, используя для сравнения strcmp, но у меня ничего не получается Когда вы говорите о массиве строк , то, видимо, имеете в виду массив указателей на char . Аргументы функции сравнения, работающей в паре с qsort - это указатели на сравниваемые объекты, в данном случае - указатели на указатели на char. (Конечно, strcmp работает просто с указателями на char). Аргументы процедуры сравнения описаны как обобщенные указатели const void * или char *. Они должны быть превращены в то, что они представляют на самом деле, т.е. (char **) и дальше нужно раскрыть ссылку с помощью *; тогда strcmp получит именно то, что нужно для сравнения. Напишите функцию сравнения примерно так: int pstrcmp(p1, p2) /* сравнить строки, используя указатели */ char *p1, *p2; /* const void * для ANSI C */ return strcmp(*(char **)p1, *(char **)p2); Сейчас я пытаюсь сортировать массив структур с помощью qsort. Процедура сравнения, которую я использую, принимает в качестве аргументов указатели на структуры, но компилятор выдает сообщение о неверном типе функции сравнения. Как мне преобразовать аргументы функции, чтобы подавить сообщения об ошибке? Преобразования должны быть сделаны внутри функции сравнения, которая должна быть объявлена как принимающая аргументы типа обобщенных указателей (const void * или char *). Функция сравнения может выглядеть так: int mystructcmp(p1, p2) char *p1, *p2; /* const void * для ANSI C */ { struct mystruct *sp1 = (struct mystruct *)p1; struct mystruct *sp2 = (struct mystruct *)p2; /* теперь сравнивайте sp1->что-угодно и sp2-> С другой стороны, если сортируются указатели на структуры, необходима косвенная адресация: sp1 = *(struct mystruct **)p1 Как преобразовать числа в строки (операция, противоположная atoi)? Есть ли функция itoa? Просто используйте sprintf. (Необходимо будет выделить память для результата. Беспокоиться, что sprintf - слишком сильное средство, которое может привести к перерасходу памяти и увеличению времени выполнения, нет оснований. На практике sprintf работает хорошо). Как получить дату или время в С программе? Просто используйте функции time, ctime, и/или localtime. (Эти функции существуют многие годы,они включены в стандарт ANSI). Вот простой пример: #include <stdio.h> #include <time.h> main() time t now = time((time t *)NULL); printf( Its %.24s.\n , ctime(&now)); return 0; Я знаю, что библиотечная функция localtime разбивает значение time t по отдельным членам структуры tm, а функция ctime превращает time t в строку символов. А как проделать обратную операцию перевода структуры tm или строки символов в значение time t? Стандарт ANSI определяет библиотечную функцию mktime, которая преобразует структуру tm в time t. Если ваш компилятор не поддерживает mktime, воспользуйтесь одной из общедоступных версий этой функции. Перевод строки в значение time t выполнить сложнее из-за большого количества форматов дат и времени, которые должны быть распознаны. Некоторые компиляторы поддерживают функцию strptime; другая популярная функция - partime широко распространяется с пакетом RCS, но нет уверенности, что эти функции войдут в Стандарт. Как прибавить n дней к дате? Как вычислить разность двух дат? Вошедшие в стандарт ANSI/ISO функции mktime и difftime могут помочь при решении обеих проблем. mktime() поддерживает ненормализованные даты, т.е. можно прямо взять заполненную структуру tm, увеличить или уменьшить член tm mday, затем вызвать mktime(), чтобы нормализовать члены year, month и day (и преобразовать в значение time t). difftime() вычисляет разность в секундах между двумя величинами типа time t. mktime() можно использовать для вычисления значения time t разности двух дат. (Заметьте, однако, что все эти приемы возможны лишь для дат, которые могут быть представлены значением типа time t; кроме того, из-за переходов на летнее и зимнее время продолжительность дня не точно равна 86400 сек.). Мне нужен генератор случайных чисел В стандартной библиотеке С есть функция rand(). Реализация этой функции в вашем компиляторе может не быть идеальной, но и создание лучшей функции может оказаться очень непростым. Как получить случайные целые числа в определенном диапазоне? Очевидный способ: rand() % N где N, конечно, интервал, довольно плох, ведь поведение младших бит во многих генераторах случайных чисел огорчает своей неслучайностью. Лучше попробуйте нечто вроде: (int)((double)rand() / ((double)RAND MAX + 1) * N) Если вам не нравится употребление чисел с плавающей точкой, попробуйте: rand() / (RAND MAX / N + 1) Оба метода требуют знания RAND MAX (согласно ANSI, RAND MAX определен в <stdlib.h>. Предполагается, что N много меньше RAND MAX. Каждый раз при запуске программы функция rand() выдает одну и ту же последовательность чисел Можно вызвать srand() для случайной инициализации генератора случайных чисел. В качестве аргумента для srand() часто используется текущее время, или время, прошедшее до нажатия на клавишу (хотя едва ли существует мобильная процедура определения времен нажатия на клавиши).
|
© 2006 - 2024 pmbk.ru. Генерация страницы: 0.001
При копировании материалов приветствуются ссылки. |