Tema 2 · Variables, tipus, operadors
Introducció
Tot programa necessita emmagatzemar dades. En C, les variables són contenidors amb un tipus definit (enter, decimal, caràcter...).
Amb scanf() podem llegir dades de l'usuari i amb printf() les mostrem per pantalla.
Objectius
- Declarar variables dels tipus
int,float,char - Utilitzar
scanf()per llegir dades del teclat - Mostrar resultats amb
printf()i caràcters de format - Dissenyar un petit conversor d'ADN a ARN
Variables i entrada/sortida
Exemple bàsic amb diferents tipus de dades:
#include <stdio.h>
int main() {
int edat = 20;
float pes = 65.5;
char grup_sanguini = 'A';
printf("Edat: %d anys\n", edat);
printf("Pes: %.1f kg\n", pes);
printf("Grup sanguini: %c\n", grup_sanguini);
return 0;
}
%d = enter, %f = float, %c = char
Ara llegim dades des del teclat amb scanf():
#include <stdio.h>
int main() {
char base_nitrogenada;
printf("Introdueix una base (A, C, G, T): ");
scanf(" %c", &base_nitrogenada); // l'espai abans de %c evita problemes
printf("Has introduït: %c\n", base_nitrogenada);
return 0;
}
& davant la variable en scanf()
Tipus primitius en profunditat
El llenguatge C disposa de diversos tipus primitius per emmagatzemar nombres enters, decimals i caràcters.
A més, podem saber quanta memòria ocupa cada variable mitjançant l'operador sizeof(),
que retorna el nombre de bytes. Per imprimir aquest valor fem servir el format %zu.
#include <stdio.h>
#include <stdbool.h>
int main() {
char inicial = 'F';
unsigned char lletra = 'A';
short any = 2025;
int edat = 16;
long poblacio = 8000000;
long long estrelles = 900000000000LL;
float nota = 8.5f;
double pi = 3.14159265359;
long double precisio = 3.14159265359L;
bool aprovat = true;
bool suspes = false;
// Mostra els valors
printf("char = %c\n", inicial);
printf("unsigned char = %c\n", lletra);
printf("short = %d\n", any);
printf("int = %d\n", edat);
printf("long = %ld\n", poblacio);
printf("long long = %lld\n", estrelles);
printf("float = %.1f\n", nota);
printf("double = %.10f\n", pi);
printf("long double = %.10Lf\n", precisio);
printf("aprovat = %d\n", aprovat);
printf("suspes = %d\n", suspes);
if(aprovat){
printf("L'alumne ha aprovat\n");
}
if(!suspes){
printf("L'alumne no ha suspes\n");
}
// Mostra les mides amb sizeof i %zu
printf("\n--- Mides en bytes ---\n");
printf("sizeof(char) = %zu\n", sizeof(inicial));
printf("sizeof(unsigned char)= %zu\n", sizeof(lletra));
printf("sizeof(short) = %zu\n", sizeof(any));
printf("sizeof(int) = %zu\n", sizeof(edat));
printf("sizeof(long) = %zu\n", sizeof(poblacio));
printf("sizeof(long long) = %zu\n", sizeof(estrelles));
printf("sizeof(float) = %zu\n", sizeof(nota));
printf("sizeof(double) = %zu\n", sizeof(pi));
printf("sizeof(long double) = %zu\n", sizeof(precisio));
printf("sizeof(bool) = %zu\n", sizeof(aprovat));
return 0;
}
%zu és el format per a size_t (resultat de sizeof)
Explicació
- Tipus enters:
char(1 byte),short(2),int(4),long(4 o 8 segons plataforma),long long(8). Elsunsignedno tenen signe. - Tipus reals:
float(4),double(8),long double(8, 12 o 16 segons plataforma). - Booleans:
bool(1 byte) amb valorstrue(1) ofalse(0). sizeofés un operador que es calcula en temps de compilació i retorna el nombre de bytes.
Formats per a floats: amplada i precisió
Quan imprimim nombres decimals amb printf(), podem controlar el nombre de decimals (precisió) i l'amplada mínima total del camp.
A continuació es mostren els formats més habituals:
#include <stdio.h>
int main() {
float nota = 8.5f;
double pi = 3.14159265359;
printf("Valor original de nota (float): %f\n", nota);
printf("Amb 3 decimals (%.3f): %.3f\n", nota, nota);
printf("Amplada mínima 3 sense decimals (%3.f): %3.f\n", nota, nota);
printf("Amplada 6 i 2 decimals (%6.2f): %6.2f\n", nota, nota);
printf("Amplada 3 i 3 decimals (%3.3f): %3.3f\n", nota, nota);
printf("Només amplada sense punt (%3f): %3f\n", nota); // %3f = amplada 3, decimals per defecte (6)
printf("\nPer a double (pi):\n");
printf("Sense formatar: %f\n", pi);
printf("Amb 5 decimals: %.5f\n", pi);
printf("Amplada 10 i 4 decimals: %10.4f\n", pi);
return 0;
}
Què significa cada format?
%f→ 6 decimals per defecte.%.nf→ n decimals. Ex:%.3f→ 3 decimals.%m.f→ amplada mínima m (inclou el signe, el punt i els decimals). Si el nombre ocupa menys, s'omple amb espais a l'esquerra. Ex:%6.2f→ mínim 6 caràcters, 2 decimals.%m.fsense precisió (ex:%3.f) equival a%3.0f(0 decimals).%mf(sense punt) → amplada mínima m, però la precisió es manté a 6 decimals. Ex:%3f→ amplada 3, 6 decimals.- Important:
%f3no és vàlid; el compilador ho interpreta com%fseguit del caràcter '3' literal.
Exemple de sortida (per al primer bloc):
Valor original de nota (float): 8.500000
Amb 3 decimals (%.3f): 8.500
Amplada mínima 3 sense decimals (%3.f): 9
Amplada 6 i 2 decimals (%6.2f): 8.50
Amplada 3 i 3 decimals (%3.3f): 8.500
Només amplada sense punt (%3f): 8.500000
Operadors en C
Els operadors ens permeten realitzar càlculs, comparacions i decisions lògiques. A continuació es mostra un programa que utilitza tots els grups principals: aritmètics, d'assignació, increment/decrement, relacionals, lògics i, per a nivells més avançats, operadors de bits.
#include <stdio.h>
#include <stdbool.h>
int main() {
// 1. Operadors aritmètics
int a = 10, b = 3;
printf("--- Aritmètics ---\n");
printf("a + b = %d\n", a + b);
printf("a - b = %d\n", a - b);
printf("a * b = %d\n", a * b);
printf("a / b = %d (divisió entera)\n", a / b);
printf("a %% b = %d (mòdul)\n", a % b);
// 2. Operadors d'assignació
int c = 5;
printf("\n--- Assignació ---\n");
printf("c = %d\n", c);
c += 3; // c = c + 3
printf("c += 3 -> c = %d\n", c);
c -= 2; // c = c - 2
printf("c -= 2 -> c = %d\n", c);
c *= 2; // c = c * 2
printf("c *= 2 -> c = %d\n", c);
c /= 3; // c = c / 3
printf("c /= 3 -> c = %d\n", c);
c %= 4; // c = c % 4
printf("c %%= 4 -> c = %d\n", c);
// 3. Increment i decrement
int d = 7;
printf("\n--- Increment / Decrement ---\n");
printf("d = %d\n", d);
printf("d++ (post-increment) = %d, després d = %d\n", d++, d);
printf("++d (pre-increment) = %d, després d = %d\n", ++d, d);
printf("d-- (post-decrement) = %d, després d = %d\n", d--, d);
printf("--d (pre-decrement) = %d, després d = %d\n", --d, d);
// 4. Operadors relacionals (comparació)
int x = 8, y = 12;
printf("\n--- Relacionals ---\n");
printf("x = %d, y = %d\n", x, y);
printf("x == y -> %d\n", x == y);
printf("x != y -> %d\n", x != y);
printf("x > y -> %d\n", x > y);
printf("x < y -> %d\n", x < y);
printf("x >= y -> %d\n", x >= y);
printf("x <= y -> %d\n", x <= y);
// 5. Operadors lògics
bool p = true, q = false;
printf("\n--- Lògics ---\n");
printf("p = %d, q = %d\n", p, q);
printf("p && q -> %d (AND)\n", p && q);
printf("p || q -> %d (OR)\n", p || q);
printf("!p -> %d (NOT)\n", !p);
printf("(x > 5) && (y < 15) -> %d\n", (x > 5) && (y < 15));
// 6. Operadors de bits (avançat)
unsigned int mask = 0x0F; // 0000 1111
unsigned int valor = 0x3A; // 0011 1010
printf("\n--- Bits (avançat) ---\n");
printf("mask = 0x%X, valor = 0x%X\n", mask, valor);
printf("valor & mask = 0x%X (AND)\n", valor & mask);
printf("valor | mask = 0x%X (OR)\n", valor | mask);
printf("valor ^ mask = 0x%X (XOR)\n", valor ^ mask);
printf("~valor = 0x%X (NOT)\n", ~valor);
printf("valor << 2 = 0x%X (desplaçament esquerra)\n", valor << 2);
printf("valor >> 1 = 0x%X (desplaçament dreta)\n", valor >> 1);
return 0;
}
Explicació de cada grup
- Aritmètics:
+ - * / %(suma, resta, multiplicació, divisió entera, mòdul). - Assignació:
=i les variants+=, -=, *=, /=, %=(operació i assignació en un sol pas). - Increment / Decrement:
++(augmentar 1),--(disminuir 1).
Pre (++x) primer canvia el valor i després l'utilitza; post (x++) primer l'utilitza i després canvia. - Relacionals (comparació):
==, !=, >, <, >=, <=retornen 1 (cert) o 0 (fals). - Lògics:
&&(AND),||(OR),!(NOT). S'usen per combinar condicions. - Bits (avançat):
&(AND),|(OR),^(XOR),~(NOT),<<(desplaçament esquerra),>>(desplaçament dreta). Treballen a nivell de bits, útil per a màscares i optimitzacions.
En C, el resultat d'una comparació o operació lògica és int (1 o 0), però es pot assignar a bool si s'inclou <stdbool.h>.
Exercicis
- Declara una variable
intper a l'edat d'un pacient i mostra-la ambprintf(). - Llegeix el nom del mateix gen del tema 1 (cadena de text) amb
scanf()i imprimeix-lo. - Escriu un programa que demani el %GC d'una seqüència (float) corresponent al teu gen anterior i el mostri amb dos decimals.
- Fes un programa que, donats dos enters, mostri la suma, la resta, el producte, la divisió entera i el mòdul.
Mini Projecte – Conversor ADN → ARN
Crea un programa que lligi una base nitrogenada d'ADN (A, C, G, T) i mostri la base complementària d'ARN:
- A (ADN) → U (ARN)
- C → G
- G → C
- T → A
Després amplia el programa per a convertir una seqüència sencera de 3 bases (ex: "ATG" → "UAC").