Tömb eleme
Írj függvényt, amely átvesz egy double
tömböt, és visszatér a 4-es indexű elemével,
ha az létezik, különben 0-val!
Megoldás
A C-ben, ha egy tömböt átadunk paraméterként, akkor csak az első
elemének (nullás indexű elemének) a címe adódik át a függvénynek.
Ebből az is következik, hogy a függvény nem tudja, mekkora az a
tömb, vagyis azt is át kell adni, külön paraméterként. A függvény
paramétereinek típusa ezért double*
, a tömb elejére mutató
pointer, és még egy int
, amelyik pedig a tömb mérete.
Hogy létezik-e a tömb 4-es indexű eleme, azt pedig ebből a méret
változóból tudjuk.
double fv(double *t, int meret) {
if (meret > 4)
return t[4];
else
return 0;
}
Tömb összege
Készíts függvényt, mely egy valós számokból álló tömb elemeit összegzi!
Alig változik
Készíts függvényt, mely a paraméterben kapott egész tömbről megvizsgálja, hogy elemeinek értéke szomszédos elemek E sugaron belül helyezkednek el (különbségük nem nagyobb, mint E vagy -E) A függvény bemenő paramétere a tömbre mutató pointer, a tömb elemeinek száma, valamint az E értéke. Visszatérési értéke logikai típusú legyen, amely azt mutatja, teljesült-e a feltétel!
Legalább kettő előfordulás
Írj függvényt, amely paraméterként vesz át egy egészekből álló tömböt, és visszaadja az első olyan tömbelem címét, amelyből legalább kettő található a tömbben! Ha nincs ilyen tömbelem, adjon vissza NULL pointert!
Megoldás
int *dupla(int *tomb, int n) {
for (int i = 0; i < n - 1; i++)
for (int j = i + 1; j < n; j++)
if (tomb[i] == tomb[j])
return tomb + i;
return NULL;
}
Minden második
Írj függvényt, ami egy tömböt átvesz paraméterként, és hátulról indulva kiírja minden második elemét! Ügyelj arra, hogy nehogy túl/alulindexeld a tömböt!
Rendezett-e
Írj függvényt, amely paraméterként vesz át egy valós értékekből álló tömböt, melyről biztosan tudjuk, hogy elemei különbözőek! A függvény ellenőrizze, hogy a tömb rendezett-e (akár növekvő, akár csökkenő sorrendben; a feltételezett rendezettség iránya az első két tömbelem vizsgálatával eldönthető). Ha a tömb nem rendezett, a függvény adja vissza az első olyan tömbelem címét, amelyik elrontja a rendezettséget! Ha a tömb rendezett, adjon vissza NULL pointert! Pl. be: {-8.11, -5.3, 0.1, 2.5, 1.4, 6.9, 12.0, 5.7}, a visszaadott érték az 1.4-et tartalmazó tömbelem címe. Pl. be: {7, 1, 2, 3, 4, 5}, a visszaadott érték a 2-t tartalmazó tömbelem címe.
Megoldás
double *rendezette(double *tomb, int n) {
if (n < 2) return NULL;
bool novekvo = tomb[0] < tomb[1];
if (novekvo) {
for (int i = 2; i < n; i++) {
if (tomb[i - 1] > tomb[i])
return tomb + i;
}
} else {
for (int i = 2; i < n; i++) {
if (tomb[i - 1] < tomb[i])
return tomb + i;
}
}
return NULL;
}
Legnagyobb
Készíts függvényt, amely paraméterként vesz át egy egész számokból álló tömböt, és visszaadja a tömb legnagyobb elemének indexét! Egészítsd ki teljes programmá, amely kiírja a legnagyobb tömbelemet! (A kiírást ne a maximumkereső függvény végezze!)
Alakítsd át a programot úgy, hogy ne a legnagyobb elem indexét, hanem annak memóriacímét adja vissza a függvény!
Megoldás
#include <stdio.h>
int max(int *t, int elemszam) {
int maxidx = 0; /* Feltételezzük, hogy van legalább egy eleme */
for (int i = 1; i < elemszam; ++i)
if (t[i] > t[maxidx])
maxidx = i; /* Ha találunk nagyobbat, megjegyezzük az indexét */
return maxidx; /* Visszaadjuk a maximumot */
}
int* maxcim(int *t, int elemszam) {
int maxidx = 0; /* Feltételezzük, hogy van legalább egy eleme */
for (int i = 1; i < elemszam; ++i)
if (t[i] > t[maxidx])
maxidx = i; /* Ha találunk nagyobbat, megjegyezzük az indexét */
return &t[maxidx]; /* Visszaadjuk a címét. return t+maxidx is jó. */
}
int main(void) {
int tomb[5] = {1,5,3,9,8};
printf("%d\n", tomb[max(tomb, 5)]);
printf("%d\n", *maxcim(tomb, 5));
return 0;
}
Alakítsd át úgy is a programot, hogy a ciklusok tömbindexek helyett pointerekkel dolgozzanak, az előadáson bemutatott módon.
Megoldás
int max(int *t, int elemszam) {
int *max = t;
for (int *p = t+1; p != t+elemszam; ++p)
if (*p > *max)
max = p;
return *max;
}
Legkisebb és legnagyobb
Írj függvényt, amely paraméterként vesz át egy egészekből álló tömböt! A függvény adja vissza címükkel átvett változókban a tömb legkisebb és legnagyobb elemének indexét! Ha több egyforma érték a legkisebb/legnagyobb, akkor ezek közül bármelyik indexét visszaadhatja.
Megoldás
A minimum- és maximumkeresésben használt indexhez illik lokális változót használni, és csak a függvény végén betenni az eredményt a cím szerint átvett változókba. Ennek okai:
- Egyszerűbb a kód, nincs tele
*pmin
és*pmax
kifejezésekkel. - Áttekinthetőbb is.
- Gyorsabb is, mivel a keresős ciklus lokális változókkal dolgozik, nem pedig indirekten elér változókkal.
void minmax(int *tomb, int n, int *pmin, int *pmax) {
int min = 0, max = 0;
for (int i = 1; i < n; i++) {
if (tomb[i] < tomb[min]) min = i;
if (tomb[i] > tomb[max]) max = i;
}
*pmin = min;
*pmax = max;
}
Súlypont
Készíts struktúratípust, amely alkalmas egy térbeli pont koordinátáinak eltárolására (x, y, z koordinálta). Írj függvényt, amely átvesz egy térbeli pontokból álló tömböt, és visszaadja a pontok súlypontját (azaz azt a pontot, amelynek a koordiátáit a bemenő pontok megfelelő koordinátáinak átlagai)! Próbáld ki a függvényt teljes programmá kiegészítve!
Hány egyedi elem van?
Készíts függvényt, mely egy adott tömbben megszámolja, hogy hány olyan elem van, amely csak egyszer fordul elő! Pl. a { 2, 7, 5, 8, 9, 5, 7, 5, 5, 3 } tömbre a visszatérési érték legyen 4, mert a { 2, 3, 8, 9 } számok mind csak egyszer szerepeltek! (Használhatod a Legalább kettő feladatban elkészült függvényt.)
A leggyakoribb elem
Készíts függvényt, mely meghatározza egy adott (véletlen számokkal feltöltött) tömbben, hogy melyik értékből található benne a legtöbb! Pl. ha a tömb elemei { 2, 7, 5, 8, 9, 5, 7, 5, 5, 3 }, akkor a függvény visszatérési értéke legyen 5, mivel az a leggyakoribb elem.
Rendezettség vizsgálata
Írj egy függvényt, amelyik egy double számokból álló tömböt vesz át paraméterként. A
függvény térjen vissza egy felsorolt típussal, amelynek lehetséges értékei: csokkeno
, ha a tömbben lévő számsorozat szigorúan monoton csökken; novekvo
, ha szigorúan
monoton nő; osszevissza
, ha egyik sem igaz rá. Írj egy programrészt, amelyik
definiál egy tömböt, és kiírja, hogy „növekvő”, ha a tömbben lévő számok szigmon növekvő sorban
vannak. Pl. [3 2.1 0.9] → csokkeno
, [3 4 2 9 5] → osszevissza
, [3 4.65
9 11] → novekvo
.
Megoldás
#include <stdio.h>
#include <stdbool.h>
/* nem lenne muszaj typedefelni amugy */
typedef enum { osszevissza, novekvo, csokkeno } SzigMon;
/* a feladat nem definialja azt, mi a helyzet a 0 es 1 elemu
tombokre (amik szigmon novekvoek es csokkenoek is :D) */
SzigMon vizsgal(double *t, int meret) {
bool nov = true, csokk = true; /* egyelore barmelyik lehet */
/* vigyazni a tulindexelesre! i+1, szoval itt i<meret-1*/
for (int i = 0; i < meret - 1; i++)
/* ha nem igaz, hogy kisebb a kovetkezonel */
if (!(t[i] < t[i + 1]))
/* akkor ez novekvo nem lehet */
nov = false;
/* ugyanaz a logika */
for (int i = 0; i < meret - 1; i++)
if (!(t[i] > t[i + 1]))
csokk = false;
/* hacsak nem 0 vagy 1 elemu a tomb, akkor ez megfelel */
if (csokk) return csokkeno;
if (nov) return novekvo;
return osszevissza;
}
int main(void) {
double t1[5] = {5, 9, 1, 3, 45};
double t2[5] = {1, 2, 3, 4, 5};
double t3[5] = {9, 8, 7, 6, 5};
if (vizsgal(t1, 5) == osszevissza) printf("t1 osszevissza\n");
if (vizsgal(t2, 5) == novekvo) printf("t2 novekvo\n");
if (vizsgal(t3, 5) == csokkeno) printf("t3 csokkeno\n");
return 0;
}
Párosak vagy negatívak?
Írj egy függvényt, amelyik egy egész számokból álló tömböt vesz át paraméterként. A függvény
térjen vissza az alábbi felsorolt típusból valamelyik értékkel: parosak
,
negativak
, mindketto
, egyiksem
, ha a tömbben páros az
összes szám, negatív az összes, illetve ha mindkét tulajdonság, vagy egyik tulajdonság sem
érvényes rájuk. Írj programot, amelyik egy példaként definiált 100 elemű tömbre meghívja a
függvényt, és kiírja, hogy „párosak”, ha érvényes rá ez a tulajdonság.
- [3 4 5] →
egyiksem
- [-2 -4 -6] →
mindketto
- [4 6 10] →
parosak
Megoldás
#include <stdio.h>
#include <stdbool.h>
typedef enum { parosak, negativak, mindketto, egyiksem } Tulajdonsagok;
Tulajdonsagok vizsgal(int *t, int meret) {
/* a megoldas gondolata, pl. parosakra:
* 1) tetelezzuk fel, hogy az osszes szam paros.
* 2) nezzuk vegig a tombot
* 2a) ha talalunk egy nem paros szamot...
* 2b) ... akkor nem igaz az, hogy mind parosak. */
/* 1 */
bool prsk = true;
bool ngtvk = true;
/* 2 */
for (int i = 0; i < meret; ++i) {
if (t[i] % 2 != 0) /* <- 2a */
prsk = false; /* <- 2b */
if (t[i] >= 0)
ngtvk = false;
}
if (prsk && ngtvk)
return mindketto;
if (prsk) /* ... de nem ngtvk */
return parosak;
if (ngtvk) /* ... de nem prsk */
return negativak;
return egyiksem; /* mar csak ez lehet. */
}
int main(void) {
int t[5] = {4, 6, 8, 10, 12};
if (vizsgal(t, 5) == parosak)
printf("parosak");
return 0;
}
24×21-es képecskék
Egy játékhoz, amit írunk, szükség vagy 24×21 fekete/fehér pontból álló kis képecskékre. Mivel ezekből rengeteg lesz, kitaláljuk, hogy a fekete/fehér jelleg miatt egy bit is tárolhat egy pontot, így az egy kép által lefoglalt memória (innentől feltételezve a 8 bites char-t) 3×21=63 bájtot foglal csak el a memóriából. Feladat: írni három függvényt, amelyek a következőeket tudják:
- Kirajzolni pontokból és csillagokból egy ilyen képecskét.
- Fehérre állítani egy pontot.
- Feketére állítani egy pontot.
Megoldás
#include <stdio.h>
typedef unsigned char kep[63];
// Az elso feladatresz megoldasa: egy kepecske kirajzolasa
void kirajzol(kep k) {
for (int y = 0; y < 21; y++) {
for (int x = 0; x < 24; x++) {
/* annyival shift, utana legalso bit */
/* (szóköz helyett .-ot használtam most) */
printf("%c", (k[y * 3 + x / 8] >> (7 - x % 8)) & 1 ? '*' : '.');
}
printf("\n");
}
printf("---\n");
}
// A masodik feladatresz: adott pontot feherre allit
void feher(kep k, int x, int y) {
/* keppont aktiv: bitenkenti VAGY */
k[y * 3 + x / 8] = k[y * 3 + x / 8] | (1 << (7 - x % 8));
}
// A harmadik feladatresz: adott pontot feketere allit
void fekete(kep k, int x, int y) {
/* keppont ki: bitenkenti ES a negalttal */
k[y * 3 + x / 8] = k[y * 3 + x / 8] & ~(1 << (7 - x % 8));
}
int main(void) {
kep k;
for (int y = 0; y < 21; y++)
for (int x = 0; x < 24; x++)
fekete(k, x, y);
kirajzol(k);
for (int x = 0; x < 24; x++)
feher(k, x, 10);
kirajzol(k);
for (int y = 0; y < 21; y++)
feher(k, 5, y);
kirajzol(k);
return 0;
}
Megoldható kétdimenziós tömbbel is, kep[3][21]
. Az egy bájton belüli képpond
sorrend is tetszőleges; vagy mindenhol 7-x%8
, vagy mindenhol simán x%8
.
Minden szám megfordítása
Írj C programot, amelyik definiál egy 1000 elemű, bájtokból álló tömböt. A program fordítsa meg az egyes bájtokban a biteket; a 7. helyiértékű cseréljen helyet a 0. helyiértékűvel, a 6. helyiértékű az 1-essel stb. (Feltételezzük, hogy a bájtok 8 bitesek. A tömb számokkal feltöltésével nem kell foglalkozni.) A program végezetül írja ki binárisan a tömb 0. elemét. A megfordításra példa:
76543210 10110010 bemenet 01001101 kimenet
Megoldás
#include <stdio.h>
int main(void) {
unsigned char t[1000];
/* egyet most itt inicializalok, hogy lassam az eredmenyt,
* de a feladat nem keri */
t[0] = 0xd7;
/* kiiras, csak hogy a csere elott is lassuk */
for (int i = 7; i >= 0; i--)
putchar((t[0] >> i) & 1 ? '1' : '0');
printf("\n");
/* ez a MEGOLDAS LENYEGE */
for (int i = 0; i < 1000; i++) {
unsigned char uj = 0;
/* amit a regi szambol kishiftelunk jobbRA,
* azt az ujba beshifteljuk jobbROL */
for (int j = 0; j < 8; j++) {
int x = t[i] & 1; /* ez kiveszi az also bitet */
t[i] >>= 1; /* a regit shifteli */
uj = uj << 1 | x; /* ez az ujat balra shifteli,
es az ujat berakja */
}
t[i] = uj;
}
/* ez csak copypaste, a feladat egyszer keri */
for (int i = 7; i >= 0; i--)
putchar((t[0] >> i) & 1 ? '1' : '0');
printf("\n");
return 0;
}
Bitek léptetése
Írj egy C programot, amelyik 100 elemű, bájtokból álló tömböt léptet egy bittel jobbra! A számokból jobbra kicsúszó bit jöjjön be mindig a következő számba balról. Az utolsó szám legalsó helyiértékéből kicsúszó bit pedig kerüljön az első szám legfelső helyiértékébe. (Feltételezzük, hogy a bájtok 8 bitesek. A tömb számokkal feltöltésével nem kell foglalkozni.) Például:
76543210 76543210 ... 76543210 76543210 01001010 11111101 01011110 00001101 bemenet 10100101 01111110 ... 10101111 00000110 kimenet
Megoldás
#include <stdio.h>
#include <stdlib.h>
int main(void) {
unsigned char t[100];
/* ezt nem kerte a feladat, csak hogy ne legyen inicializalatlan */
for (int i = 0; i < 100; ++i)
t[i] = rand() % 256;
/* ezt se kerte, csak hogy latszodjon az eredmeny */
for (int i = 7; i >= 0; i--)
putchar((t[0] >> i) & 1 ? '1' : '0');
printf(" ... ");
for (int i = 7; i >= 0; i--)
putchar((t[99] >> i) & 1 ? '1' : '0');
printf("\n");
/* MEGOLDASA a feladatnak: tulajdonkepp ez a ciklus. */
/* utolso szam utolso bitje,
* mert ez csuszik be az elso szamba; mar most kivesszuk,
* hogy lent, amikor az atvitelt "becsusztatjuk" az
* if (atvitel) resznel, ott mar a megfelelo erteket
* tartalmazza */
int atvitel = t[99] & 1;
for (int i = 0; i < 100; i++) {
int uj_atvitel = t[i] & 1; /* a kovetkezo szamhoz - ez a kicsuszo bit */
t[i] >>= 1; /* ezzel csuszik az egesz */
if (atvitel == 1) /* ha volt "atvitel", akkor azt berakjuk a legfelsobe */
t[i] |= 1 << 7;
atvitel = uj_atvitel;
}
/* kiirom az eredmenyt; a feladat nem kerte */
for (int i = 7; i >= 0; i--)
putchar((t[0] >> i) & 1 ? '1' : '0');
printf(" ... ");
for (int i = 7; i >= 0; i--)
putchar((t[99] >> i) & 1 ? '1' : '0');
printf("\n");
return 0;
}
Sztringek, mint karaktertömbök
Hozzunk létre egy sztringet! Változtassunk meg benne néhány
karaktert! Írjunk ciklust, amelyik megszámolja az 'l'
betűket a sztringben!
Megoldás
#include <stdio.h>
int main(void) {
char sz[20] = "Hello, vilag!";
printf("|%s|\n", sz);
sz[0] = 'h'; /* sztring: "idezojel", karakter: 'h' aposztrof! */
printf("|%s|\n", sz);
sz[7] = '\0'; /* 0 is lehetne, ugyanaz. */
printf("|%s|\n", sz);
/* tekintsünk a sztringre, mint tömbre. hol van vége?
ahol sz[i]==0, nem pedig i=19-nél, ami a tömb méretéből adódna! */
int db = 0;
for (int i = 0; sz[i] != '\0'; ++i)
if (sz[i] == 'l')
db += 1;
printf("[%s] sztring %d darab l betűt tartalmaz.\n", sz, db);
return 0;
}
Üdvözlés
Készíts programot, amely bekéri a felhasználó nevét, majd üdvözli őt a nevén szólítva!
Hány szóköz?
Készíts programot, mely bekér egy mondatot, majd
a.) megszámolja és kiírja, hogy a mondatban hány szóköz található.
b.) kiírja a mondatot szóközök nélkül.
Kisbetűk I.
Készíts függvényt (numLower), ami megkap egy stringre mutató
pointert, és visszaadja az adott szövegben található kisbetűk
számát. (Ehhez használható a ctype.h
islower()
függvénye is.)
Kisbetűk II.
Írj C függvényt, amely egy nullával terminált sztringben kicseréli az
angol abécé nagybetűit a nekik megfelelő kisbetűkre. Ha a bemeneti sztring
"Hello Vilag", módosítsa azt "hello vilag"-ra.
(Tipp: A megoldáshoz a ctype.h
könyvtári függvényei használhatóak.)
Hogyan kell módosítani a függvényt, hogy nagybetűkre cseréljen?
Felülírás és csere
Írj függvényt, amely az első paraméterében kapott sztringben megkeresi a második paraméterében adott karakter előfordulásait, és felülírja azokat a harmadik paraméterében adott karakterrel! Pl. "alma", 'a', 'e' → "elme". A függvény visszatérési értéke a kicserélt karakterek száma legyen.
Írj függvényt, amely szintén egy sztringet és egy karakterpárost kap, de ez ne felülírja az első előfordulásait a másodikkal, hanem cserélje meg őket! Pl. 'a', 'e' jelentse azt, hogy 'a'-t 'e'-re kell cserélni, 'e'-t pedig 'a'-ra. Hogyan lehet ezt megoldani az előző függvény felhasználásával?
Squeeze
Írj olyan "squeeze" függvényt, amely az első paraméterben megadott sztringből az összes olyan karaktert törli, amelyik szerepel a második paraméterben megadott sztringben. Például "megadott sztring", "gt" paraméterekkel meghívva a függvényt az első paraméter így módosul: "meado szrin".
Pontosan egyszer
Írj programot, amely beolvas egy sztringet, és megállapítja, hogy vannak-e benne olyan karakterek, amelyek pontosan egyszer fordulnak elő. A program írja ki ezeket a karaktereket, ha pedig nincsenek a sztringben egyedi karakterek, akkor közölje a felhasználóval!
Decimális
Írj olyan int dec_to_int(char *s)
függvényt, amelyik a megadott
számjegyekből álló sztringet a neki megfelelő egész értékké
alakít (tízes számrendszer szerint)! Pl. dec_to_int("256")
visszatérési értéke 256
.
Oldd meg a feladatot a sscanf()
segítségével és anélkül is!
Hexadecimális
Írj olyan int hexa_to_int(char *s)
függvényt, amelyik a megadott
hexadecimális számjegyekből álló sztringet a neki megfelelő egész értékké
alakít! Pl. hexa_to_int("1ef")
visszatérési értéke 495
.
Oldd meg a feladatot a sscanf()
segítségével és anélkül is!
Legalább kettő – sztringre
Írj függvényt, amely paraméterként vesz át egy sztringet, és visszaadja az első olyan karakter címét, amelyből legalább kettő található a sztringben! Ha nincs ilyen karakter, adjon vissza NULL pointert!
Megoldás
char *duplas(char *string) {
for (int i = 0; string[i] != '\0'; i++)
for (int j = i+1; string[j] != '\0'; j++)
if (string[i] == string[j])
return string+i;
return NULL;
}
Része-e?
Írj egy függvényt, amely egy adott sztringben megkeresi egy másik
sztring legutolsó előfordulását, és visszaadja annak pozícióját, illetve
-1-et, ha nem található. A megoldáshoz ne használd a könyvtári strrstr()
függvényt! Például "abcdabce"-ben keressük "abc"-t, a visszatérési érték
4, a színnel jelölt előfordulás miatt.
Megoldás
A következő módon bontható fel ezt részekre:
- Kell egy függvény, amelyik megmondja, hogy egy adott sztring elején szerepel-e
egy másik sztring. Ezt fogom lefuttatni a különböző részein az eredeti sztringeknek
(visszafelé). Szemfülesek az
strncmp
-t használhatják erre. - Kell egy függvény, amelyik egy sztring hosszát megmondja (de jó a gyári
strlen
is), mivel - visszafelé futtatok egy ciklust, és nézem, hogy megtalálom-e valahol a szénakazal végén a tűt.
- Ahol először megtalálom, azzal az indexszel vissza is térhetek; ha sehol nem találtam meg, akkor -1-gyel.
#include <stdio.h>
#include <stdbool.h>
bool igy_kezdodik(char *mi, char *hogyan) {
int i;
/* amig egyiknek sincs vege, es egyeznek a betuk, kov. karakter */
i=0;
while (hogyan[i]!='\0' && mi[i]!='\0' && hogyan[i]==mi[i])
i++;
/* ha a hogyan string vegere ertunk, akkor eddig tuti megegyezett
a mi-vel */
return hogyan[i]=='\0';
}
int hossz(char *str) {
int i = 0;
while (str[i]!='\0') i++;
return i;
}
int utolso_elofordulas(char *szenakazal, char *tu) {
int h;
h=hossz(szenakazal);
h-=hossz(tu); /* ennel csak elorebb lehet */
while (h>=0 && !igy_kezdodik(szenakazal+h, tu))
h--;
/* ha ertelmes index van, akkor azzal terunk vissza */
if (h>=0)
return h;
/* amugy -1 */
return -1;
}
int main(void) {
printf("%d\n", utolso_elofordulas("almafa, eperfa", "fa"));
printf("%d\n", utolso_elofordulas("almafa, eperfa", "a"));
printf("%d\n", utolso_elofordulas("almafa, eperfa", "kortefa"));
return 0;
}
Az első függvénynek az is jó megoldás lenne, ha az összehasonlítandó karakterek számát paraméterként kapja; olyankor nem kellene figyelnie a lezáró nullákra.
strcat()
Írjunk függvényt, amelyik egyik sztring végére másol egy
másikat, vagyis hozzáfűzi a paraméterként kapott első sztringhez a
másodikat! (Ezt csinálja a könyvtári strcat()
függvény
is.)
Megoldás
#include <stdio.h>
void sztringhozzafuz(char *mihez, char *honnan) {
int folytat, i;
i = 0;
while (mihez[i] != '\0')
i++; /* ezzel megkeressuk, az elobbinek hol van vege */
folytat = i; /* es oda masoljuk a masikat, folytatolagosan */
i = 0; /* nezzuk a masik sztringet az elejetol */
while (honnan[i] != '\0') {
mihez[folytat] = honnan[i];
i++;
folytat++;
}
mihez[folytat] = '\0'; /* lezaro nulla eddig nem - most megtesszuk. */
}
/* peldak, hogyan kell meghivni a fuggvenyeket */
int main(void) {
/* mit a mizujs[]? azt, hogy a fordito kitalalja a tomb meretet. */
/* a hello[] sztringhez hozzafuzunk, ezert az nagyobb kell legyen. */
char hello[50] = "Hello, vilag!",
mizujs[] = "Mizujs?";
printf("Sztring: [%s] es [%s]\n", hello, mizujs);
sztringhozzafuz(hello, " ");
sztringhozzafuz(hello, mizujs);
printf("Osszefuzve: [%s].\n", hello);
return 0;
}
strlcat()
Írj egy függvényt (paraméterei: cél, forrás, cél tömb mérete), amelyik egy cél sztring (1.
paraméter) végére hozzáfűz egy forrás sztringet (2. paraméter); figyelembe véve azt, hogy a cél
tömb maximális mérete adott (3. paraméter), amelybe már a lezáró nullának is bele kell férnie.
Mindkét helyen eredendően is 0-val lezárt sztring van. Ha az összefűzött sztring nem fér el a
cél helyen, akkor le kell vágnia a függvénynek – de nullával mindig legyen lezárva. Írj
programrészt, amelyben bemutatod a függvény használatát. A string.h
függvényei NEM
használhatóak.
Megoldás
Rendes helyeken ilyen gyárilag szokott lenni, strlcat
vagy
g_strlcat
néven. Az egésznek az előnye, hogy a cél puffer
méretét kell megadni a harmadik paraméterben, ami statikus tömb esetén egy
sima sizeof. Nem kell levonni 1-et a lezáró 0 miatt, semmi ilyesmi, pontosan
a méretet várja.
#include <stdio.h>
void strlcat(char *cel, char *forras, int meret) {
int celmeret, forrasidx;
celmeret=0;
while (cel[celmeret]!=0)
++celmeret;
forrasidx=0;
while (forras[forrasidx]!=0 && celmeret+forrasidx<meret-1) {
cel[celmeret+forrasidx]=forras[forrasidx];
forrasidx++;
}
/* akarmiert is lett vege, lezaro 0. */
cel[celmeret+forrasidx]=0;
}
int main(void) {
char cel[6]="alma";
char cel2[9]="alma";
strlcat(cel, "le", sizeof(cel));
strlcat(cel2, "le", sizeof(cel2));
printf("[%s]\n", cel);
printf("[%s]\n", cel2);
return 0;
}
Összefűzés
Írj függvényt, amely paraméterként vesz át egy cél sztringet, továbbá két másik sztringet és egy elválasztó karaktert! Másolja be a cél sztringbe a másik két sztringet úgy, hogy közéjük az elválasztó karaktert teszi.
Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A beépített sztringkezelő függvények nem használhatóak!
Példa paraméterek: „alma”
és „körte”
, továbbá „;”
Példa eredmény: „alma;körte”
Megoldás
#include <stdio.h>
void osszefuz(char *ide, char *egyik, char *masik, char koze) {
int pos=0;
for (int i=0; egyik[i]!='\0'; ++i)
ide[pos++]=egyik[i];
ide[pos++]=koze;
for (int i=0; masik[i]!='\0'; ++i)
ide[pos++]=masik[i];
ide[pos++]='\0';
}
int main(void) {
char kesz[20];
osszefuz(kesz, "alma", "korte", ';');
printf("%s\n", kesz);
return 0;
}
Sztringek szétválasztása
Írj egy függvényt, amely paraméterként vesz át egy bemeneti sztringet és egy elválasztó karaktert! Legyen még két további paramétere, amelyekbe az eredményt írja. Vágja ketté a függvény a sztringet az első elválasztó karakternél: az eleje menjen az egyik eredmény sztringbe, másik pedig a másikba!
Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A beépített sztringkezelő függvények nem használhatóak.
Példa paraméterek: „alma;körte”
és „;”
Példa eredmény: „alma”
és „körte”
Megoldás
#include <stdio.h>
void szeletel(char *be, char elvalaszto, char *egyik, char *masik) {
int x = 0;
int pos = 0;
while (be[x] != elvalaszto)
egyik[pos++] = be[x++];
egyik[pos] = '\0';
x++;
pos = 0;
while (be[x] != '\0')
masik[pos++] = be[x++];
masik[pos] = 0;
}
int main(void) {
char bal[20], jobb[20];
szeletel("alma;korte", ';', bal, jobb);
printf("[%s] es [%s]\n", bal, jobb);
return 0;
}
strstr()
Írj függvényt, amely két sztringet vesz át paraméterként, és az elsőben megkeresi a második első előfordulását! Ha megtalálja, adja vissza a megtalált szöveg első karakterének címét, ha nincs benne, akkor NULL pointert! A megoldáshoz nem használhatsz könyvtári függvényt. (A feladat a string.h-ban található strstr függvény saját megvalósítása.) Egészítsd ki teljes programmá, a program az "Indul a kutya s a tyúk aludni." mondatban keresse meg a "kutya" szót! (A függvény a kis és nagybetűket tekintse különbözőnek!)
Megoldás
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
char* mystrstr(char* hol, char* mit) {
for (int i = 0; hol[i]!='\0'; i++) {
int j;
bool talalt = true;
for (j=0; hol[i+j]!='\0' && mit[j]!='\0' && talalt; j++)
if (hol[i+j]!=mit[j])
talalt = false;
if (talalt && mit[j]=='\0')
return &hol[i];
}
return NULL;
}
int main(void) {
char s1[] = "Indul a kutya s a tyúk aludni.";
char* pos1 = mystrstr(s1, "kutya");
if (pos1 != NULL)
printf("Pozíció: %d\n", (int) (pos1-s1));
else
printf("NULL - nincs benne\n");
char s2[] = "Indul a kuty";
char* pos2 = mystrstr(s2, "kutya");
if (pos2 != NULL)
printf("Pozíció: %d\n", (int) (pos2-s2));
else
printf("NULL - nincs benne\n");
return 0;
}
Névelő
Készíts programot, mely adott sztringben megszámolja, hányszor fordul elő az „a” névelő. A névelő lehet mondat elején, de végén nem, viszont vessző állhat előtte is és utána is, egyébként szóköz karakterek határolják.
Caesar kódolás
A gyakorlaton volt egy olyan példa, amelyik karaktereket képes bekódolni a→b, b→c, c→d stb kódolással. Írj egy függvényt, amelyiknek megadható a kódolandó karakter, és a→d kódolást használ. Javítsd úgy az órán tárgyalt függvényt, hogy csak a kisbetűket kódolja, más karaktereket hagyjon változatlanul. Figyelj arra is, hogy a programkódban ne legyenek mágikus értékek (pl. 26, mint az abc betűinek száma).
Megoldás
#include <stdio.h>
/* Ez bekodol egy karaktert, a kulcs szerint. */
char kodol(char mit, char kulcs) {
char delta = kulcs - 'a';
if (mit >= 'a' && mit <= 'z') {
/* eltolas */
mit = mit + delta;
/* tulcsuszott a z-n? */
if (mit > 'z')
/* akkor vissza kell menni annyit, hogy ujra az abecen
belul legyunk. az 'annyit' erteke 'z'-'a'+1 lepes,
nem pedig 'z'-'a'! az utobbi a ket karakter kozotti
tavolsag, az elso pedig az a szam, amely az osszes
letezo betuk szamat mutatja! */
mit = mit - ('z' - 'a' + 1);
}
return mit;
}
char dekodol(char mit, char kulcs) {
char delta = kulcs - 'a';
if (mit >= 'a' && mit <= 'z') {
mit = mit - delta;
if (mit < 'a')
mit = mit + ('z' - 'a' + 1);
}
return mit;
}
int main(void) {
char szoveg[] = "hello, world!";
/* az abc kiirasa */
for (int i = 'a'; i <= 'z'; ++i)
printf("%c", i);
printf("\n");
for (int i = 'a'; i <= 'z'; ++i)
printf("%c", kodol(i, 'd'));
printf("\n");
/* szoveg kodolasa */
for (int i = 0; szoveg[i] != 0; ++i)
szoveg[i] = kodol(szoveg[i], 'd');
printf("[%s]\n", szoveg);
/* szoveg dekodolasa */
for (int i = 0; szoveg[i] != 0; ++i)
szoveg[i] = dekodol(szoveg[i], 'd');
printf("[%s]\n", szoveg);
return 0;
}
Karakterek törlése
Írj függvényt, amely átvesz paraméterként egy módosítandó sztringet és még egy karaktert. Alakítsa át úgy a sztringet úgy, hogy a megadott karaktert törölje a sztring elejéről és a végéről is! Mindkét oldalon lehet több is, vagy akár semennyi. A belsejében viszont tudjuk, hogy nincsen.
Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A beépített sztringkezelő függvények nem használhatóak.
Példa bemenet: „xxxHello hallo elektor kalandorxxxx”
és az „x”
karakter
Példa kimenet: „Hello hallo elektor kalandor”
Megoldás
#include <stdio.h>
void sztring_trim(char *str, char mit) {
int eleje = 0;
while (str[eleje] == mit)
eleje++;
int pos = 0;
for (int i = eleje; str[i] != mit && str[i] != '\0'; i++)
str[pos++] = str[i];
str[pos] = '\0';
}
int main(void) {
char szoveg[] = "xxxHello hallo elektor kalandorxxxx";
sztring_trim(szoveg, 'x');
printf("[%s]\n", szoveg);
return 0;
}
Bevezető és lezáró karakterek
Írj függvényt, amely paraméterként átvesz egy cél sztringet, továbbá egy forrás sztringet, egy karaktert és egy darabszámot! Másolja át a cél sztringbe a forrást úgy, hogy elé és mögé a megadott karakterből a megadott darabszámút tegye. Ezen kívül a szóközöket is cserélje ki a megadott karakterre.
Írj főprogramot, amelyben egy példával bemutatod a függvény használatát! A beépített sztringkezelő függvények nem használhatóak.
Példa bemenet: „Hello hallo elektor kalandor”
, továbbá az „x”
karakter és 3
Példa kimenet: „xxxHelloxhalloxelektorxkalandorxxx”
Megoldás
#include <stdio.h>
void strelemoge(char *ide, char *mit, char kar, int db) {
int pos = 0;
for (int x = 0; x < db; ++x)
ide[pos++] = kar;
for (int x = 0; mit[x] != '\0'; ++x)
ide[pos++] = mit[x] == ' ' ? kar : mit[x];
for (int x = 0; x < db; ++x)
ide[pos++] = kar;
ide[pos] = '\0';
}
int main(void) {
char novelt[30];
strelemoge(novelt, "Hello hallo elektor kalandor", 'x', 3);
printf("[%s]\n", novelt);
return 0;
}
Második szó, utolsó szó
Írj függvényt, amely paraméterként kap egy sztringet! A sztring szöveget tartalmaz, melynek szavait szóközök választják el egymástól (minden szó, ami nem szóköz). A függvény adja vissza címével átvett változókban a sztring második szavának indexét, visszatérési értékként (return-nel) pedig a sztring utolsó szavának címét! A paraméterként kapott sztringről biztosan tudjuk, hogy legalább két szóból áll, a szavakat pontosan egy szóköz választja el egymástól, és a sztring első és utolsó karaktere nem szóköz.
Megoldás
char *szavak(char *sztring, int *masodik) {
int utolso = 0;
*masodik = 0;
for (int i = 0; sztring[i] != '\0'; i++) {
if (sztring[i] == ' ') {
utolso = i;
if (*masodik == 0)
*masodik = i + 1;
}
}
return sztring + utolso + 1;
}
„The” kezdetű címek"
Könyvek, filmet címeit úgy szokás rendezni, hogy a címek elején lévő névelőket (pl. angolul a
„The”, magyarul az „A” és „Az”) a rendezésben nem vesszük figyelembe. Írj egy olyan módosított
strcmp_the()
függvényt, amely paramétere és visszatérési értéke az eredeti strcmp()
-éhez
hasonló, de az összehasonlításnál figyelmen kívül hagyja a „The” kezdetet!
Megoldás
A legegyszerűbb megoldás az alábbi. Megvizsgáljuk mindkét sztringet. Ha valamelyik a „The ” részsztringgel
kezdődik, az annak megfelelő pointert 4-gyel növeljük, tehát négy karakterrel hátrébb léptetjük.
Az így kapott sztringeket adjuk az eredeti strcmp()
-nek. A két pointer növelését
azért tehetjük meg, mert azok a saját függvényünknek lokális változói, amelyet módosíthatunk.
/* Sztring összehasonlító függvény, ami nem veszi figyelembe
* a szting elején lévő "The " előtagot */
int strcmp_the(char *egyik, char *masik) {
if (strncmp(egyik, "The ", 4) == 0)
egyik += 4;
if (strncmp(masik, "The ", 4) == 0)
masik += 4;
return strcmp(egyik, masik);
}
IP cím
Írj egy olyan szabványos ANSI C függvényt, amely paraméterként kap egy sztringet, mely egy IP
címet tartalmaz a szokásos alakban: négy darab 0 és 255 közötti szám pontokkal elválasztva. A
függvény állítsa elő az IP cím 32 bites reprezentációját! A visszatérési értéke legyen egy
unsigned
érték, amelynek legalsó bájtja az IP cím utolsó részének megfelelő értéket
tartalmazza, a második az IP cím utolsó előtti részét és így tovább. Feltesszük, hogy az
unsigned típus az adott architektúrán legalább 32 bites. Ha a bemenet például "0.0.2.33", akkor
a kimenet: 545.
Megoldás
Barátunk a scanf()
. Itt egyáltalán nem kell karakterenkénti
feldolgozást, és semmi hasonlót csinálni. A scanf %u
be fog olvasni egy
nemnegatív számot, és a pontnál meg fog állni, mivel a pont nem lehet része egy egész számnak.
A formátumsztringbe pedig ha elhelyezünk egy pontot, akkor a scanf azt fogja várni, hogy a
bemeneten ott is legyen az a pont; beolvassa és eldobja. És hát, mivel nem a standard bemenetről
olvasunk, hanem sztringből, sscanf()
lesz a függvényünk. Vigyázni kell, hogy a
<< műveleteket zárójelezni kell az összeadásnál – itt inkább bitenkénti vagy kapcsolatot
használtam (az eredmény egyébként ugyanaz lenne).
#include <stdio.h>
unsigned str_to_ip(char *str) {
unsigned a, b, c, d;
sscanf(str, "%u.%u.%u.%u", &a, &b, &c, &d);
return a<<24 | b<<16 | c<<8 | d;
}
int main(void) {
printf("%u\n", str_to_ip("0.0.2.33"));
return 0;
}