C/Przykłady z komentarzem: Różnice pomiędzy wersjami

Z Wikibooks, biblioteki wolnych podręczników.
< C
Usunięta treść Dodana treść
Lethern (dyskusja | edycje)
revert ("czwarta potęga dwójki to 8"?)
Linia 1: Linia 1:
=== Liczby losowe ===
=== Liczby losowe ===
Poniższy program generuje wiersz po wierszu macierz o określonych przez użytkownika wymiarach, zawierającą losowo wybrane liczby. Każdy wygenerowany wiersz macierzy zapisywany jest w pliku tekstowym o wprowadzonej przez użytkownika nazwie. W pierwszym wierszu pliku wynikowego zapisano wymiary utworzonej macierzy.
Poniższy program generuje wiersz po wierszu macierz o określonych przez użytkownika wymiarach, zawierającą losowo wybrane liczby. Każdy wygenerowany wiersz macierzy zapisywany jest w pliku tekstowym o wprowadzonej przez użytkownika nazwie. W pierwszym wierszu pliku wynikowego zapisano wymiary utworzonej macierzy.
Program napisany i skompilowany został w środowisku GNU/Linux.
<source lang="c">


#include <stdio.h>
#include <[[Programowanie:C:Biblioteka standardowa:Indeks tematyczny#stdio.h|stdio.h]]>
#include <stdlib.h> /* dla funkcji rand oraz srand */
#include <[[Programowanie:C:Biblioteka standardowa:Indeks tematyczny#stdlib.h|stdlib.h]]> /* dla funkcji [[C/rand|rand()]] oraz [[C/srand|srand()]] */
#include <time.h> /* dla funkcji time */
#include <[[Programowanie:C:Biblioteka standardowa:Indeks tematyczny#time.h|time.h]]> /* dla funkcji [[C/time|time()]] */
int main()
main()
{
{
int i, j, n, m;
int i, j, n, m;
Linia 14: Linia 14:
char fileName[128];
char fileName[128];
puts("Wprowadz nazwe pliku wynikowego..");
[[C/printf|printf]]("Wprowadz nazwe pliku wynikowego..\n");
scanf("%127s",fileName);
[[C/scanf|scanf]]("%s",&fileName);
puts("Wprowadz po sobie liczbe wierszy i kolumn macierzy oddzielone spacją..");
printf("Wprowadz po sobie liczbe wierszy i kolumn macierzy oddzielone spacją..\n");
scanf("%d %d", &n, &m);
scanf("%d %d", &n, &m);
Linia 25: Linia 25:
warunek, który w kontrolowany sposób zatrzyma program (funkcja exit;)
warunek, który w kontrolowany sposób zatrzyma program (funkcja exit;)
*/
*/
if ( (fp = fopen(fileName, "w")) == NULL )
if ( (fp = [[C/fopen|fopen]](fileName, "w")) == NULL )
{
{
puts("Otwarcie pliku nie jest mozliwe!");
[[C/puts|puts]]("Otwarcie pliku nie jest mozliwe!");
exit(0);
exit; /* jeśli w procedurze glownej
to piszemy bez nawiasow */
}
}
else { puts("Plik otwarty prawidłowo.."); }
else { puts("Plik otwarty prawidłowo.."); }
fprintf(fp, "%d %d\n", n, m);
[[C/fprintf|fprintf]](fp, "%d %d\n", n, m);
/* w pierwszym wierszu umieszczono wymiary macierzy */
/* w pierwszym wierszu umieszczono wymiary macierzy */
srand( time(0) );
[[C/srand|srand]]( (unsigned int) [[C/time|time]](0) );
for (i=1; i<=n; ++i)
for (i=1; i<=n; ++i)
{
{
Linia 45: Linia 46:
if (j!=m) fprintf(fp," ");
if (j!=m) fprintf(fp," ");
}
}
fputc(fp,'\n');
fprintf(fp,"\n");
}
}
fclose(fp);
[[C/fclose|fclose]](fp);
return 0;
return 0;
}
}
</source>


=== Zamiana liczb dziesiętnych na liczby w systemie dwójkowym ===
=== Zamiana liczb dziesiętnych na liczby w systemie dwójkowym ===
Zajmijmy się teraz innym zagadnieniem. Wiemy, że komputer zapisuje wszystkie liczby w postaci binarnej (czyli za pomocą jedynek i zer). Spróbujmy zatem zamienić liczbę, zapisaną w "naszym" dziesiątkowym systemie na zapis binarny. '''Uwaga:''' Program działa jedynie dla liczb od 0 do maksymalnej wartości którą może przyjąć typ <code>unsigned short int</code> w twoim kompilatorze.
Zajmijmy się teraz innym zagadnieniem. Wiemy, że komputer zapisuje wszystkie liczby w postaci binarnej (czyli za pomocą jedynek i zer). Spróbujmy zatem zamienić liczbę, zapisaną w "naszym" dziesiątkowym systemie na zapis binarny. '''Uwaga:''' Program działa jedynie dla liczb od 0 do maksymalnej wartości którą może przyjąć typ <code>unsigned short int</code> w twoim kompilatorze.

