Új hozzászólás Aktív témák
-
Jester01
veterán
válasz
TheRolf #2493 üzenetére
Először is, használd a fordítót arra, hogy minél több hibát jelezzen neked. gcc esetén erre a -Wall kapcsoló szolgál. Lássuk mi nem tetszik neki:
t.c: In function 'fordit':
t.c:14: warning: implicit declaration of function 'malloc'
t.c:14: warning: incompatible implicit declaration of built-in function 'malloc'
t.c:14: error: called object 'str' is not a function
t.c:15: error: called object 'out' is not a function
t.c:15: warning: return makes integer from pointer without a cast
t.c: At top level:
t.c:18: warning: return type defaults to 'int'
t.c: In function 'main':
t.c:21: warning: assignment makes pointer from integer without a castAz első kettő azért van, mert nincs meg a malloc prototípusa, ehhez erősen ajánlott egy #include <stdlib.h> (bár nem kötelező).
A következő kettő azért van, mert kerek zárójelet használtál szögletes helyett tömb indexeléshez.
Az ötödik probléma, hogy a main() függvényed visszatérési típusa nincs megadva. Bár C-ben alapértelmezés az int, de azért ajánlott kiírni.
Az utolsó kettő oka, hogy a függvényed visszatérési típusából hiányzik egy csillag, hogy pointert adjon vissza.
Ezeket javítva sajnos további hibákra derül fény:
t.c: In function 'main':
t.c:25: warning: control reaches end of non-void function
t.c: In function 'fordit':
t.c:16: warning: 'i' may be used uninitialized in this function
/tmp/ccle9qDf.o: In function `main':
t.c:(.text+0x89): warning: the `gets' function is dangerous and should not be used.Az első, hogy a main() nem ad vissza értéket. Ezt egy return 0; kiválóan orvosolja.
A második már súlyosabb, azt mondja, az i változónak nincs kezdőérték megadva mielőtt használod. C-ben a változóknak nincs alapértelmezett kezdőértékük.
Végül, a gets függvény használata veszélyes, mivel nincs benne hosszúság ellenőrzés. Ugyan ez nem végzetes hiba de helyette ajánlott az fgets használata.
Jelenleg akkor így néz ki a program ami a fordítónak már nem okoz fejfájást:
#include <stdio.h>
#include <stdlib.h>
int hossza(char *str){
int i=0;
while (str) {
i++;
}
return i;
}
char* fordit(char *str) {
int i=0;
char *out;
out = (char*)malloc((hossza(str))*(sizeof(char)));
while (str[i]) {
out[i] = str[-i-1];
}
return out;
}
int main() {
char betuk[50];
char *z;
gets(betuk);
z = fordit(betuk);
puts(z);
free(z);
//getchar();
return 0;
}(A gets benne maradt egyelőre, lásd később.)
Ezután jutunk el a futási hibákhoz. A felderítésükhöz debugger vagy más diagnosztikai program (pl. valgrind) ajánlott. Példának okáért kapjuk elő a gdb debuggert. Miután beadtuk a stringünket, azt látjuk, hogy a processzor pörög de nem történik semmi. Nézzük meg miben mesterkedik a programunk:
(gdb) r
Starting program: /var/tmp/a.out
hello
^C
Program received signal SIGINT, Interrupt.
hossza (str=0x7fffffffe6d0 "hello\n") at t.c:6
6 while (str) {Ahha. Szóval ott került végtelen ciklusba, mivel az str az biza nem változik. Oda igazából str[i] kellene. Nézzük, jobb lesz-e ettől. Igen, most egy másik ciklusban pörög, aminek a feltétele a megtévesztésig hasonló:
Program received signal SIGINT, Interrupt.
0x00000000004005f5 in fordit (str=0x7fffffffe6d0 "hello\n") at t.c:16
16 while (str[i]) {Innen pedig azért nem lép ki, mert az i nem változik a ciklusban. Tegyünk róla, hogy 1-el növekedjen. Szuper jó, ettől már legalább lefut a program, csak semmit nem ír ki. Nézzük meg például honnan lesz első betűje a kimenetnek:
(gdb) br 17
Breakpoint 1 at 0x40066d: file t.c, line 17.
(gdb) r
Starting program: /var/tmp/a.out
hello
Breakpoint 1, fordit (str=0x7fffffffe6d0 "hello\n") at t.c:17
17 out[i] = str[-i-1];
(gdb) p i
$1 = 0
(gdb) p -i-1
$2 = -1Hoppá, mire is kértük a számítógépet? out[0] = str[-1]. Ez így nem lesz jó, oda nekünk az utolsó betű kellene, ami azt jelenti itt még hozzá kellene adni a string hosszát. Tegyük ezt meg. Csoda, kiírta fordítva a szöveget. Na de minket nem olyan egyszerű boldoggá tenni, ráengedjük a valgrindot is:
hello
==28218== Invalid read of size 1
==28218== at 0x4C25824: __GI_strlen (mc_replace_strmem.c:284)
==28218== by 0x4E8DDCA: puts (ioputs.c:37)
==28218== by 0x400697: main (t.c:28)
==28218== Address 0x518a045 is 0 bytes after a block of size 5 alloc'd
==28218== at 0x4C244E8: malloc (vg_replace_malloc.c:236)
==28218== by 0x40061D: fordit (t.c:15)
==28218== by 0x400687: main (t.c:27)Elismerem ez kissé érthetetlen, de azt szeretné mondani nekünk, hogy a kiírásnál az első 5 byte után a hatodik olvasása nem jó. De miért is akar hatot olvasni, ha egyszer a "hello" csak 5 betű. Jusson eszünkbe, hogy C-ben a stringek végét egy nulla byte jelzi. Írjuk át a programot, hogy ezt vegye figyelembe. Ettől már a valgrind is elégedett lesz.
Végszó:
1) Sajnos az fgets függvény a sor végét jelző entert is eltárolja a pufferbe, így azzal extra izzadnunk kell egy kicsit.
2) gondolom az strlen használata tiltott volt, ezért írtál saját hossza függvényt
3) sizeof(char) definíció szerint 1.
4) a malloc visszatérési típusa void*, és az bármilyen pointerré cast nélkül konvertálható. Lehetőleg kerüljük a felesleges castolásokat.
5) némi visszajelzés a felhasználó felé nem ártFentiek figyelembevételével a végső program:
#include <stdio.h>
#include <stdlib.h>
int hossza(char *str){
int i=0;
while (str[i]) {
i++;
}
return i;
}
char* fordit(char *str) {
int i=0;
int hossz=hossza(str);
char *out = malloc(hossz+1);
while (str[i]) {
out[i] = str[hossz-i-1];
i++;
}
out[i]=0;
return out;
}
int main() {
char betuk[50];
char *z;
int hossz;
printf("string (max %d karakter):\n", sizeof(betuk)-2);
fgets(betuk, sizeof(betuk), stdin);
hossz=hossza(betuk);
if (hossz>0 && betuk[hossz-1]=='\n') {
betuk[hossz-1]=0;
}
z = fordit(betuk);
puts(z);
free(z);
return 0;
}Elnézést a hosszú hozzászólásért, csak igyekeztem halászatot oktatni, nem sült galambot kínálni.
Új hozzászólás Aktív témák
● olvasd el a téma összefoglalót!
● ha kódot szúrsz be, használd a PROGRAMKÓD formázási funkciót!
- Mibe tegyem a megtakarításaimat?
- AMD vs. INTEL vs. NVIDIA
- OLED TV topic
- Milyen videókártyát?
- Kerékpárosok, bringások ide!
- Túra és kirándulás topic
- Vélemény: nem úgy tűnik, de Lip-Bu Tan most menti meg az Intelt
- Samsung Galaxy S25 Ultra - titán keret, acélos teljesítmény
- Okosóra és okoskiegészítő topik
- Milyen TV-t vegyek?
- További aktív témák...
- Dell Latitude 5450 Intel Core Ultra 5 135U 4nm 32GB DDR5 érintőképernyős laptop Dell gari 2027.09.hó
- PlayStation 4/5 kontroller analóg cseréje HALL TMR érzékelősre, 1 év garancia!!! Nincs többé drift!!
- PlayStation 5/4 kontroller analóg cseréje HALL TMR érzékelősre, 1 év garancia!!! Nincs többé drift!!
- XBOX ONE/Series kontroller analóg cseréje HALL TMR érzékelősre, 1 év garancia!!! Nincs többé drift!!
- XBOX Series S 512GB, 6 hó garanciával Bp-i üzletből eladó!
- ÁRGARANCIA!Épített KomPhone i7 14700KF 32/64GB RAM RTX 5070Ti 16GB GAMER PC termékbeszámítással
- Csere-Beszámítás! Olcsó RTX Gamer Laptop játékra! I5 11400H / RTX 3050Ti / 16GB DDR4 / 512GB SSD
- ÁRGARANCIA!Épített KomPhone i5 14600KF 32/64GB RAM RTX 5060 Ti 16GB GAMER PC termékbeszámítással
- Eladó ÚJ, BONTATLAN Samsung Galaxy A05s 4/64GB ezüst / 12 hónap jótállással!
- Csere-Beszámítás! Felsőkategóriás számítógép PC Játékra! I9 13900KF / RTX 4080 / 32GB RAM / 1TB SSD
Állásajánlatok
Cég: PCMENTOR SZERVIZ KFT.
Város: Budapest
Cég: Promenade Publishing House Kft.
Város: Budapest