for loop skips items

Discussion in 'C Programming' started by Qu?bec, Feb 15, 2012.

  1. Qu?bec

    Qu?bec Guest

    How comes the for loop just printf 3 characters?

    1 e
    7 e
    10 e

    The string mixed by C is : J?an Pi?rr?

    =========
    fmt string is "Jean Pierre"
    ---------------
    const char *fmt;
    .....
    strcpy(ligne, fmt);
    ....
    for(i=0;i<11;i++){
    for(j=0;j<65;j++){
    if(alphabet[j] == fmt){
    ligne = alphabet[65-j];
    printf("%d %c\n", i, fmt);
    break;
    }
    }

    }

    ===
    char alphabet[] = {
    '0','1','2','3','4','5','6','7','8','9',
    'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N',
    'O','P','Q','R','S','T','U','V','W','X','Y','Z', ' ',
    'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v','w','x','y','z', '_', '-'};
    Qu?bec, Feb 15, 2012
    #1
    1. Advertising

  2. Qu?bec

    Joe Pfeiffer Guest

    Qu?bec <> writes:

    > How comes the for loop just printf 3 characters?
    >
    > 1 e
    > 7 e
    > 10 e


    I'm guessing there's something important in the code you edited out:

    #include <stdio.h>

    const char fmt[] = "Jean Pierre";

    char alphabet[] = {
    '0','1','2','3','4','5','6','7','8','9',
    'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N',
    'O','P','Q','R','S','T','U','V','W','X','Y','Z', ' ',
    'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    'o','p','q','r','s','t','u','v','w','x','y','z', '_', '-'};

    int main()
    {
    int i, j;
    for(i=0;i<11;i++){
    for(j=0;j<65;j++){
    if(alphabet[j] == fmt){
    printf("%d %c\n", i, fmt);
    break;
    }
    }

    }
    }

    snowball:537$ ./bogus
    0 J
    1 e
    2 a
    3 n
    4
    5 P
    6 i
    7 e
    8 r
    9 r
    10 e
    snowball:538$
    Joe Pfeiffer, Feb 15, 2012
    #2
    1. Advertising

  3. Qu?bec

    Qu?bec Guest

    On Wed, 15 Feb 2012 13:32:02 -0700, Joe Pfeiffer wrote:
    > Qu?bec <> writes:
    >
    >> How comes the for loop just printf 3 characters?
    >>
    >> 1 e
    >> 7 e
    >> 10 e

    >
    > I'm guessing there's something important in the code you edited out:
    >
    > #include <stdio.h>
    >
    > const char fmt[] = "Jean Pierre";
    >
    > char alphabet[] = {
    > '0','1','2','3','4','5','6','7','8','9',
    > 'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N',
    > 'O','P','Q','R','S','T','U','V','W','X','Y','Z', ' ',
    > 'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    > 'o','p','q','r','s','t','u','v','w','x','y','z', '_', '-'};
    >
    > int main()
    > {
    > int i, j;
    > for(i=0;i<11;i++){
    > for(j=0;j<65;j++){
    > if(alphabet[j] == fmt){
    > printf("%d %c\n", i, fmt);
    > break;
    > }
    > }
    >
    > }
    > }
    >
    > snowball:537$ ./bogus
    > 0 J
    > 1 e
    > 2 a
    > 3 n
    > 4
    > 5 P
    > 6 i
    > 7 e
    > 8 r
    > 9 r
    > 10 e
    > snowball:538$


    Hi again sorry for the missing code, I thought it was too much. If you
    never did JNI stay away, you may be scared :)

    Anyway, now I am sure the for loops where good.

    Java calls C witch returns the modified string with the jstring ret.

    Here is the out put

    The string 'Jean Pierre' received by C has 11 characters.
    fmt- e -80- Ã
    fmt- e -80- Ã
    fmt- e -80- Ã
    fmt- 85- Ã
    The string mixed by C is : [?om8§
    in java: [?om8§

    Thanks

    Jean


    ===========
    #include "Serial.h"
    #include <stdlib.h>
    #include <stdio.h>
    #include <string.h>
    #include <stddef.h>
    #define JNI_FALSE 0
    #define JNI_TRUE 1

    char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " <from a
    friend on this group ...
    "abcdefghijklmnopqrstuvwxyz_-";
    const int alphas = sizeof alphabet - 1;

    JNIEXPORT jstring JNICALL Java_Serial_numero
    (JNIEnv *env, jobject jobjc, jstring jstr){
    jboolean iscopy;
    jstring ret;
    jsize len;
    int i, j;
    const char *fmt;
    char alphabet[65];
    char ligne[12];

    fmt = (*env)->GetStringUTFChars(env, jstr, &iscopy);
    len = (*env)->GetStringLength(env, jstr);

    printf("The string '%s' received by C has %d characters.\n", fmt, len );

    for(i=0;i<11;i++){
    for(j=0;j<alphas;j++){
    if(alphabet[j] == fmt){
    printf("fmt- %c ", fmt);
    ligne = alphabet[65-j];
    printf("%d- %c\n",ligne);
    break;
    }
    }
    }

    ligne[12] = '\0';
    printf("The string mixed by C is : %s\n", ligne);

    ret = (jstring)(*env)->NewStringUTF(env, ligne);
    (*env)->ReleaseStringUTFChars(env, jstr, fmt);

    return ret;
    }

    =================
    /* DO NOT EDIT THIS FILE - it is machine generated */
    #include <jni.h>
    /* Header for class Serial */

    #ifndef _Included_Serial
    #define _Included_Serial
    #ifdef __cplusplus
    extern "C" {
    #endif
    /*
    * Class: Serial
    * Method: numero
    * Signature: (Ljava/lang/String;)Ljava/lang/String;
    */
    JNIEXPORT jstring JNICALL Java_Serial_numero
    (JNIEnv *, jclass, jstring);

    #ifdef __cplusplus
    }

    #endif
    #endif
    ===========

    public class Serial
    { static
    {
    System.loadLibrary("serial");
    }

    public static void main(String[] args)
    {
    Serial serie = new Serial();
    String fromC = serie.numero("Jean Pierre");
    System.out.println("in java: " + fromC);
    }

    public native String numero(String one);
    }
    Qu?bec, Feb 15, 2012
    #3
  4. Qu?bec <> writes:
    <snip>
    > Hi again sorry for the missing code, I thought it was too much. If you
    > never did JNI stay away, you may be scared :)


    Fear not. Many of us have been about the block a few times. After IBM
    jCL, nothing is really scary!

    > Anyway, now I am sure the for loops where good.


    They are.

    <snip>
    > char alphabet[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ " <from a
    > friend on this group ...
    > "abcdefghijklmnopqrstuvwxyz_-";


    This is a file-scope array object.

    > JNIEXPORT jstring JNICALL Java_Serial_numero
    > (JNIEnv *env, jobject jobjc, jstring jstr){
    > jboolean iscopy;
    > jstring ret;
    > jsize len;
    > int i, j;
    > const char *fmt;
    > char alphabet[65];


    And this is an automatic (function-local) array object with the same
    name. It "shadows" the one you correctly defined, effectively hiding
    it. What's worse, it's uninitialised, so it may contain any old junk.

    Just delete this line.

    <snip>
    --
    Ben.
    Ben Bacarisse, Feb 15, 2012
    #4
  5. Qu?bec

    Noob Guest

    Noob, Feb 16, 2012
    #5
  6. Kenneth Brody <> writes:

    > On 2/16/2012 4:49 AM, Noob wrote:
    >> Ben Bacarisse wrote:
    >>
    >>> Fear not. Many of us have been about the block a few times.
    >>> After IBM jCL, nothing is really scary!

    >>
    >> Not even http://en.wikipedia.org/wiki/Brainfuck ?

    >
    > Ever try reading WhiteSpace source code from hardcopy?


    No, but then I've never *had* to use either. It's a bit like hungry
    polar bears -- not at all scary because I don't expect to be on an ice
    floe any time soon!

    --
    Ben.
    Ben Bacarisse, Feb 17, 2012
    #6
  7. Qu?bec

    Phil Carmody Guest

    Qu?bec <> writes:
    > How comes the for loop just printf 3 characters?
    >
    > 1 e
    > 7 e
    > 10 e
    >
    > The string mixed by C is : J?an Pi?rr?
    >
    > =========
    > fmt string is "Jean Pierre"
    > ---------------
    > const char *fmt;
    > ....
    > strcpy(ligne, fmt);
    > ...
    > for(i=0;i<11;i++){
    > for(j=0;j<65;j++){


    65 is a magic number. It's not even self-evidently correct as it stands.
    If you were to add another character to your alphabet, you'd need to change
    this line too. If you're attempting to match names, then you'll definitely
    need to change the alphabet, even if you're restricting yourself to ASCII
    - have you never encountered someone with a '.' in their name, for example
    (there's one on comp.lang.c), or even "'"?

    Re-order, and use sizeof().

    Phil

    > if(alphabet[j] == fmt){
    > ligne = alphabet[65-j];
    > printf("%d %c\n", i, fmt);
    > break;
    > }
    > }
    >
    > }
    >
    > ===
    > char alphabet[] = {
    > '0','1','2','3','4','5','6','7','8','9',
    > 'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N',
    > 'O','P','Q','R','S','T','U','V','W','X','Y','Z', ' ',
    > 'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    > 'o','p','q','r','s','t','u','v','w','x','y','z', '_', '-'};


    --
    > I'd argue that there is much evidence for the existence of a God.

    Pics or it didn't happen.
    -- Tom (/. uid 822)
    Phil Carmody, Feb 22, 2012
    #7
  8. Qu?bec

    Joe Pfeiffer Guest

    Phil Carmody <> writes:

    > Qu?bec <> writes:
    >> How comes the for loop just printf 3 characters?
    >>
    >> 1 e
    >> 7 e
    >> 10 e
    >>
    >> The string mixed by C is : J?an Pi?rr?
    >>
    >> =========
    >> fmt string is "Jean Pierre"
    >> ---------------
    >> const char *fmt;
    >> ....
    >> strcpy(ligne, fmt);
    >> ...
    >> for(i=0;i<11;i++){
    >> for(j=0;j<65;j++){

    >
    > 65 is a magic number. It's not even self-evidently correct as it stands.
    > If you were to add another character to your alphabet, you'd need to change
    > this line too. If you're attempting to match names, then you'll definitely
    > need to change the alphabet, even if you're restricting yourself to ASCII
    > - have you never encountered someone with a '.' in their name, for example
    > (there's one on comp.lang.c), or even "'"?
    >
    > Re-order, and use sizeof().


    You raise a good point, but a bit of explanation is probably worth
    while:

    A number that appears in your code with no explanation, as if by magic,
    is a "magic number" (the term comes from a number that was at the
    beginning of an a.out file and identified the file as a.out and also
    defined which of several "types" of a.out file it was. This number was
    actually referred to as the "magic number").

    There are at least two major problems with magic numbers:

    1) They aren't documented. There is no way for someone reading the code
    to see 65 and understand, in isolation, why the number is 65 and not
    64 or 66. Yes, the reader can find the declaration of alphabet, count
    the elements, and realize that 65 is the right number. That's
    needlessly obscure.

    2) They aren't self-correcting. You don't want the number 65, you want
    the elements in the alphabet array. If you add an element, you need to
    locate every single instance of 65 that refers to the number of elements
    in that particular array and change it -- without changing any 65s that
    refer to something else.

    So, there's a pretty well-established rule that a magic number should
    never appear in your code. There are a few numbers that appear so
    frequently and whose meaning is so obvious that they are OK -- 0,
    probably 1, maybe -1, outside chance of 2 -- but those are pretty much
    the list.

    Instead, anyplace you need a constant, you should derive it if
    possible. As Phil says, sizeof(alphabet) is what you really want here.
    In some cases, it's good to derive it in a #define, and use that
    everywhere it appears.

    If there is no way derive it, use a defined constant, like

    #define WORD_SIZE 32

    Then you can:

    #define SIGN_BIT (1 << (WORD_SIZE-1))

    Anecdote: my coding standards for my classes forbade magic numbers.
    The student who turned in a program that included

    #define TEN 10

    was a bit irate when he got docked for a magic number....
    Joe Pfeiffer, Feb 22, 2012
    #8
  9. Qu?bec

    Ike Naar Guest

    On 2012-02-15, Qu?bec <> wrote:
    > How comes the for loop just printf 3 characters?
    >
    > 1 e
    > 7 e
    > 10 e
    >
    > The string mixed by C is : J?an Pi?rr?
    >
    >=========
    > fmt string is "Jean Pierre"
    > ---------------
    > const char *fmt;
    > ....
    > strcpy(ligne, fmt);
    > ...
    > for(i=0;i<11;i++){
    > for(j=0;j<65;j++){
    > if(alphabet[j] == fmt){
    > ligne = alphabet[65-j];
    > printf("%d %c\n", i, fmt);
    > break;
    > }
    > }
    >
    > }
    >
    >===
    > char alphabet[] = {
    > '0','1','2','3','4','5','6','7','8','9',
    > 'A','B','C','D','E','F','G','H','I','J', 'K','L','M','N',
    > 'O','P','Q','R','S','T','U','V','W','X','Y','Z', ' ',
    > 'a','b','c','d','e','f','g','h','i','j','k','l','m','n',
    > 'o','p','q','r','s','t','u','v','w','x','y','z', '_', '-'};


    In addition to the problems reported by others, there's a subtle
    bug in your program: the line

    ligne = alphabet[65-j];

    has undefined behaviour when j equals 0 (which can happen if fmt
    contains the character '0'). You probably want

    ligne = alphabet[65-j-1];

    or, getting rid of the magic number,

    ligne = alphabet[sizeof alphabet - j - 1];
    Ike Naar, Feb 22, 2012
    #9
  10. On Feb 22, 4:43 am, Joe Pfeiffer <> wrote:
    > Phil Carmody <> writes:
    > > Qu?bec <> writes:


    > > 65 is a magic number. [...]

    >
    > You raise a good point, but a bit of explanation is probably worth
    > while:
    >
    > A number that appears in your code with no explanation, as if by magic,
    > is a "magic number" (the term comes from a number that was at the
    > beginning of an a.out file and identified the file as a.out and also
    > defined which of several "types" of a.out file it was.  This number was
    > actually referred to as the "magic number").


    I'm pretty sure the term preceeds this unix usage. I suspect unix
    called it that because of earlier usage.

    For instance the term was apparently in use in the 1960s for the use
    of arbitary constants in FORTRAN and COBOL programs.

    <snip>
    Nick Keighley, Feb 22, 2012
    #10
  11. Joe Pfeiffer <> writes:
    <snip>
    > A number that appears in your code with no explanation, as if by magic,
    > is a "magic number"

    <snip>
    > If there is no way derive it, use a defined constant, like
    >
    > #define WORD_SIZE 32
    >
    > Then you can:
    >
    > #define SIGN_BIT (1 << (WORD_SIZE-1))


    This is undefined but, of course, it may work. I point it out only in
    case some beginners take that as a portable and reliable way to get the
    sign bit. I think

    #define SIGN_BIT (~INT_MAX)

    is bound to work on all conforming C implementations.

    <snip>
    --
    Ben.
    Ben Bacarisse, Feb 22, 2012
    #11
  12. Qu?bec

    Shao Miller Guest

    On 2/22/2012 09:25, Ben Bacarisse wrote:
    >I think
    >
    > #define SIGN_BIT (~INT_MAX)
    >
    > is bound to work on all conforming C implementations.
    >
    > <snip>


    Can that produce a "negative zero"? C99 6.2.6.2p4.
    Shao Miller, Feb 25, 2012
    #12
  13. Qu?bec

    Jens Gustedt Guest

    Am 02/25/2012 11:30 AM, schrieb Shao Miller:
    > On 2/22/2012 09:25, Ben Bacarisse wrote:
    >> I think
    >>
    >> #define SIGN_BIT (~INT_MAX)
    >>
    >> is bound to work on all conforming C implementations.
    >>
    >> <snip>

    >
    > Can that produce a "negative zero"? C99 6.2.6.2p4.


    yes, for sign and magnitude if the implementation doesn't have negative
    zeros, the behavior would be undefined

    do such beasts exist?

    Jens
    Jens Gustedt, Feb 25, 2012
    #13
  14. Jens Gustedt <> writes:

    > Am 02/25/2012 11:30 AM, schrieb Shao Miller:
    >> On 2/22/2012 09:25, Ben Bacarisse wrote:
    >>> I think
    >>>
    >>> #define SIGN_BIT (~INT_MAX)
    >>>
    >>> is bound to work on all conforming C implementations.
    >>>
    >>> <snip>

    >>
    >> Can that produce a "negative zero"? C99 6.2.6.2p4.

    >
    > yes, for sign and magnitude if the implementation doesn't have negative
    > zeros, the behavior would be undefined


    Yes, but in a sense that undefined behaviour doesn't matter as much as
    it usually does! On a sign and magnitude machine which does not support
    negative zero (i.e. where generating 1000...000 is UB) the problem can't
    be solved.

    But I agree I should have said "on all conforming C implementations
    where it's possible to do what is required".

    <snip>
    --
    Ben.
    Ben Bacarisse, Feb 25, 2012
    #14
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Johan
    Replies:
    0
    Views:
    1,797
    Johan
    Oct 7, 2004
  2. Eric Maia

    UserControl sometimes skips validation

    Eric Maia, Nov 18, 2004, in forum: ASP .Net
    Replies:
    2
    Views:
    2,624
    Eric Maia
    Nov 19, 2004
  3. EC
    Replies:
    0
    Views:
    315
  4. David Lozzi

    SELECT TOP 12 Skips one!

    David Lozzi, Feb 9, 2006, in forum: ASP .Net
    Replies:
    1
    Views:
    349
    Steven Cheng[MSFT]
    Feb 9, 2006
  5. Isaac Won
    Replies:
    9
    Views:
    352
    Ulrich Eckhardt
    Mar 4, 2013
Loading...

Share This Page