<source lang="c">
#include <stdio.h>
#include <[[Programowanie:C:Biblioteka standardowa:Indeks tematyczny#stdio.h|stdio.h]]>
#include <limits.h>
#include <[[Programowanie:C:Biblioteka standardowa:Indeks tematyczny#limits.h|limits.h]]>
void dectobin (unsigned short a)
void dectobin (unsigned short a)
Linia 62: Linia 62:
int licznik;
int licznik;
/* czwarta potęga dwójki to 8 */
/* CHAR_BIT to liczba bitów w bajcie */
licznik = 4 << sizeof a;
licznik = CHAR_BIT * sizeof(a);
while (--licznik >= 0) {
while (--licznik >= 0) {
putchar(((a >> licznik) & 1)) ? '1' : '0');
putchar(((a >> licznik) & 1)) ? '1' : '0');
Linia 69: Linia 69:
}
}
int main (void)
int main ()
{
{
unsigned short a;
unsigned short a;
Linia 81: Linia 81:
return 0;
return 0;
}
}

</source>
=== Zalążek przeglądarki ===
Zajmiemy się tym razem inną kwestią, a mianowicie programowaniem sieci. Jest to zagadnienie bardzo ostatnio popularne. Nasz program będzie miał za zadanie połączyć się z serwerem, którego adres użytkownik będzie podawał jako pierwszy parametr programu, wysłać zapytanie HTTP i odebrać treść, którą wyśle do nas serwer. Zacznijmy może od tego, że obsługa sieci jest niemal identyczna w różnych systemach operacyjnych. Na przykład między systemami z rodziny Unix oraz Windowsem różnica polega tylko na dołączeniu innych plików nagłówkowych (dla Windowsa - winsock2.h). Przeanalizujmy zatem poniższy kod:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#define MAXRCVLEN 512
#define PORTNUM 80
char *query = "GET / HTTP1.1\n\n";
int main(int argc, char *argv[])
{
char buffer[MAXRCVLEN+1];
int len, mysocket;
struct sockaddr_in dest;
char *host_ip = NULL;
if (argc != 2) {
printf ("Podaj adres serwera!\n");
exit (1);
}
host_ip = argv[1];
mysocket = socket(AF_INET, SOCK_STREAM, 0);
dest.sin_family = AF_INET;
dest.sin_addr.s_addr = inet_addr(host_ip); /* ustawiamy adres hosta */
dest.sin_port = htons (PORTNUM); /* numer portu przechowuje dwubajtowa zmienna - musimy ustalić porządek sieciowy - Big Endian */
memset(&(dest.sin_zero), '\0', 8); /* zerowanie reszty struktury */
connect(mysocket, (struct sockaddr *)&dest,sizeof(struct sockaddr)); /* łączymy się z hostem */
write (mysocket, query, strlen(query)); /* wysyłamy zapytanie */
len=read(mysocket, buffer, MAXRCVLEN); /* i pobieramy odpowiedź */
buffer[len]='\0';
printf("Rcvd: %s",buffer);
close(mysocket); /* zamykamy gniazdo */
return EXIT_SUCCESS;
}

Powyższy przykład może być odrobinę niezrozumiały, dlatego przyda się kilka słów wyjaśnienia. Pliki nagłówkowe, które dołączamy zawierają deklarację nowych dla Ciebie funkcji - socket(), connect(), write() oraz read(). Oprócz tego spotkałeś się z nową strukturą - sockaddr_in. Wszystkie te obiekty są niezbędne do stworzenia połączenia. Aby dowiedzieć się więcej nt. wszystkich użytych tu funkcji i struktur musisz odwiedzić podręcznik o [[Programowanie w systemie UNIX|programowaniu]] w systemie UNIX.

Wersja z 07:21, 16 gru 2011

Liczby losowe

Poniższy program generuje wiersz po wierszu macierz o określonych przez użytkownika wymiarach, zawierającą losowo wybrane liczby. Każdy wygenerowany wiersz macierzy zapisywany jest w pliku tekstowym o wprowadzonej przez użytkownika nazwie. W pierwszym wierszu pliku wynikowego zapisano wymiary utworzonej macierzy. Program napisany i skompilowany został w środowisku GNU/Linux.

#include <stdio.h>
#include <stdlib.h>  /* dla funkcji rand() oraz srand() */
#include <time.h>	 /* dla funkcji time() */

