www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Scanf function changes value of in-loop variable

reply "Capture_A_Lag" <bla bla.bla> writes:
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
next sibling parent "bearophile" <bearophileHUGS lycos.com> writes:
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
prev sibling next sibling parent "FreeSlave" <freeslave93 gmail.com> writes:
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
prev sibling next sibling parent Justin Whear <justin economicmodeling.com> writes:
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
prev sibling next sibling parent =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
prev sibling next sibling parent reply "Dicebot" <public dicebot.lv> writes:
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
parent reply "Capture_A_Lag" <bla bla.bla> writes:
Thank you everybody!!!
I thought %d is ok for all integral types.
Apr 16 2014
parent Justin Whear <justin economicmodeling.com> writes:
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
prev sibling parent reply "FreeSlave" <freeslave93 gmail.com> writes:
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
parent reply =?UTF-8?B?QWxpIMOHZWhyZWxp?= <acehreli yahoo.com> writes:
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
next sibling parent "FreeSlave" <freeslave93 gmail.com> writes:
On Wednesday, 16 April 2014 at 18:46:18 UTC, Ali Çehreli wrote:
 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
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.
Apr 16 2014
prev sibling parent reply "FreeSlave" <freeslave93 gmail.com> writes:
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
parent "Capture_A_Lag" <bla bla.bla> writes:
Thanks everyone for figuring everything out!
Apr 16 2014