LinuxForum.Fans
Тема

Как написать первую программу на С ?

Автор: drBatty 70 сообщений 64401 просмотров 📌 закреплена
13.11.2010 23:13 · отредактировано #98783

Единственный способ освоить новый язык
программирования - писать на нем программы. Первая програм-
ма, которая должна быть написана, - одна для всех языков:
напечатать слова : HELLO, WORLD.
Это - самый существенный барьер; чтобы преодолеть его,
вы должны суметь завести где-то текст программы, успешно его
скомпилировать, загрузить, прогнать и найти, где оказалась
ваша выдача. Если вы научились справляться с этими техничес-
кими деталями, все остальное сравнительно просто.



Керниган, Ричи. Язык С.


Итак. Нам потребуется текстовый редактор(vim), компилятор(gcc), и make. Ещё потребуется линковщик (ld).
Как это найти - зависит от дистрибутива, в Slackware это добро лежит в d/

1) создаём каталог для нашего проекта:
[console]doc@bx:~$ mkdir -pv projects/first_program
mkdir: создан каталог `projects/first_program'
doc@bx:~$ cd !$
cd projects/first_program
doc@bx:~/projects/first_program$
[/console]

2) запускаем vim, и пишем

text
#include <stdio.h> /*это заголовочный файл. */
/* Там лежат объявления функций. Нам понадобится printf */
/* про эту функцию можно почитать в man'е. */
/* Беда в том, что в bash тоже есть такая функция */
/* потому набирайте man 3 printf */

int main(void) /* наша функция. она не имеет параметров,*/ /*но возвращает значение */ { printf("Привет Мир!\n"); /* вывод сообщения */ return 0; /* выход. 0 - успешное завершение */ }

3) теперь собираем:
[console]doc@bx:~/projects/first_program$ gcc -Wall -O3 -o hello main.c [/console]
объяснения ключей:
-Wall - все ошибки выводятся.
-O3 самая сильная оптимизация
-o hello имя нашей программы
main.c созданный нами файл

*примечание: можно собирать открыв ещё одну консоль. А в виме можно перейти в командный режим и набрать команду vim'а !, и сразу после неё команду shella
[console]:!gcc -Wall -O3 -o hello main.c [/console]
конечно это работает в любом хорошем редакторе.

4) Запускаем нашу программу:
[console]doc@bx:~/projects/first_program$ ./hello
Привет Мир!
[/console]

а про make я вам завтра расскажу. Если это кому-то интересно...

13.11.2010 23:30 #98786

Как использовать vim?

Вход в режим редактирования осуществляется кнопкой i.
Выход - кнопкой ESC
в нормальном режиме можно всё сохранить командой :w
выход из нормального режима :q

Полезно:
Копировать строку yy
поиск и замена :%s/маша/таня/gci
Здесь: % значит - по всему тексту
s - команда замены
маша - что ищем
таня - на что меняем
g значит "все вхождения в строке"
c с вопросами
i регистро НеЗаВиСиМо

для кодеров очень полезно выделение блока (CTRL+V) и ещё вставка (I) перед блоком.
команда :set number (используйте автодополнение!) включает номера строк
gv включает прошлый блок

Автодополнение: обычно я использую CTRL+N, но есть и CTRL+X+...

вкладки: zo открыть, zc закрыть и т.д. Незаменимая фича для кодера.

13.11.2010 23:38 #98788

Окна в vim'е

Угу. консольная прога поддерживает окошки.

можно открыть второй файл командой :split файл это разбиение по вертикали. По горизонтали :vsplit
переключатся можно используя CTRL+W+W (есть и ещё 100500 команд)

А ещё есть вкладки, aka табы. Для их открытия наберите :tabnew файл
Лично я юзаю и то и другое.

13.11.2010 23:46 #98790

Подсветка синтакса.

Это великая вещь. Без неё никуда. Включается командой :syntax on. в vim работает поддержка ВСЕХ языков программирования, в т.ч. даже такой экзотики как sed. Впрочем, мы про C, а он конечно тоже подсвечивается. Как и C++.

Ну и автоотступы - Хорошая Мысль. Оно тоже работает.

14.11.2010 16:37 #98936

К вышеперечисленным опциям gcc стоит добавить
-std=c89 - достаточно для K&R
-std=c99 - для ANSI/ISO C 99.

Чтобы не набирать каждый раз всю эту красоту для вызова gcc,
можно, например, добавить в .bashrc, который лежит в вашем домашнем каталоге,
такую строчку:
alias c99='gcc -std=c99 -Wall -O3'

потом сделать
~ $ source .bashrc

и "девушка созрела":
теперь можно осуществлять компиляцию командой
~ $ c99 -o <e_name> <s_name.c>

Для учебных целей представляется уместным выделить под ваши программы отдельный каталог:
~ $ mkdir <c_progs>

Если нет необходимости хранить скомпилированными все ваши учебные программы,
можно ещё упростить себе жизнь:

в тот же .bashrc добавить строчку
alias run='./a.out'

перед началом деятельности уходить в связанный с ней каталог:
~ $ cd <c_progs>

запускать компиляцию командой
~ $ c99 <s_name.c>
получая на выходе каждый раз новый a.out в вашем каталоге <c_progs>,
и запускать его на выполнение командой
~ $ run

На вашем терминале приглашение ОСи может выглядеть несколько отличным от ~ $.

Угловые скобки в названиях файлов и каталогов - не используем.

Кстати, о терминалах smile

Если всё получилось с компиляцией первых программ на С,
и вам захотелось выжать из вашей командной строки всё, что она может
(а может она совсем не мало),

возможно, стоит обратиться к nCurses.

Для gcc нет conio.h, и не будет,
потому что для полного управления терминалом в *nix'ах используется библиотека nCurses.

Но поговорим об этом чуть позже, одолев основы С.

Доктор, алаверды smile

14.11.2010 17:55 #98953

Мужики, продолжайте... пожалуйста. Мне это очень интересно... Как раз есть в планах написать маленькую программу :) А я все забыл, давно не програмил wink Со школы так сказать. Тем паче всегда хотелось поковыряться в С

14.11.2010 19:54 #98998

Chars67, Спасибо! Плюсик поставил.

xlin написал:
Мужики, продолжайте... пожалуйста. Мне это очень интересно...

мне тоже. в планах
make & mercurial

15.11.2010 23:57 #99419

Чтобы не отставать в разговоре про первую программу,

в число опций gcc добавим -lncurses и скомпилируем такой код:

text

#include <ncurses.h>

int main(void) { initscr();

addstr("Hello, C with nCurses world!!!\n") // вызов addstr можно заменить на printw refresh();

getch(); // вовсе не обязательный вызов, но об этом - позже endwin(); return 0; }

Вызовы initscr(), refresh() и endwin() обязательны для адекватной работы любой программы,

обращающейся к библиотеке nCurses.

Возможно, вам покажется занятным попытаться обойтись без них.
Ну так результаты тоже будут "занятными".

Если говорить более конструктивно, то попробуйте убрать getch(),
и сравните результаты работы программы в "окне терминала" под Иксами,
и в виртуальной консоли (которая Alt-F1..Alt-F6).

Собственно, дальше можно обратиться к
Dan Gookin
"Programmer's Guide to nCurses"
2007
,
к man'ам и faq'ам по данной библиотеке.

Или здесь найдём о чём потолковать, разбираясь с ней дальше.

smile Просто это будет уже не первая программа

16.11.2010 03:04 #99449

alias'ы конечно хорошо, но я использую make. Что это такое, и зачем оно надо? эта утилитка собирает проект из исходных файлов. я добавил в свой простой проект ещё один файл, с одной функцией. Точнее 2 файла:

text
#include <stdio.h>

#include "other.h"

int my_printf(char *s) { int return_code; return_code = printf("%s\n", s); return return_code; }

это файл other.c

а вот второй (other.h):

text
#ifndef OTHER_H
#define OTHER_H

int my_printf(char *s);

#endif /* OTHER_H */

файл main.c теперь принял такой вид:

text
#include "other.h"

int main(void) { my_printf("Привет, мир!"); return 0; }

теперь у меня сначала собираются 2 модуля, а потом они уже линкуются (по-русски "связываются") в законченную программу. Ну а что-бы это всё собирать, используется утилита make, и Makefile к ней:

text
CC = gcc
CFLAGS = -Wall -g
# CFLAGS = -Wall -O2
LDFLAGS =

OBJECTS = main.o other.o TARGET = helloworld

RM = rm -f INSTALL = /usr/bin/install -c

BINDIR = /usr/local/bin

$(TARGET): $(OBJECTS) $(CC) $(LDFLAGS) -o $@ $(OBJECTS)

%.o: %.c $(CC) $(CFLAGS) -c $<

main.o: main.c other.h other.o: other.c other.h

clean: $(RM) $(OBJECTS) $(TARGET)

install: $(TARGET) $(INSTALL) $(TARGET) $(BINDIR)

вот теперь всё по взрослому.

В переменной $(OBJECTS) прописаны все 2 моих объектных файла, а в строчках

text
main.o: main.c other.h
other.o: other.c other.h

прописано, от чего они зависят. собирается это всё командой
[console]make[/console]
без всяких параметров. тут дана отладочная версия, но вы можете прописать и другие ключики в $(FLAGS)
я советовал -O3, но с этим ключём некоторые программы могут и не заработать (слишком сильная оптимизация. Хотя у меня работает).
выглядит это так
[console]doc@bx:~/docs/projects/HelloWorld$ make
gcc -Wall -g -c -o main.o main.c
gcc -Wall -g -c -o other.o other.c
gcc -o helloworld main.o other.o
doc@bx:~/docs/projects/HelloWorld$ ./helloworld
Привет, мир!
[/console]
если изменить other.c
то пересоберётся лишь модуль other.o
[console]doc@bx:~/docs/projects/HelloWorld$ make
gcc -Wall -g -c -o other.o other.c
gcc -o helloworld main.o other.o
[/console]
а второй модуль не будет пересобираться (main.o), это здорово ускоряет сборку (что важно, ибо с первого раза лично у меня ничего не работает)

конечно для первой программы это и не нужно, но вам, уважаемые читатели, наверное не такой примитив придётся делать в реальной жизни?

16.11.2010 03:24 #99450

забыл сказать - в Makefile в строчках

text
$(TARGET): $(OBJECTS)
    $(CC) $(LDFLAGS) -o $@ $(OBJECTS)

%.o: %.cpp $(CC) $(CFLAGS) -c $<

должны быть табуляции, а не пробелы (как видимо их заменит движок форума). В интернетах пишут, что пробелы make не любит...

Вообще говоря, make собирает цели. цель по умолчанию у меня helloworld, но есть ещё make clean, для того, что-бы удалить все результаты работы make

text
doc@bx:~/docs/projects/HelloWorld$ make clean
rm -f main.o other.o helloworld

теперь make будет пересобирать всё с нуля.

Есть ещё и цель install, для установки нашего приложения в систему (что НЕ рекомендуется, а рекомендуется собрать пакет. Это уже дистроспецифично).

22.01.2011 07:13 #119616

Если кто-то захочет посмотреть примеры решения простых задач на Си, то пожалуйста:
http://cirishen.blogspot.com/
Чем богаты. :-)

22.01.2011 07:49 · отредактировано #119617

drBatty, а СMake'а в планах нет?
[added]
Эх... не посмотрел на дату старта топика...=\

22.01.2011 10:56 #119635
Fat-Zer написал:
а СMake'а в планах нет?

будет... потом.

22.01.2011 13:02 #119674

если будут продолжения то эт здорово.

22.01.2011 13:39 #119692

про cmake писать сложно... это ОЧЕНЬ далеко от темы (первая программа). нужно отдельную тему заводить, а может и отдельный раздел (ИМХО я не вижу особых преимуществ у CMake, кроме кроссплатформенности).

Вот неплохой мануал на эту тему: http://symmetrica.net/cmake/CMake-1.htm

23.01.2011 09:28 · отредактировано #119911
drBatty написал:
про cmake писать сложно... это ОЧЕНЬ далеко от темы (первая программа). нужно отдельную тему заводить, а может и отдельный раздел (ИМХО я не вижу особых преимуществ у CMake, кроме кроссплатформенности).

в начале ветке в планах был обозначен mercurial, а это, пожалуй, ещё дальше от первой программы. Вот и подумал, что... ну да ладно... Спасибо за линк.
cmake'ом просто заинтересовался, ибо один знакомый недавно меня спросил как им пользоваться, и вообще что это и с чем его едят...

ЗЫ: ещё было бы интересно почитать про valgrid, automake/autoconf. Но всё это когда время будет...

11.03.2011 23:39 #139123

а не проще написать
cout<<"hello, world";

11.03.2011 23:41 #139124
kosmo26 написал:
а не проще написать
cout<<"hello, world";

Это уже не С, это С++

12.03.2011 13:41 #139225
kosmo26 написал:
а не проще написать
cout<<"hello, world";

нет, ибо не работает. попробуйте сами просто сменить в моём коде мою строчку на вашу.
на самом деле, перезагруженный operator<<() это совсем не просто, несмотря на то, что мало букв.

durc написал:
Это уже не С, это С++

это ещё и ООП - вместо функционального программирования используется объектно ориентированное.

19.04.2011 21:45 #153267

А вот в самом начале во втором пункте надо было написать этот код в Vim я написал чего с ним дальше то делать ? почему сразу идет переход к 3 пункту!?
Простите новичка!!!

Войдите или зарегистрируйтесь, чтобы ответить.