main()
{
  int i, j, n, m;
  float re;
  FILE *fp;
  char fileName[128];

  printf("Wprowadz nazwe pliku wynikowego..\n");
  scanf("%s",&fileName);

  printf("Wprowadz po sobie liczbe wierszy i kolumn macierzy oddzielone spacją..\n");
  scanf("%d %d", &n, &m);

           /* jeżeli wystąpił błąd w otwieraniu pliku i go nie otwarto,
            wówczas funkcja fclose(fp) wywołana na końcu programu zgłosi błąd
            wykonania i wysypie nam program z działania, stąd musimy umieścić
            warunek, który w kontrolowany sposób zatrzyma program (funkcja exit;)
           */
  if ( (fp = fopen(fileName, "w")) == NULL )  
  {
    puts("Otwarcie pliku nie jest mozliwe!");
    exit;    /*  jeśli w procedurze glownej
              to piszemy bez nawiasow */
  }

  else  { puts("Plik otwarty prawidłowo..");  }
  
  fprintf(fp, "%d %d\n", n, m);
          /* w pierwszym wierszu umieszczono wymiary macierzy */

  srand( (unsigned int) time(0) );
  for (i=1; i<=n; ++i)
  {
    for (j=1; j<=m; ++j)
    {
      re = ((rand() % 200)-100)/ 10.0;
      fprintf(fp,"%.1f", re );
      if (j!=m) fprintf(fp,"    ");
    }
  fprintf(fp,"\n");
  }  
  fclose(fp);
  return 0;
}

Zamiana liczb dziesiętnych na liczby w systemie dwójkowym

Zajmijmy się teraz innym zagadnieniem. Wiemy, że komputer zapisuje wszystkie liczby w postaci binarnej (czyli za pomocą jedynek i zer). Spróbujmy zatem zamienić liczbę, zapisaną w "naszym" dziesiątkowym systemie na zapis binarny. Uwaga: Program działa jedynie dla liczb od 0 do maksymalnej wartości którą może przyjąć typ unsigned short int w twoim kompilatorze.

#include <stdio.h>
#include <limits.h>

void dectobin (unsigned short a)
{
  int licznik;      

  /* CHAR_BIT to liczba bitów w bajcie */
  licznik = CHAR_BIT * sizeof(a);
  while (--licznik >= 0) {
    putchar(((a >> licznik) & 1)) ? '1' : '0');
  }
}

int main ()
{
  unsigned short a;

  printf ("Podaj liczbę od 0 do %hd: ", USHRT_MAX);
  scanf ("%hd", &a);
  printf ("%hd(10) = ", a);
  dectobin(a);
  printf ("(2)\n");

  return 0;
}

Zalążek przeglądarki

Zajmiemy się tym razem inną kwestią, a mianowicie programowaniem sieci. Jest to zagadnienie bardzo ostatnio popularne. Nasz program będzie miał za zadanie połączyć się z serwerem, którego adres użytkownik będzie podawał jako pierwszy parametr programu, wysłać zapytanie HTTP i odebrać treść, którą wyśle do nas serwer. Zacznijmy może od tego, że obsługa sieci jest niemal identyczna w różnych systemach operacyjnych. Na przykład między systemami z rodziny Unix oraz Windowsem różnica polega tylko na dołączeniu innych plików nagłówkowych (dla Windowsa - winsock2.h). Przeanalizujmy zatem poniższy kod:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>

#define MAXRCVLEN 512
#define PORTNUM 80

char *query = "GET / HTTP1.1\n\n";

int main(int argc, char *argv[])
{
  char buffer[MAXRCVLEN+1];
  int len, mysocket;
  struct sockaddr_in dest; 
  char *host_ip = NULL;
  if (argc != 2) {
    printf ("Podaj adres serwera!\n");
    exit (1);
    }
  host_ip = argv[1];
  mysocket = socket(AF_INET, SOCK_STREAM, 0);

  dest.sin_family = AF_INET; 
  dest.sin_addr.s_addr = inet_addr(host_ip); /* ustawiamy adres hosta */
  dest.sin_port = htons (PORTNUM); /* numer portu przechowuje dwubajtowa zmienna - musimy ustalić porządek sieciowy - Big Endian */
  memset(&(dest.sin_zero), '\0', 8); /* zerowanie reszty struktury */

  connect(mysocket, (struct sockaddr *)&dest,sizeof(struct sockaddr)); /* łączymy się z hostem */
  write (mysocket, query, strlen(query)); /* wysyłamy zapytanie */
  len=read(mysocket, buffer, MAXRCVLEN); /* i pobieramy odpowiedź */

  buffer[len]='\0';

  printf("Rcvd: %s",buffer);
  close(mysocket); /* zamykamy gniazdo */
  return EXIT_SUCCESS;
}

Powyższy przykład może być odrobinę niezrozumiały, dlatego przyda się kilka słów wyjaśnienia. Pliki nagłówkowe, które dołączamy zawierają deklarację nowych dla Ciebie funkcji - socket(), connect(), write() oraz read(). Oprócz tego spotkałeś się z nową strukturą - sockaddr_in. Wszystkie te obiekty są niezbędne do stworzenia połączenia. Aby dowiedzieć się więcej nt. wszystkich użytych tu funkcji i struktur musisz odwiedzić podręcznik o programowaniu w systemie UNIX.