Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.

Citanje integera metodom scanf

[es] :: C/C++ programiranje :: Citanje integera metodom scanf

[ Pregleda: 5094 | Odgovora: 12 ] > FB > Twit

Postavi temu Odgovori

Autor

Pretraga teme: Traži
Markiranje Štampanje RSS

Dejan Krstic

Član broj: 479
Poruke: 2558



+1 Profil

icon Citanje integera metodom scanf18.09.2003. u 10:29 - pre 258 meseci
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?
 
Odgovor na temu

brcha
Filip Brčić
Beograd, Serbia

Član broj: 440
Poruke: 436

Jabber: brcha@kdetalk.net
ICQ: 40994923
Sajt: brcha.com


+2 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 12:08 - pre 258 meseci
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
... and the aliens sent an android down to earth, to slow down mankind's development
... and they named it Bill Gates.
 
Odgovor na temu

Dejan Krstic

Član broj: 479
Poruke: 2558



+1 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 12:21 - pre 258 meseci
Code:

5555555555555555555555555555
x=-1282524957,y=1


Ja i dalje ne kapiram zasto ovde nije vratio nulu?!
 
Odgovor na temu

brcha
Filip Brčić
Beograd, Serbia

Član broj: 440
Poruke: 436

Jabber: brcha@kdetalk.net
ICQ: 40994923
Sajt: brcha.com


+2 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 13:18 - pre 258 meseci
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
... and the aliens sent an android down to earth, to slow down mankind's development
... and they named it Bill Gates.
 
Odgovor na temu

brcha
Filip Brčić
Beograd, Serbia

Član broj: 440
Poruke: 436

Jabber: brcha@kdetalk.net
ICQ: 40994923
Sajt: brcha.com


+2 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 13:54 - pre 258 meseci
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...“).
... and the aliens sent an android down to earth, to slow down mankind's development
... and they named it Bill Gates.
 
Odgovor na temu

srki
Srdjan Mitrovic
Auckland, N.Z.

Član broj: 2237
Poruke: 3654
..-leonardo.sbs.auckland.ac.nz



+3 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 23:25 - pre 258 meseci
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?
 
Odgovor na temu

brcha
Filip Brčić
Beograd, Serbia

Član broj: 440
Poruke: 436

Jabber: brcha@kdetalk.net
ICQ: 40994923
Sajt: brcha.com


+2 Profil

icon Re: Citanje integera metodom scanf18.09.2003. u 23:36 - pre 258 meseci
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.
... and the aliens sent an android down to earth, to slow down mankind's development
... and they named it Bill Gates.
 
Odgovor na temu

Dejan Krstic

Član broj: 479
Poruke: 2558



+1 Profil

icon Re: Citanje integera metodom scanf19.09.2003. u 17:08 - pre 258 meseci
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.
 
Odgovor na temu

tOwk
Danilo Šegan
Zemun/Beograd

Član broj: 94
Poruke: 2743
*.verat.net

ICQ: 9344053
Sajt: alas.matf.bg.ac.yu/~mm011..


+2 Profil

icon Re: Citanje integera metodom scanf19.09.2003. u 17:19 - pre 258 meseci
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 :-)

Možda se moje mišljenje promenilo, ali ne i činjenica da sam u pravu.
 
Odgovor na temu

brcha
Filip Brčić
Beograd, Serbia

Član broj: 440
Poruke: 436

Jabber: brcha@kdetalk.net
ICQ: 40994923
Sajt: brcha.com


+2 Profil

icon Re: Citanje integera metodom scanf20.09.2003. u 01:06 - pre 258 meseci
a kada se majkro$oft držao standarda ;)
... and the aliens sent an android down to earth, to slow down mankind's development
... and they named it Bill Gates.
 
Odgovor na temu

enterx_
friderich shaiz
ex yu

Član broj: 14874
Poruke: 24
*.math.hr



Profil

icon Re: Citanje integera metodom scanf10.10.2003. u 12:28 - pre 257 meseci
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
Kompletnu odgovornost za sadržaj objavljenih tekstova snose isključivo njihovi autori, čiji je pseudonim jasno označen pored sadržaja teksta.


 
Odgovor na temu

Dejan Krstic

Član broj: 479
Poruke: 2558



+1 Profil

icon Re: Citanje integera metodom scanf21.10.2003. u 15:36 - pre 257 meseci
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.
 
Odgovor na temu

RumRum
Aleksandar Arsin
inženjer mašinskog održavanja
Zemun, Srbija

Član broj: 13022
Poruke: 49
*.ptt.yu

Jabber: rumrum@elitesecurity.org
ICQ: 322104429
Sajt: aarsin.info


+7 Profil

icon Re: Citanje integera metodom scanf08.11.2003. u 04:23 - pre 256 meseci
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,
 
Odgovor na temu

[es] :: C/C++ programiranje :: Citanje integera metodom scanf

[ Pregleda: 5094 | Odgovora: 12 ] > FB > Twit

Postavi temu Odgovori

Navigacija
Lista poslednjih: 16, 32, 64, 128 poruka.