Документ взят из кэша поисковой машины. Адрес
оригинального документа
: http://www.sao.ru/hq/sts/linux/book/bogatyrev_c_unix/gl_1.shtml
Дата изменения: Unknown Дата индексирования: Tue Oct 2 17:37:32 2012 Кодировка: koi8-r Поисковые слова: п п п п п п п п п п п п п п п п п п п п п п п |
#include <stdio.h> main(){ printf("Hello, world\n"); }
Ответ: раз не объявлено иначе, функция main считается возвращающей целое значение (int). Но функция main не возвращает ничего - в ней просто нет оператора return.
Корректно было бы так:
#include <stdio.h> main(){ printf("Hello, world\n"); return 0; }или
#include <stdio.h> void main(){ printf("Hello, world\n"); exit(0); }а уж совсем корректно - так:
#include <stdio.h> int main(int argc, char *argv[]){ printf("Hello, world\n"); return 0; }
#include studio.h main { int i i := 43 print ('В году i недель') }
int n; n = 2; printf ("%d + %d = %d\n", n, n, n + n);
if( x > 2 ) then x = 2; if x < 1 x = 1;Ответ: в Си нет ключевого слова then, условия в операторах if, while должны браться в ()-скобки.
Напишите программу, печатающую ваше имя, место работы и адрес. В первом варианте программы используйте библиотечную функцию printf, а во втором - puts.
Составьте программу с использованием следующих постфиксных и префиксных операций:
a = b = 5 a + b a++ + b ++a + b --a + b a-- + bРаспечатайте полученные значения и проанализируйте результат.
for(INIT; CONDITION; INCR) BODY INIT; repeat: if(CONDITION){ BODY; cont: INCR; goto repeat; } out: ;Цикл while
while(COND) BODY cont: repeat: if(CONDITION){ BODY; goto repeat; } out: ;Цикл do
do BODY while(CONDITION) cont: repeat: BODY; if(CONDITION) goto repeat; out: ;
В операторах цикла внутри тела цикла BODY могут присутствовать операторы break и continue; которые означают на наших схемах следующее:
#define break goto out #define continue goto cont
* ** *** **** *****используя цикл for. Введите переменную, значением которой является размер катета треугольника.
Напишите операторы Си, которые выдают строку длины WIDTH, в которой сначала содержится x0 символов '-', затем w символов '*', и до конца строки - вновь символы '-'. Ответ:
int x; for(x=0; x < x0; ++x) putchar('-'); for( ; x < x0 + w; x++) putchar('*'); for( ; x < WIDTH ; ++x) putchar('-'); putchar('\n');либо
for(x=0; x < WIDTH; x++) putchar( x < x0 ? '-' : x < x0 + w ? '*' : '-' ); putchar('\n');
* *** ***** ******* *********Ответ:
/* Треугольник из звездочек */ #include <stdio.h> /* Печать n символов c */ printn(c, n){ while( --n >= 0 ) putchar(c); } int lines = 10; /* число строк треугольника */ void main(argc, argv) char *argv[]; { register int nline; /* номер строки */ register int naster; /* количество звездочек в строке */ register int i; if( argc > 1 ) lines = atoi( argv[1] ); for( nline=0; nline < lines ; nline++ ){ naster = 1 + 2 * nline; /* лидирующие пробелы */ printn(' ', lines-1 - nline); /* звездочки */ printn('*', naster); /* перевод строки */ putchar( '\n' ); } exit(0); /* завершение программы */ }
main(){ /* печать фразы 10 раз */ int i; while(i < 10){ printf("%d-ый раз\n", i+1); i++; } }
Ответ: автоматическая переменная i не была проинициализирована и содержит не 0, а какое-то произвольное значение. Цикл может выполниться не 10, а любое число раз (в том числе и 0 по случайности). Не забывайте инициализировать переменные, возьмите описание с инициализацией за правило!
int i = 0;Если бы переменная i была статической, она бы имела начальное значение 0.
В данном примере было бы еще лучше использовать цикл for, в котором все операции над индексом цикла собраны в одном месте - в заголовке цикла:
for(i=0; i < 10; i++) printf(...);
Вспомогательные переменные, не несущие смысловой нагрузки (вроде счетчика повторений цикла, не используемого в самом теле цикла) принято по традиции обозначать однобуквенными именами, вроде i, j. Более того, возможны даже такие курьезы:
main(){ int _ ; for( _ = 0; _ < 10; _++) printf("%d\n", _ ); }основанные на том, что подчерк в идентификаторах - полноправная буква.
main(){ int x = 12; printf( "x=%d\n" ); int y; y = 2 * x; printf( "y=%d\n", y ); }
Комментарий: в теле функции все описания должны идти перед всеми выполняемыми операторами (кроме операторов, входящих в состав описаний с инициализацией). Очень часто после внесения правок в программу некоторые описания оказываются после выполняемых операторов. Именно поэтому рекомендуется отделять строки описания переменных от выполняемых операторов пустыми строками (в этой книге это часто не делается для экономии места).
int n; n = 12; main(){ int y; y = n+2; printf( "%d\n", y ); }
Ответ: выполняемый оператор n=12 находится вне тела какой-либо функции. Следует внести его в main() после описания переменной y, либо переписать объявление перед main() в виде
int n = 12;
В последнем случае присваивание переменной n значения 12 выполнит компилятор еще во время компиляции программы, а не сама программа при своем запуске. Точно так же происходит со всеми статическими данными (описанными как static, либо расположенными вне всех функций); причем если их начальное значение не указано явно - то подразумевается 0 ('\0', NULL, ""). Однако нулевые значения не хранятся в скомпилированном выполняемом файле, а требуемая "чистая" память расписывается при старте программы.
TYPE x = выражение;является (почти) эквивалентом для
TYPE x; /* описание */ x = выражение; /* вычисление начального значения */Рассмотрим пример:
#include <stdio.h> extern double sqrt(); /* квадратный корень */ double x = 1.17; double s12 = sqrt(12.0); /* #1 */ double y = x * 2.0; /* #2 */ FILE *fp = fopen("out.out", "w"); /* #3 */ main(){ double ss = sqrt(25.0) + x; /* #4 */ ... }Строки с метками #1, #2 и #3 ошибочны. Почему?
Ответ: при инициализации статических данных (а s12, y и fp таковыми и являются, так как описаны вне какой-либо функции) выражение должно содержать только константы, поскольку оно вычисляется КОМПИЛЯТОРОМ. Поэтому ни использование значений переменных, ни вызовы функций здесь недопустимы (но можно брать адреса от переменных).
В строке #4 мы инициализируем автоматическую переменную ss, т.е. она отводится уже во время выполнения программы. Поэтому выражение для инициализации вычисляется уже не компилятором, а самой программой, что дает нам право использовать переменные, вызовы функций и.т.п., то есть выражения языка Си без ограничений.
Напишите программу, реализующую эхо-печать вводимых символов. Программа должна завершать работу при получении признака EOF. В UNIX при вводе с клавиатуры признак EOF обычно обозначается одновременным нажатием клавиш CTRL и D (CTRL чуть раньше), что в дальнейшем будет обозначаться CTRL/D; а в MS DOS - клавиш CTRL/Z. Используйте getchar() для ввода буквы и putchar() для вывода.
Напишите программу, подсчитывающую число символов поступающих со стандартного ввода. Какие достоинства и недостатки у следующей реализации:
#include <stdio.h> main(){ double cnt = 0.0; while (getchar() != EOF) ++cnt; printf("%.0f\n", cnt ); }
Ответ: и достоинство и недостаток в том, что счетчик имеет тип double. Достоинство можно подсчитать очень большое число символов; недостаток - операции с double обычно выполняются гораздо медленнее, чем с int и long (до десяти раз), программа будет работать дольше. В повседневных задачах вам вряд ли понадобится иметь счетчик, отличный от long cnt; (печатать его надо по формату "%ld").
Составьте программу перекодировки вводимых символов со стандартного ввода по следующему правилу:
a -> b b -> c c -> d ... z -> a другой символ -> *Коды строчных латинских букв расположены подряд по возрастанию.
Составьте программу перекодировки вводимых символов со стандартного ввода по следующему правилу:
B -> A C -> B ... Z -> Y другой символ -> *Коды прописных латинских букв также расположены по возрастанию.
Напишите программу, печатающую номер и код введенного символа в восьмеричном и шестнадцатеричном виде. Заметьте, что если вы наберете на вводе строку символов и нажмете клавишу ENTER, то программа напечатает вам на один символ больше, чем вы набрали. Дело в том, что код клавиши ENTER, завершившей ввод строки - символ '\n' тоже попадает в вашу программу (на экране он отображается как перевод курсора в начало следующей строки!).
Разберитесь, в чем состоит разница между символами '0' (цифра нуль) и '\0' (нулевой байт). Напечатайте
printf( "%d %d %c\n", '\0', '0', '0' );Поставьте опыт: что печатает программа?
main(){ int c = 060; /* код символа '0' */ printf( "%c %d %o\n", c, c, c); }Почему печатается 0 48 60? Теперь напишите вместо
int c = 060;строчку
char c = '0';
#include <stdio.h> void main(){ printf("ab\0cd\nxyz"); putchar('\n'); }Запомните, что '\0' служит признаком конца строки в памяти, а '\n' - в файле. Что в строке "abcd\n" на конце неявно уже расположен нулевой байт:
'a','b','c','d','\n','\0'Что строка "ab\0cd\nxyz" - это
'a','b','\0','c','d','\n','x','y',z','\0'
Что строка "abcd\0" - избыточна, поскольку будет иметь на конце два нулевых байта (что не вредно, но зачем?). Что printf печатает строку до нулевого байта, а не до закрывающей кавычки. Программа эта напечатает ab и перевод строки.
Вопрос: чему равен sizeof("ab\0cd\nxyz")? Ответ: 10.
Напишите программу, шифрующую текст файла путем замены значения символа (например, значение символа C заменяется на C+1 или на ~C ).
© Copyright А. Богатырев, 1992-95
Си в UNIX
Назад | Содержание | Вперед