digitalmars.D.learn - Scanf function changes value of in-loop variable
- Capture_A_Lag (18/18) Apr 16 2014 Hi all!
- bearophile (4/6) Apr 16 2014 Have you tried to use a tmp of type int to avoid stomping?
- FreeSlave (4/22) Apr 16 2014 I suppose it's because scanf wait for int variable (which 4
- Justin Whear (11/34) Apr 16 2014 ------------------------------------------------------------------------...
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (5/8) Apr 16 2014 %d is for int.
- Dicebot (7/25) Apr 16 2014 scanf is inherently unsafe routine and does not protect you from
- Capture_A_Lag (2/2) Apr 16 2014 Thank you everybody!!!
- Justin Whear (5/7) Apr 16 2014 This is true when using the D format functions (e.g. readf) which are
- FreeSlave (3/3) Apr 16 2014 Note that readf is not equivalent to scanf since readf does not
- =?UTF-8?B?QWxpIMOHZWhyZWxp?= (4/6) Apr 16 2014 Just like in scanf, a single space character is sufficient to consume
- FreeSlave (6/14) Apr 16 2014 My mistake. I thought spaces are counted precisely (or maybe it's
- FreeSlave (3/3) Apr 16 2014 It also throws if you input initial or trailing spaces and there
- Capture_A_Lag (1/1) Apr 16 2014 Thanks everyone for figuring everything out!
Hi all! I have this code: ------------------------------------------------------------------------------ ubyte N, M, K; ubyte[][max][max] Matrix; scanf("%d %d %d", &N, &M, &K); ubyte tmp; for(ubyte n = 1; n <= N; n++) for(ubyte m = 1; m <= M; m++) { scanf("%d", &tmp); // After this scanf n becomes 0 for no reason if(tmp) Matrix[m][tmp] ~= n; } ------------------------------------------------------------------------------ After scanf in loop variable n becomes 0. Is this a bug? Please help me!
Apr 16 2014
Capture_A_Lag:After scanf in loop variable n becomes 0. Is this a bug? Please help me!Have you tried to use a tmp of type int to avoid stomping? Bye, bearophile
Apr 16 2014
On Wednesday, 16 April 2014 at 17:47:05 UTC, Capture_A_Lag wrote:Hi all! I have this code: ------------------------------------------------------------------------------ ubyte N, M, K; ubyte[][max][max] Matrix; scanf("%d %d %d", &N, &M, &K); ubyte tmp; for(ubyte n = 1; n <= N; n++) for(ubyte m = 1; m <= M; m++) { scanf("%d", &tmp); // After this scanf n becomes 0 for no reason if(tmp) Matrix[m][tmp] ~= n; } ------------------------------------------------------------------------------ After scanf in loop variable n becomes 0. Is this a bug? Please help me!I suppose it's because scanf wait for int variable (which 4 bytes), but you pass pointer to ubyte, and when you input data it overwrites neighbor bytes.
Apr 16 2014
On Wed, 16 Apr 2014 17:47:03 +0000, Capture_A_Lag wrote:Hi all! I have this code:------------------------------------------------------------------------------ubyte N, M, K; ubyte[][max][max] Matrix; scanf("%d %d %d", &N, &M, &K); ubyte tmp; for(ubyte n = 1; n <= N; n++) for(ubyte m = 1; m <= M; m++) { scanf("%d", &tmp); // After this scanf n becomes 0 for no reason if(tmp) Matrix[m][tmp] ~= n; }------------------------------------------------------------------------------After scanf in loop variable n becomes 0. Is this a bug? Please help me!You are using the wrong format spec for an unsigned ubyte; switch out all instances of "%d" with "%hhu" and it should work. Short version: the "% d" instructs the C scanf function to overwrite 32bits of the stack starting at tmp which is only 8 bits long. Even better than using the proper format spec, you could swap out the non- typesafe C functions and use the D equivalents readf and formattedRead (see std.stdio and std.format). Justin
Apr 16 2014
On 04/16/2014 10:47 AM, Capture_A_Lag wrote:ubyte tmp;scanf("%d", &tmp); // After this scanf n becomes 0 for no reason%d is for int. Ali P.S. A friendly request: It makes it much easier for the rest of the group if posts contained compilable, minimal but complete code. Thanks.
Apr 16 2014
On Wednesday, 16 April 2014 at 17:47:05 UTC, Capture_A_Lag wrote:Hi all! I have this code: ------------------------------------------------------------------------------ ubyte N, M, K; ubyte[][max][max] Matrix; scanf("%d %d %d", &N, &M, &K); ubyte tmp; for(ubyte n = 1; n <= N; n++) for(ubyte m = 1; m <= M; m++) { scanf("%d", &tmp); // After this scanf n becomes 0 for no reason if(tmp) Matrix[m][tmp] ~= n; } ------------------------------------------------------------------------------ After scanf in loop variable n becomes 0. Is this a bug? Please help me!scanf is inherently unsafe routine and does not protect you from type mismatch. In your snipper "%d" implies that argument is address of integer variable, however you supply it address of ubyte one. As loop variable happens to be on stack right next to `tmp` variable, it gets stomped when sizeof(int) bytes get written to &tmp
Apr 16 2014
Thank you everybody!!! I thought %d is ok for all integral types.
Apr 16 2014
On Wed, 16 Apr 2014 18:17:37 +0000, Capture_A_Lag wrote:Thank you everybody!!! I thought %d is ok for all integral types.This is true when using the D format functions (e.g. readf) which are able to inspect the types of the variables being assigned, but scanf is a C function and not typesafe. Justin
Apr 16 2014
Note that readf is not equivalent to scanf since readf does not skip spaces and newline character. Input must completely match format.
Apr 16 2014
On 04/16/2014 11:36 AM, FreeSlave wrote:Note that readf is not equivalent to scanf since readf does not skip spaces and newline character. Input must completely match format.Just like in scanf, a single space character is sufficient to consume zero or more whitespace characters. Ali
Apr 16 2014
On Wednesday, 16 April 2014 at 18:46:18 UTC, Ali Çehreli wrote:On 04/16/2014 11:36 AM, FreeSlave wrote:My mistake. I thought spaces are counted precisely (or maybe it's old behavior). But you still should add \n at the end of format to avoid format exceptions. That does not make sense for console input since every input ended with Enter, which makes newline anyway.Note that readf is not equivalent to scanf since readf does not skip spaces and newline character. Input must completely match format.Just like in scanf, a single space character is sufficient to consume zero or more whitespace characters. Ali
Apr 16 2014
It also throws if you input initial or trailing spaces and there are no spaces at the start or end of format string (scanf skips these spaces)
Apr 16 2014