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

Z Wikibooks, biblioteki wolnych podręczników.
< C
Usunięta treść Dodana treść
m Dodano kategorię "C" za pomocą HotCat
Linia 378: Linia 378:


</source>
</source>

[[Kategoria:C]]

Wersja z 20:58, 22 sty 2019

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.

Znajdowanie wzoru funkcji kwadratowej przechodzącej przez trzy punkty

// gcc m.c -Wall
// ./a.out

# include <stdio.h>

//
//
// znane 3 punkty : (x0,y0), (x1,y1), (x2,y2)
// dane do testów
// (3,10),(1,0),(-2,15) -> f(x)=2x^2 -3x +1   http://matematyka.pisz.pl/strona/1394.html
//   (1,−4), (2,3), (−1,0) -> f(x)=3x2−2x−5  http://matematyka.pisz.pl/forum/52119.html
// A(1,-1), B(0,0), C(-1,3): -> f(x)=x2-2x. http://www.traugutt.miasto.zgierz.pl/matma/kwadratowa.html
// (-6 ,51),(-5 , 38), (-4 , 27) -> The solution is a = 1, b = -2 and c = 3  http://answers.yahoo.com/question/index?qid=20090814183525AA26rSD
// (2 , -8),(1 , 0) (-2 , 0)  -> f(x) = -2(x - 1)(x + 2) =  - 2 x^2  - 2 x + 4  http://www.analyzemath.com/quadraticg/Tutorial1.html
// (1, 3), (−1, 4),  (2, 1) -> a = −1/2 , b = −1/2 , and c = 4 
// (−1,2), (0,3) and (1,6) -> y=x2+2x+3 http://www.amsi.org.au/ESA_Senior_Years/SeniorTopic2/2a/2a_2content_8.html



double wx[3]={3,1,-2}; // double wx[3]={x0,x1,x2};
double wy[3]={10,0,15}; // double wy[3]={y0,y1,y2};

// szukamy trójmianu kwadratowego 
// f(x) = ax^2 + bx + c 
//przechodzącego przez te 3 punkty = interpolacja kwadratowa
//
// układ 3 równań liniowych 
// z 3 niewiadomymi : a, b, c 
// a*x0^2 + b*x0 + c = y0
// a*x1^2 + b*x1 + c = y1
// a*x2^2 + b*x2 + c = y2



// układ 3 równań liniowych postaci :
// a*wi1 + b*wi2 + c*wi3 = yi
//
// win jest współczynnikiem : w 
// gdzie pierwsza cyfra i jest numerem równia ( rząd )
// druga cyfra n jest numerem kolumny ( szukanej a, b, c ) 
//
// a*w00 + b*w01 + c*w02 = y0
// a*w10 + b*w11 + c*w12 = y1
// a*w20 + b*w21 + c*w22 = y2

// wi0 = xi^2
// wi1 = xi
// wi2 = 1




// 4 macierze : 
//double ws[3][3] = {{w00,w01,w02},{w10,w11,w12}, {w20,w21,w22}};
// w kolumnie n jest yi
//double wa[3][3] = {{y0,w01,w02},{y1,w11,w12}, {y2,w21,w22}};
//double wb[3][3] = {{w00,y0,w02},{w10,y1,w12}, {w20,y2,w22}};
//double wc[3][3] = {{w00,w01,y0},{w10,w11,y1}, {w20,w21,y2}};

// a=wa/ws
// b= wb/ws
// c=wc/ws
 
 
 
 
 /*
w = wyznacznik macierzy 3x3 

1 2 3		w11 w12 w13 	a1 b1 c1  	w00 w01 w02 
4 5 6		w21 w22 w23	a2 b2 c2	w10 w11 w12 
7 8 9		w31 w32 w33	a3 b3 c3	w20 w21 w22 

det = 1*5*9       + 2*6*7       + 3*4*8       - 3*5*7       - 2*4*9       - 1*6*8 =  
det = w11*w22*w33 + w21*w32*w13 + w31*w12*w23 - w31*w22*w13 - w11*w32*w23 - w21*w12*w33;
det = a1*b2*c3    + a2*b3*c1    + a3*b1*c2    - a3*b2*c1    - a1*b3*c2    - a2*b1*c3;
det = w00*w11*w22 + w10*w21*w02 + w20*w01*w12 - w20*w11*w02 - w00*w21*w12 - w10*w01*w22;
  


http://www.sciaga.pl/tekst/41303-42-obliczanie_wyznacznikow_macierzy_c_c

test : 
1 2 3
6 5 4
3 7 2
----
63.0000


http://www.matematyka.pl/12881.htm
3 1 1
2 2 3
1 3 2
----
-12

*/
// macierze do testów funkcji DeterminatOfMatrix33
double t1[3][3] = {{1,2,3},{6,5,4},{3,7,2}}; // det = 63
double t2[3][3] = {{3,1,1},{2,2,3},{1,3,2}}; // det = -12
// w = 1*5*9       + 2*6*7       + 3*4*8       - 3*5*7       - 2*4*9       - 1*6*8 =  0
double t3[3][3] = {{1,2,3},{4,5,6},{7,8,9}}; // det = 0
double t4[3][3] = {{2,1,1},{1,-1,-1},{1,2,1}}; // det = 3  http://www.purplemath.com/modules/cramers.htm


