|
[ Dejan Krstic @ 18.09.2003. 10:29 ] @
| Code:
void main()
{
int x, y;
y = scanf("%d", &x);
printf("%d", y);
}
Problem je u tome sto metoda scanf uvek vrati 1. Koliko sam ja shvatio iz dokumentacije ona treba da vrati 1 samo ukoliko je vrednost dodeljena promenljivoj. A ja, na primer, unesem vrednost koja je izvan opsega integera i opet mi vrati 1 a vrednost x bude neka nebulozna. Zar ne bi trebalo u tom slucaju da vrati 0? |
[ brcha @ 18.09.2003. 12:08 ] @
Grešiš, ovaj silno grešiš sinak ;)
Code:
[12:52:20 brcha@tbird2000 /tmp]$ cat>proba.c
#include<stdio.h>
int main(){
int x;
int y;
y = scanf("%d",&x);
printf("x=%d,y=%d\n",x,y);
return 0;
}
[12:53:14 brcha@tbird2000 /tmp]$ gcc -o proba proba.c
[12:53:23 brcha@tbird2000 /tmp]$ ./proba
1
x=1,y=1
[12:53:29 brcha@tbird2000 /tmp]$ ./proba
a
x=1075048988,y=0
[12:53:32 brcha@tbird2000 /tmp]$ ./proba
2.5
x=2,y=1
[12:58:29 brcha@tbird2000 /tmp]$ ./proba
aaa 2.42
x=1075048988,y=0
[13:01:21 brcha@tbird2000 /tmp]$ ./proba
3mm
x=3,y=1
Elem, fora ti je u tome što scanf čita ulaz i očekuje da on počinje sa željenim tipom podataka (u ovom slučaju sa intom). Ako počinje sa nekom nebulozom, onda vraća 0. A ako počinje kako valja onda učitava dokle valja, a posle discarduje (ili prosleđuje sledećem parametru). Ako svi parametri prođu kako treba, onda vraća 1, a u suprotnom 0, kao što se može primetiti iz priloženog testiranja. Ako kod tebe vraća drugačije, možda imaš neki bugovit scanf, mada mi to zvuči ...
Poz!
F
[ Dejan Krstic @ 18.09.2003. 12:21 ] @
Code:
5555555555555555555555555555
x=-1282524957,y=1
Ja i dalje ne kapiram zasto ovde nije vratio nulu?!
[ brcha @ 18.09.2003. 13:18 ] @
Kod iz GlibC-2.2.5:/stdio-common/vfscanc.f (linije 1528-1579):
Code:
/* Convert the number. */
ADDW (L_('\0'));
if (need_longlong && (flags & LONGDBL))
{
if (number_signed)
num.q = __strtoll_internal (wp, &tw, base, flags & GROUP);
else
num.uq = __strtoull_internal (wp, &tw, base, flags & GROUP);
}
else
{
if (number_signed)
num.l = __strtol_internal (wp, &tw, base, flags & GROUP);
else
num.ul = __strtoul_internal (wp, &tw, base, flags & GROUP);
}
if (wp == tw)
conv_error ();
if (!(flags & SUPPRESS))
{
if (! number_signed)
{
if (need_longlong && (flags & LONGDBL))
*ARG (unsigned LONGLONG int *) = num.uq;
else if (need_long && (flags & LONG))
*ARG (unsigned long int *) = num.ul;
else if (flags & SHORT)
*ARG (unsigned short int *)
= (unsigned short int) num.ul;
else if (!(flags & CHAR))
*ARG (unsigned int *) = (unsigned int) num.ul;
else
*ARG (unsigned char *) = (unsigned char) num.ul;
}
else
{
if (need_longlong && (flags & LONGDBL))
*ARG (LONGLONG int *) = num.q;
else if (need_long && (flags & LONG))
*ARG (long int *) = num.l;
else if (flags & SHORT)
*ARG (short int *) = (short int) num.l;
else if (!(flags & CHAR))
*ARG (int *) = (int) num.l;
else
*ARG (signed char *) = (signed char) num.ul;
}
++done;
}
break;
Izgleda mi da ako je dobra konverzija, vraća int, a ako nije dobra konverzija, ne radi ništa!!!
A errore dispatchuje ako je pri konverziji iz ulaznog teksta u string (wp - Workspace Poiner) ili ako je konvertor (koji inače konvertuje u long) vratio pointer za kraj konverzije ( __strtol_internal(const char *nptr, char **endptr, int group, __locale_t loc);) podešen na početak (znak da je došlo do greške u konverziji). E, pa strtol je glup i ne vraća grešku pri takvoj konverziji, što se može videti iz ovog mog testa:
Code:
[14:12:27 brcha@tbird2000 /tmp]$ cat>proba-strtol.c
#include<stdio.h>
#include<stdlib.h>
int main(){
long l;
char *wp = "55555555555555555555555555555555555555555555555555555555555";
char *tw;
l = strtol(wp,&tw,10);
if(wp == tw) printf("wp == tw\n");
printf("l=%ld\n",l);
return 0;
}
[14:12:41 brcha@tbird2000 /tmp]$ gcc -o proba-strtol proba-strtol.c
[14:12:45 brcha@tbird2000 /tmp]$ ./proba-strtol
l=2147483647
Da ne smaram dalje, problem je dakle u strtol (odnosno __strtol_internal). Kad iskopam šta se u toj funkciji dešava, dodaću još jedan post.
Poz!
F
[ brcha @ 18.09.2003. 13:54 ] @
Elem, pogledaj ovo parčence koda iz GlibC-2.2.4:/sysdeps/generic/strtol.c (linije 505-508):
Code:
if (__builtin_expect (overflow, 0))
{
__set_errno (ERANGE);
Znači, ne vraća ništa, ali, naravno, podešava errno.
Pogledaj sada izmenjene verzije popularnih i korisnih programa proba-strtol i proba :)
Code:
[14:37:09 brcha@tbird2000 /tmp]$ cat proba-strtol.c
#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
int main(){
long l;
char *wp = "55555555555555555555555555555555555555555555555555555555555\0";
char *tw;
l = strtol(wp,&tw,10);
if(wp == tw) printf("wp == tw\n");
printf("l=%ld,wp=%p,tw=%p,tw-wp=%p,tw-wp=%d,error: %s\n",l,wp,tw,tw-wp,tw-wp,strerror(errno));
return 0;
}
[14:37:30 brcha@tbird2000 /tmp]$ gcc -o proba-strtol proba-strtol.c
[14:37:37 brcha@tbird2000 /tmp]$ ./proba-strtol
l=2147483647,wp=0x80484e0,tw=0x804851b,tw-wp=0x3b,tw-wp=59,error: Numerical result out of range
[14:37:42 brcha@tbird2000 /tmp]$ cat proba.c
#include<stdio.h>
#include<errno.h>
int main(){
int x;
int y;
y = scanf("%d",&x);
printf("x=%d,y=%d\nerror=%s\n",x,y,strerror(errno));
return 0;
}
[14:37:51 brcha@tbird2000 /tmp]$ gcc -o proba proba.c
[14:37:56 brcha@tbird2000 /tmp]$ ./proba
5555555555555555555555555555555555555555555555555555555555555555555555
x=2147483647,y=1
error=Numerical result out of range
[14:38:03 brcha@tbird2000 /tmp]$ ./proba
2
x=2,y=1
error=Success
Znači, sve radi kako valja... Samo posle scanfa treba da proveriš da li je errno == ERANGE.
Poz!
F
PS: Nismo li budale što to odmah nismo provalili, pošto ceo libc postavlja errno ako nešto ne valja... logično je da u scanfu odn u strtol nisu napravili tako debilan propust!
PS2: Zašto kažeš „metoda“? To nekako nije u duhu C jezika... radije funkcija :) (man:scanf(3) kaže o tome „The scanf family of functions scans input...“).
[ srki @ 18.09.2003. 23:25 ] @
Citat: brcha:
5555555555555555555555555555555555555555555555555555555555555555555555
x=2147483647,y=1
error=Numerical result out of range
Ali ti lepo dobijes maxint a Dejan dobije neku glupost. Da li je definisano standardom sta treba da se dobije u tom slucaju? Dejane, koji prevodilac koristis?
[ brcha @ 18.09.2003. 23:36 ] @
algoritam strtol radi tako sto mnozi sa bazom i dodaje trenutnu cifru dok ne dođe do overflow-a. tako da bi trebalo da se uvek dobije MAXINT. a što se tiče standarda, nemam pojma.
[ Dejan Krstic @ 19.09.2003. 17:08 ] @
Pa i mene je to zbunjivalo jer prakticno uvek dobijem razlicitu vrednost. Mislio sam da mozda scanf uopste ne uspe da dodeli tom mestu bilo sta pa onda vraca neku glupost zbog toga a nisam znao da mora uvek da vrati maxint.
Inace Visual Studio.NET.
[ tOwk @ 19.09.2003. 17:19 ] @
Citat: srki:
Da li je definisano standardom sta treba da se dobije u tom slucaju?
Da, prema radnom izdanju koje ja imam, odeljak 7.20.1.4 koji opisuje strtol, strtoll, strtoul, strtoull:
Citat: Returns
The strtol, strtoll, strtoul, and strtoull functions return the converted value, if any. If no conversion could be performed, zero is returned. If the correct value is outside the range of representable values, LONG_MIN, LONG_MAX, LLONG_MIN, LLONG_MAX, ULONG_MAX, or ULLONG_MAX is returned (according to the return type and sign of the value, if any), and the value of the macro ERANGE is stored in errno.
Usput, u FAQ-u na ovom forumu imaš adresu na kojoj možeš da nađeš ovu draft verziju ISO C standarda :-)
[ brcha @ 20.09.2003. 01:06 ] @
a kada se majkro$oft držao standarda ;)
[ enterx_ @ 10.10.2003. 12:28 ] @
scanf vraća broj učitanih polja !!! a -1 kad se dogodi greška
npr: scanf ("%d",&x); vraća 1
scanf ("%s",polje) vraća 1
scanf ("%d %s",&x,polje) vraća 2 i tako za n ucitanih elemenata ako je sve proslo dobro funkcija ce vratiti n
[ Dejan Krstic @ 21.10.2003. 15:36 ] @
To kapiram ali u mom slucaju nije sve proslo dobro (cak nije postavio promenljivu da ima vrednosta maxint nego nesto sasvim bez veze) pa je vratio 1.
[ RumRum @ 08.11.2003. 04:23 ] @
Pozdrav,
mislim da je samo neophodna dodela x, npr.:
Code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
printf("A sada, proba fore sa \"ELITESECURITY-ja\": \n");
int x, y;
printf("Ajde, lepo unesi ceo broj: ");
scanf("%d", &x);
printf("Rezultat unosa je: x = %d;\n", x);
printf("Sada dodeli unetu vrednost y = x;\n");
y = x;
printf("Rezultat dodele je: y = %d!!!!\n", y);
printf("O, gle čuda!!!\n");
return EXIT_SUCCESS;
}
Ajd' uzdravlje,
Copyright (C) 2001-2025 by www.elitesecurity.org. All rights reserved.
|