Thread: Help understanding code (with no comments) that uses for and switch

  1. #1
    Registered User
    Join Date
    Apr 2008
    Posts
    115

    Help understanding code (with no comments) that uses for and switch

    Can someone make some sense out of this code for me. I understand how the switch works but they lost me on the for loop using *fld[NUMFLD]. NUMFLD was defined as 10 and rec is a char array (rec[1000]) containing a line copied from a file. FLDSEP was defined as "|". I posted question on the pointer and it makes some sense now thanks to everyone who helped answer my questions. Now I am confused again. I can probably get thru id I knew what was happening during the for loop. Thanks for any assistance.

    Code:
        920     int     fldcnt = 0;
        921     char    *fld[NUMFLD]; - *fld[10]
        922     int     error_flag = 0;
        923     char    tmprec[MAXRECLEN]; - tmprec[1000]
        924     int     index = 0;
        925
        926     sprintf(jnl.mesg,"%s",rec); 
        927     log_it(log_file,jnl);
        928
        929     strcpy(tmprec,rec); - copy the line into tmprec[1000]
        930     bzero(&fld,NUMFLD); 
        931     for (fld[fldcnt] = strtok(tmprec,FLDSEP); 
        932         fld[fldcnt] != NULL;
        933         fld[++fldcnt] = strtok(NULL,FLDSEP))
        934     {
        935         strip_trailing_spaces(fld[fldcnt]);
        936
        937         switch(fldcnt)
        938         {
        939             case 0:     /* bol */
        940                 pgi_ack_file.bol = atoi(fld[fldcnt]);
        941                 break;
        942             case 1:     /* delivery */
        943                 strcpy(pgi_ack_file.delivery,fld[fldcnt]);
        944                 break;
        945             case 2:     /* delivery_item */
        946                 pgi_ack_file.delivery_item = atoi(fld[fldcnt]);
        947                 break;
        948             case 3:     /* mfg_std */
        949                 pgi_ack_file.mfg_std = atoi(fld[fldcnt]);
        950                 break;
        951             case 4:     /* num_skids */
        952                 pgi_ack_file.num_skids = atoi(fld[fldcnt]);
        953                 break;
        954             case 5:     /* skid_num */
        955                 pgi_ack_file.skid_num = atoi(fld[fldcnt]);
        956                 break;
        957             case 6:     /* unit */
        958                 strcpy(pgi_ack_file.unit_txt,fld[fldcnt]);
        959                 break;
        960             case 7:     /* gross weight */
        961                 pgi_ack_file.skid_gross_wght_lbs = atof(fld[fldcnt]);
        962                 break;
        963             case 8:     /* net weight */
        964                 pgi_ack_file.skid_net_wght_lbs = atof(fld[fldcnt]);
        965                 break;
        966             case 9:     /* storage location */
        967                 pgi_ack_file.storage_location = atoi(fld[fldcnt]);
        968                 break;
        969             default:
        970                 strcpy(jnl.mesg,"Too many fields in record");
        971                 log_it(log_file,jnl);
        972                 sprintf(jnl.mesg,"Bad fldcnt %d. should be %d",fldcnt,NUMFLD);
        973                 log_it(log_file,jnl);
        974                 error_flag = 1;
        975                 break;
        976         }
        977
        978         if (error_flag == 1) return (IMCS_DB_FATAL);
        979     }
        980
        981     if (fldcnt != NUMFLD)
        982     {
        983         strcpy(jnl.mesg,"Too few fields in record");
        984         log_it(log_file,jnl);
        985         sprintf(jnl.mesg,"Bad fldcnt %d. should be %d",fldcnt,NUMFLD);
        986         log_it(log_file,jnl);
        987         error_flag = 1;
        988         return (IMCS_DB_FATAL);
        989     }

  2. #2
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Interesting use of for-loop, essentially, it loops through all the fields in the tmprec, incrementing fldcnt when getting the "next" one.
    Code:
         for (fld[fldcnt] = strtok(tmprec,FLDSEP); 
             fld[fldcnt] != NULL;
             fld[++fldcnt] = strtok(NULL,FLDSEP))
    I personally would probably have written it like this:
    Code:
         for (fldcnt = 0, fld[fldcnt] = strtok(tmprec,FLDSEP); 
             fld[fldcnt] != NULL;
             fld[fldcnt++] = strtok(NULL,FLDSEP))
    to make sure it's clear fldcnt is starting at zero when you begin.


    The switch is simply using the fldcnt to take the separated strings into their respective fields in a struct, using atoi(), atof() and strcpy() to convert/copy the value itself.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  3. #3
    Registered User
    Join Date
    Apr 2008
    Posts
    115

    I think I understand the first line of for loop but the rest is still confusing

    for (fld[fldcnt] = strtok(tmprec,FLDSEP);

    I believe this is setting *fld[0] = first token in the first line that was stored in temprec[1000] and from here (somehow) it will continue storing the remaining 10 tokens into *fld[0...10]. I looked at one of the files and sure enough there are 10 "fields" all seperated by |. Hope this helps someone help me with the rest. Thanks.

    -Carl

  4. #4
    Registered User
    Join Date
    Apr 2008
    Posts
    115

    Thanks matsp

    Thanks for taking time to explain that to me. I posted right after you did so I guess I am on the right path.

    -Carl

  5. #5
    Registered User
    Join Date
    Apr 2008
    Posts
    115

    Still having problem with one line

    fld[fldcnt++] = strtok(NULL,FLDSEP))

    What is happening here? Thanks.

    -Carl

  6. #6
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Actually, it should only fill in 0..9 of fld[], and fldcnt should be 10 when the loop exits.

    The code is actually broken in the case where the incoming data has more than 9 '|' in the line, it will overflow the fld[] array, so a more correct function would be:
    Code:
    for (fldcnt = 0, fld[fldcnt] = strtok(tmprec,FLDSEP); 
             fldcnt < 10 && fld[fldcnt] != NULL;
             fld[++fldcnt] = strtok(NULL,FLDSEP))
    or
    Code:
    for (fldcnt = 0, fld[fldcnt] = strtok(tmprec,FLDSEP); 
             !errorflag && fld[fldcnt] != NULL;
             fld[fldcnt++] = strtok(NULL,FLDSEP))
    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  7. #7
    Kernel hacker
    Join Date
    Jul 2007
    Location
    Farncombe, Surrey, England
    Posts
    15,677
    Quote Originally Posted by cjohnman View Post
    fld[fldcnt++] = strtok(NULL,FLDSEP))

    What is happening here? Thanks.

    -Carl
    strtok looks something like this internally:
    Code:
    char *strtok(char *str, int sep)
    {
        static char *oldstr;
        char *orig = str; 
        if (str == NULL) str = oldstr;
        while(str && *str != sep) str++;
        if (!str) {
           oldstr = NULL;
           return NULL;
        }
        oldstr = str +1;  // Point to 
        return orig;
    }
    So if you pass in NULL, it will use the previous string after the current separotor.

    --
    Mats
    Compilers can produce warnings - make the compiler programmers happy: Use them!
    Please don't PM me for help - and no, I don't do help over instant messengers.

  8. #8
    Registered User
    Join Date
    Apr 2008
    Posts
    115

    Thanks

    Thank you. I will now move on to the struct. Fun stuff. Who knows maybe in 6 months with the help of this site and my books I may get to be a average programmer. NOT.

    -Carl

Popular pages Recent additions subscribe to a feed