double DeterminatOfMatrix33(double w[3][3])
{
return ( w[0][0]*w[1][1]*w[2][2] + w[1][0]*w[2][1]*w[0][2] + w[2][0]*w[0][1]*w[1][2] - w[2][0]*w[1][1]*w[0][2] - w[0][0]*w[2][1]*w[1][2] - w[1][0]*w[0][1]*w[2][2] );
  
}

// i =0 give det(wa); 
// i =1 give det(wb)
// i =2 give det(wc)
double GiveDet_n(int n, double ws[3][3], double wy[3])
{
  int i;
  double wi[3][3]; // use local copy, do not change ws !
  
 
 // copy values from ws to wi
 for (i=0; i<3; ++i)
   {
   wi[i][0]= ws[i][0];
   wi[i][1]= ws[i][1];      
   wi[i][2]= ws[i][2];		
  }
  
  // copy wy column
 for (i=0; i<3; ++i)
   wi[i][n]=wy[i];
   
 //
 printf(" w%d = {",n);
 for (i=0; i<3; ++i)
  {
   printf("{ %f ,",wi[i][0]);
   printf("%f ,",wi[i][1]);
   printf("%f }, \n",wi[i][2]);
  }  
   
   return DeterminatOfMatrix33(wi);
}


// main matrix of system of equations 
double GiveMatrixOfSystem(double wx[3], double ws[3][3])
{
 int i;
 
 printf(" ws = {");
 for (i=0; i<3; ++i)
  {
   ws[i][0]= wx[i]*wx[i]; printf("{ %f ,",ws[i][0]);
   ws[i][1]= wx[i];       printf("%f ,",ws[i][1]);
   ws[i][2]= 1;		  printf("%f }, \n",ws[i][2]);
  }
  
  

return DeterminatOfMatrix33(ws);
}


/* =================== main ============================================================*/

int main()
{

 double ws[3][3];
 double dets,deta, detb, detc;
  double a,b,c;
 
 dets = GiveMatrixOfSystem(wx,ws);
 deta = GiveDet_n(0,ws,wy);
 detb = GiveDet_n(1,ws,wy);
 detc = GiveDet_n(2,ws,wy);
 
 a = deta/dets;
 b = detb/dets;
 c = detc/dets;
 

 printf("a = %f ; b = %f ; c = %f ;\n",a,b,c);
 
 
 return 0;
}

Wybieranie ciągu z łańcucha

#include <stdio.h> // printf
/*
 gcc r.c -Wall
 time ./a.out


'0123456789012345678901'
'2345678'

/*


http://stackoverflow.com/questions/9895216/remove-character-from-string-in-c

"The idea is to keep a separate read and write pointers (pr for reading and pw for writing), 
always advance the reading pointer, and advance the writing pointer only when it's not pointing to a given character."

modified 



 remove first length2rmv chars and after that take only length2stay chars from input string
 output = input string 
*/
void extract_str(char* str, unsigned int length2rmv, unsigned long int length2stay) {
    // separate read and write pointers 
    char *pr = str; // read pointer
    char *pw = str; // write pointer
    int i =0; // index

    while (*pr) {
        if (i>length2rmv-1 && i <length2rmv+length2stay)
          pw += 1; // advance the writing pointer only when 
        pr += 1;  // always advance the reading pointer
        *pw = *pr;    
        i +=1;
    }
    *pw = '\0';
}

int main() {
    char str[] = "0123456789012345678901";
    printf("'%s'\n", str);
    extract_str(str, 2, 7); // opuszczamy 2 pierwsza znaki i wybieramy 7 następnych
    printf("'%s'\n", str);
    return 0;
}