Thread: character array filling with junk

  1. #16
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    To call fflush(stdin) "garbage" seems an emotional (anti-windows) reaction.
    O_o

    Now who's trying to start something? [Edit]Yes. That was a joke.[/Edit]

    Seriously though, you are being paranoid--at least "fanboyish"--if you think my reaction is born of being "anti-windows". (I am more "pro-standard" and "pro-do what it says on the label".) To be clear, I'd call any other mechanism the standard doesn't cover masquerading as standard behavior garbage; for example, I'd call it garbage when a vendor ships a `strdup' with "string.h". (Yes, I also called it garbage when Borland liked to pretend that "graphics.h" was standard.) If the mechanic was provided under `void _fpurge(FILE*)' with "string.h" or `void fpurge(FILE *)' in a header not shipping as standard I would not have a problem with the mechanic being provided. So, I do not have a problem with the mechanic.

    Of course, I do also have a problem with the name `fflush' in respect to streams open only for reading. Seriously, what does `fflush(stdin)' say? Clear any errors? Read until the next token? Read until the next line? Restore characters already consumed as part of the previous read operation?

    As for the mechanism, a strategy for processing input with `fgets' followed by formatting has already been referenced, and when done properly, you don't need a system specific `fflush(stdin)' because the underlying stream isn't being tasked with "dirty" input. (You only ask for characters, and you only get characters.) I'm not against a form of "reset" being available, but I would not want an application I'm using to throw away my input "until newline" just in case I've entered multiple values on one line.

    In my opinion, a sane gcc build for a windows environment should define fflush(stdin) to either do nothing or to do what the windows compiler runtime does.
    The argument that Microsoft should have the final say with extensions to C on "Windows" simply because they ship both "Windows" and a compiler is ridiculous. Your opinion necessarily results in and of believing that one vendor should have final say on "undefined behavior". Where does this end? How do you choose which vendor sets the standard? Are you going to pick and choose other extensions regarding "undefined behavior"? Does one vendor get the final word on all "undefined behavior"? Feel free to hold whatever opinion you wish, but you are building on flawed logic; the code is "undefined behavior" so you shouldn't be relying on it regardless of your opinion.

    *shrug*

    That is what "undefined behavior" means.

    [Edit]
    Also, your compiler has nothing to do with the availability of a `fflush(stdin)' defined as clearing errors/consuming input until newline; the availability is found within the standard library "runtime". With your build of "GCC", assuming a "MinGW" variant, you are almost certainly using the same "MSVCRT.DLL" as distributed by Microsoft with earlier "Visual C++" environments which has long been a shipping part of "Windows".

    I don't mean to be harping on this idea, but the notion of the "runtime" behaving differently with this bit of "undefined behavior" is exactly the issue being discussed.
    [/Edit]

    Soma
    Last edited by phantomotap; 01-30-2014 at 02:10 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  2. #17
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    @oogabooga:
    I agree, the fflush(stdin) "extended" behavior you speak of is reasonable in that spirit, but it is an extension, and still undefined behavior when considering portability, or C at large.

    Regarding the undefined behavior, here's some relevant bits of the standard:
    Definition of undefined behavior
    Quote Originally Posted by C11 3.4.3
    3.4.3
    1 undefined behavior
    behavior, upon use of a nonportable or erroneous program construct or of erroneous data,
    for which this International Standard imposes no requirements
    2 NOTE Possible undefined behavior ranges from ignoring the situation completely with unpredictable
    results, to behaving during translation or program execution in a documented manner characteristic of the
    environment (with or without the issuance of a diagnostic message), to terminating a translation or
    execution (with the issuance of a diagnostic message).
    3 EXAMPLE
    An example of undefined behavior is the behavior on integer overflow.
    fflush details:
    Quote Originally Posted by C11 7.19.5.2 p2
    2 If stream points to an output stream or an update stream in which the most recent
    operation was not input, the fflush function causes any unwritten data for that stream
    to be delivered to the host environment to be written to the file; otherwise, the behavior is
    undefined.
    My reading of that is:
    fflush(stdin) will result in undefined behavior.
    Undefined behavior (per 3.4.3 p2) is inherently not portable. Each implementation can choose to fail translation, or behave in a documented manner or do something else.

    This highlights the difficulty of portability and working with undefined behavior. Any undefined behavior is not portable. It may be safe and sane, and useful on one system, but totally broken on another. The C standard can't specify some things due to differences in features on various platforms -- some things just may not be possible. For example, the facility for checking whether anything is in the input buffer (a "peek" function), needed for a non-blocking call to fflush(stdin) -- since the getchar() loop looking for '\n' or EOF may block on an empty input buffer -- may not be present on a given platform.

    As for the "sane gcc build for Windows environment":
    You may be conflating GCC and glibc. GCC, strictly speaking, is the compiler (and for the purpose of this discussion, the preprocessor and linker too). It should not know or care what fflush(stdin) does when called, it should simply compile your code with the headers and runtime library you specify; what fflush(stdin) does is for the runtime library to decide. GCC could compile/link your code with the MSVC run time library and headers, so fflush(stdin) does what you want. Or it could use glibc runtime and headers, compiled for Windows, which might causes a seg fault on fflush(stdin); both would be valid per the C standard. What you're really talking about here is more of a "Windows C standard". Such a standard could say something to the effect of "all C runtime implementations on Windows platforms must support the C standard, and furthermore must define fflush(stdin) to flush the input buffer to the next newline or EOF; or to do return immediately if the input buffer is empty". But such a standard does not exist. And even if it did, you could write a "pure C" implementation that ignored any of the extra "Windows C standard" requirements, and still have a valid C runtime library.

    Hope that clears things up a bit.

  3. #18
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    @Soma:

    How can a
    "runtime" [behave] differently with this bit of "undefined behavior"
    If it's undefined, it's undefined. Undefined means that the implementation is able to do absolutely anything it wants to. It's under no obligation to trash memory, erase the disk and set your keyboard on fire. Although that is certainly an option.


    In particular, it doesn't have to leave it "undefined". That's my only real point here.


    However, relying on definitions outside the standard is, of course, non-portable and I agree that that is what should be pushed on the forum. I just feel that many people misunderstand what "undefined behavior" means.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  4. #19
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    So, I found a problem with reads that omitted some critical information. I now have it to the point where I am at 196 out of 197 pieces of information successfully imported, but *1* piece isn't.

    I'm going to change the numbers and letters here to avoid revealing data, but the rest should be accurate:

    The data (multiple iterations of this at 15-minute intervals):
    Code:
    ZZZ_0041228_02:00:12 GOOD0001‡ 02.00.09  UNRELATED MESSAGE THAT I AM TESTING FOR
    ZZZ_0041229_02:00:12                                                              
    ZZZ_0041230_02:00:12 HEADING         HEADING        HEADING    HEADING   
    ZZZ_0041231_02:00:12 HEADING         HEADING        HEADING     
    ZZZ_0041232_02:00:12 ------------------------------------------------------------  _
    ZNU_0041233_02:00:12 <02:00:08> CMDLN 0E0*
    ZZZ_0041234_02:00:12   1Z              XXXX           00A        15               
    ZZZ_0041235_02:00:12   1X              XXXX           101         3               
    ZZZ_0041236_02:00:12                                                              
    ZZZ_0041237_02:00:12 TOTAL AVAILABLE RESOURCES   55555
    ZZZ_0041238_02:00:12                                                              
    ZZZ_0041239_02:00:12 TOTAL RESOURCES INUSE  33333 _
    The code as I've changed it to now:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <errno.h>
    const char stats[45]="UNRELATED MESSAGE THAT I AM TESTING FOR";
    const char inits[45]="                                       ";
    const char triu[20]="L RESOURCES I";
    const char tspa[20]="             ";
    
    void IterateDay(int date);
    int cInputString(int iMaxChar, char *cArr, int iValidate);
    
    int main(int argc, char *argv[])
    {
      printf("Welcome to TPBS Report Generator v0.1\n");
      printf("Program currently only looks at a single month at a time\n\n");
      int iDays = 0;
    //  int iDays = 1;  //For testing, comment do/while and uncomment this line
      char cYear[6];
      char cMo[4];
      int iLnCt = 0;
      int iChVal = 0;
      printf("Enter the Year in YYYY format:\n");
      cInputString(4,cYear,2);
      do
      {
        printf("Enter the Month in MM format:\n");
        cInputString(2,cMo,2);
        if(cMo[0] == '0')
        {
          switch (cMo[1])
            {
              case '1':
              case '3':
              case '5':
              case '7':
              case '8': iDays = 31; break;
              case '4':
              case '6':
              case '9': iDays = 30; break;
              case '2':
                {
                  if(atoi(cYear)%4==0) iDays = 29;
                  else iDays = 28; 
                  break;
                }
            }
        }
        else if(cMo[0] == '1')
        {
          if(cMo[1] == '0' || cMo[1] == '2') iDays = 31;
          if(cMo[1] == '1') iDays = 30;
        }
      }
      while(iDays < 28);
      cYear[4] = '\0';
      cMo[2] = '\0';
      char cInput[8];
      strcpy(cInput,cYear);
      strcat(cInput,cMo);
    //  printf("cInput: %s\n",cInput);
    //  system("PAUSE");
      char str[200]=" ";
      char spac[1]=" ";
      int ch;
      FILE *fp;
      FILE *finuse;
      FILE *ftpbs;
      char cOutInuse[80];
      char cOutTPBS[80];
      snprintf(cOutInuse, sizeof(cOutInuse), "c:\\%s inuse.csv",cInput);
      snprintf(cOutTPBS, sizeof(cOutTPBS), "c:\\%s TPBS.csv",cInput);
      finuse=fopen(cOutInuse, "w+");
      if(finuse == NULL) printf("Inuse Write File Error: %s\n", strerror(errno));
      else
      {
        fprintf(finuse,"Date/Time,Total Resources Inuse\n");
        fflush(finuse);
      }
      fclose(finuse);
      ftpbs=fopen(cOutTPBS, "w+");
      if(finuse == NULL) printf("TPBS Write File Error: %s\n", strerror(errno));
      fclose(ftpbs);
      char tim[10]="        ";
      strcpy(str,inits);      
      char tp[6]="  ";       
      char bs[6]="    ";     
      char to[6]="   ";      
      char pc[6]="  ";       
      char inuse[8]="      "; //Total Resources Inuse
      int iSpace = 0;
      int iTotal = 0;
      int InStats=0;          //value to indicate position inside stats loop
      int i=0;                //Counter
      int k;
      char cInputFile[80];
      char cPath[25] = "C:\\*****************\\"; //redacted
      char cAppend[28] = "**********************.LOG"; //redacted
      for(k=1;k<=iDays;k++)
      {
        if(k<10)
        {                       
          snprintf(cInputFile, sizeof(cInputFile), "%s%s0%i %s",cPath,cInput,k,cAppend);
        }
        else snprintf(cInputFile, sizeof(cInputFile), "%s%s%i %s",cPath,cInput,k,cAppend);
        printf("cInput: %s\n",cInput);
        fp=fopen(cInputFile, "r+");
    //    fp=fopen("C:\\test.txt", "r+");
        if(fp == NULL) printf("Read File Error: %s", strerror(errno));
        else
        {
          printf("Reading %s\n",cInputFile);
    //      printf("cInput: %s\n",cInput);      
    //      system("PAUSE");
          while((ch=fgetc(fp)) != EOF)
          {
            if(i>11 && i<20) tim[i-12]=ch;
            if((ch=='\n' || ch=='\r') && !InStats) //if hitting \n while instats TRUE
                                                   //we need to store the stats first
              {
                if(strcmp(str,stats)==0) InStats=1;
                i=-1;
                iChVal = 0;
    //            strcpy(tim,"        ");
                strcpy(str,inits);
              }
            else if(i>40 && !InStats) str[i-41]=ch;
            else if(InStats)
            {
              if(i>24 && i<39)
              {
                str[i-25]=ch;
    //          printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
              }
              if(i==23) 
              {
    //          printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
    //            printf("i = 23");
                if(ch>=49) 
                {
    //              printf("ch = 49");
                  iSpace++; 
                  tp[i-23]=ch;
                }
                else
                {
    //              printf("ch = %i",ch);
                }
              }
              else if(i==24) 
              {
    //                         printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
    //            printf("time = %s",tim);
    //            printf("iSpace = %i\n",iSpace);
    //            printf("ch = %i\n",ch);
    //            if(ch>=58 && ch<=123 && iSpace==1)
    //            {
                  iSpace++; 
                  tp[i-23]=ch;
                  tp[i-22]='\0';
    //              printf("tp = %s\n",tp);
    //            }
    /*            else
                {
                  iSpace=0;
                  tp[i-23]='\0';
                }*/
    //            system("PAUSE");
              }
              else if(i==38)
              {
                str[13]='\0';
                if(strcmp(str,triu)==0) iTotal=1;
                if(strcmp(str,tspa)==0)
                {
                  iSpace++;
    //            printf("str: %s\n",str);
    //            printf("iSpace = %i\n",iSpace);
    //            printf("iTotal = %i\n",iTotal);
    //            system("PAUSE");            
    //            bs[i-39]==ch;
                }
              }
              else if(i>38 && i<43 && iSpace==3) bs[i-39]=ch;
              else if(i>38 && i<43 && iSpace!=3) iSpace=0;
              else if(i==43 && iSpace==3) bs[i-39]='\0';
              else if(i>53 && i<57 && iSpace==3) to[i-54]=ch;
              else if(i==57 && iSpace==3) to[i-54]='\0';
              else if(i>64 && i<67 && iSpace==3) pc[i-64]=ch;
              else if(i>=43 && i<=47 && iTotal==1) inuse[i-43]=ch;
              else if(i==48 && iTotal==1)
              {
    //          printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
    //            printf("Yay!\niSpace = %i\n",iSpace);
    //            printf("iTotal = %i",iTotal);
    //            system("PAUSE");                       
                inuse[i-43]=ch;
                inuse[i-42]='\0';
                finuse=fopen(cOutInuse, "a+");
                fprintf(finuse,"%s/%i/%s %s,%s\n",cMo,k,cYear,tim,inuse);
                fflush(finuse);
                fclose(finuse);
    //            printf("%s/%i/%s %s,%s\n",cMo,k,cYear,tim,inuse);
                InStats=0;
                iTotal=0;
                i=-1;     
              }
              else if(i==67 && iSpace==3)
              {
    //          printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
                pc[i-64]=ch;
                pc[i-63]='\0';
                ftpbs=fopen(cOutTPBS, "a+");
                fprintf(ftpbs,"%s/%i/%s %s,%s,%s,%s,%s\n",cMo,k,cYear,tim,tp,bs,to,pc);
                fflush(ftpbs);
                fclose(ftpbs);
    //            printf("%s/%i/%s %s,%s,%s,%s,%s\n",cMo,k,cYear,tim,tp,bs,to,pc);
    //            printf("%s\n",pc);
                iSpace=0;
                i=-1;
              }
              else if(ch=='\n' || ch=='\r')
              {
    //          printf("i: %i\n",i);
    //          printf("ch: %i\n",ch);
    //          system("PAUSE");
                iSpace=0;
                iTotal=0;
                i=-1;
                ch=0;
              }
            }
            i++;
          }
        }
        fflush(stdin);
        fflush(fp);
        printf("%s done\n\n\n",cInputFile);
    //    printf("cInput: %s\n\n\n",cInput);
    //    strcpy(cInput,cInputCopy);
    //    printf("k: %i\n",k);
    //    printf("cAppend: %s\n",cAppend);
    //    system("PAUSE");    
        fclose(fp); 
      }
      printf("Files written:\n%s\n%s\n",cOutInuse,cOutTPBS);
      system("PAUSE");    
      return 0;
    }
    
    int cInputString(int iMaxChar, char *cArr, int iValidate)
    {
    /* This is a character input function to limit the length of characters
       inputted by the user.  This is necessary because without using such a 
       function, user could overrun the input stack and cause errors.  It'll 
       accept single-character inputs until it hits the number of characters 
       requested (iMaxChar) or until the user hits Enter. */
    /* iValidate determines whether to check for input.  Data is checked based on
       the following table:
       0: do not check data
       1: verify all data is alpha (lower and upper-case letters)
       2: verify all data is numeric */
    /* int return is the length of the characters inputted */
      fflush(stdin);
      char cC;
      int iCount = 0;
      do
        {
          cC = getch();
          printf ("%c",cC);
          switch (iValidate)
          {
            case 1:
            {
              if((isalpha(cC))||cC==' '||cC==0xd)
              {
                cArr[iCount] = cC;
                ++iCount;
                break;
              }
              else
              {
                printf("\nInvalid Entry, use only letters.  Please try again: ");
                break;
              }
            }
            case 2: 
              {   
              if (!isdigit(cC))
                {
                  printf("\nInvalid Entry, use only numbers.  Please try again: ");
                  break;
                }
              else if (cC == 0xd) break;
              else
                {
                  cArr[iCount] = cC;
                  ++iCount;
                  break;
                }
              }
            default:
              {                 
                cArr[iCount] = cC;
                ++iCount;
                break;
              }
          }
        }
      while (iCount < iMaxChar && cC != 0xd);
      printf ("\n");
      fflush(stdin);
      return iCount;
    }
    That 1Z line isn't getting picked up - it should, but it isn't. When I go over the entire file, it's simply missing from my output. When I go over just this small test file, it puts it in the output, but for some reason the *time* changes to something that shouldn't even be possible (00:00:15 - the same time as the first iteration in my full file).
    Last edited by reillan; 01-30-2014 at 03:21 PM.

  5. #20
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    I should note that my suspicion has to do with the following line:
    <02:00:08> CMDLN 0E0*

    This is the only time that line interrupts the rest of the data in the first file I'm looking at. I haven't checked the rest of the days yet to verify if they work.

  6. #21
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    [Edit]
    @oogabooga:

    No doubt, I may indeed have read too much into what you've said because they way you said it led me to so interpret.

    I appreciate what you are saying. I am not saying that you are wrong as such because I'm no sure what you are saying. If you are only saying that "undefined behavior" may be well-defined to some purpose in certain circumstances you are entirely correct.

    Your reference of expectations with "Windows" and "his choice" in using "undefined behavior" makes me think that you interpret "undefined behavior" as reliable with respect to some particular aspect of an environment implying a "The code is actually well-defined." mentality just because one environment says that the code is well-defined.

    That mindset is wrong, but if that isn't what you've said, if I've poorly understood, then we not need continue this side discussion.
    [/Edit]

    In particular, it doesn't have to leave it "undefined". That's my only real point here.
    O_o

    Well, that is entirely correct, but your statements suggest that you believe that "undefined behavior" is reliable once defined by some vendor.

    o_O

    Yeah, it seems that you also misunderstand what "undefined behavior" means.

    Example:
    In my opinion, a sane gcc build for a windows environment should define fflush(stdin) to either do nothing or to do what the windows compiler runtime does.
    For example, on my machine with the gcc imp that I have, the following program shows that fflush(stdin) actually "flushes" the input buffer.
    Well, that surely may and probably is the case, but Microsoft having defined this bit of "undefined behavior" only governs the specific "runtime" in question.

    The standard library implementation provided by other vendors do not have to honor how Microsoft defined this bit of "undefined behavior".

    Microsoft does not have to honor how they defined this bit of "undefined behavior".

    So, for example, your "GCC" environment under "Windows" probably used the "MSVCRT.DLL" as a standard library implementation. Because your environment currently uses the "MSVCRT.DLL" library, you are allowed to this bit of "undefined behavior" with certain expectations. Yes. Your environment has effectively defined the behavior, but that places no burden on any other environment.

    To continue the example, if you were to now to use my debug library, linking it instead of "MSVCRT.DLL", the application would producing an error doing nothing whatever to the stream--`FILE *'. Yes. The environment employed by using my debug library has effectively defined (Specifically, passing a stream opened only for reading to `fflush' writes an error message to the `FILE *' returned by `sda_log' without doing anything at all to the `FILE *' provided.) the behavior, but as before, that places no burden on any other environment.

    The two "runtimes", mine and "MSVCRT.DLL", behave differently with respect to this bit of "undefined behavior". To be sure, both behaviors are equally valid, but no less is a fact, you can't rely on either behavior from other environments even though these two specific environments have chosen to define the behavior because the code is "undefined behavior".

    The same logic applies to `fflush(stdin)'; just because the code is well-defined in one specific case does not imply that the code is somehow not "undefined behavior". That is the nature of "undefined behavior"; the exhibited behavior is allowed to change for any reason or without reason.

    Again, look at the quoted "C11 3.4.3" (I'm advising that because I'm too lazy to post it myself.): the "undefined behavior" section specifically references executing in a "documented manner". So, yes, an implementation doesn't have to leave "undefined behavior" as "undefined", but your code remains dependent on "undefined behavior". In other words, an environment specifically documenting some bit of "undefined behavior" does not magic away the fact the relevant code depends on "undefined behavior" within the standard.

    Soma
    Last edited by phantomotap; 01-30-2014 at 04:03 PM.
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  7. #22
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    @reillan

    In difference to you for somewhat hijacking the thread:

    Is this data representative? (That is, similar to even if not identical to a real set of data.)
    If so, have you considered that the "suspicious" line seems to be "out-of-band" data?
    Is it possible that the "out-of-band" is indicative of an error in the generating process/annotations to the data representing human information?

    I only ask because, despite the "magic numbers", it seems likely that you are correct in "suspecting" that line as you don't seem to have done anything to parse that data.

    As a matter of convenience, for us, if you post again please consider providing a properly "baked" example.

    For example, if a value is expected to be only lower case, use only lower case characters to represent the field, of if the value is expected to be a date, use only ':' or possible 'D' to represent the field.

    The data as posted, even if representative, seems only conducive to space delimited parsing, but from your comments it seems as if you need to specifically handle certain values which you also seem to avoid.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  8. #23
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    So this is a TPF system that's generating data to a log file, and as is the nature of TPF, sometimes one command gets interrupted with another command. Now, I only have to read the log file and generate a report, which is great news for me, as I don't have to run my program ON that TPF system. But, there are frequent interruptions.

    The frequent interruptions are why I wrote my program to do the following:

    1. Cull the entire log for a specific phrase
    2. Once in that specific phrase, look for data in expected locations. The "1Z" in line 7 will always be the 24th and 25th characters in that line, for instance. If there's a better way of determining my line position than resetting a counter and incrementing it after every character read, I'd love to know it, btw.
    3. If it finds at least a minimum amount of expected data in expected locations, it records the remaining data and records it to a file (it may be that I'm getting "success" where I should be getting "failure", or vice-versa, and omitting records or overrunning data as a result).
    4. When it finds the phrase "L RESOURCES I", I know that I've hit the very last line of the record. It records the number at the end of the line and resets my "InStats" flag so that it no longer assumes it's within that section of code.

    just realized something - the characters I'm testing for in that line are there... and then the rest aren't. But, because I'm writing those characters to a string and then getting a \n unexpectedly, it may provide my strange overruns... grr...

    (The "DL" characters in my example are actually "TA" in the real file... wish I wasn't in a secure environment or I'd post the real stuff, hah)

  9. #24
    - - - - - - - - oogabooga's Avatar
    Join Date
    Jan 2008
    Posts
    2,808
    @Soma,

    I agree with pretty much all you said, though to ask what fflush(stdin) does is not relevant since it is presumably documented by MS. I don't know and I don't care because I've never used it, never plan to use it, and from now on will insist that people get rid of it. You've talked me into it!

    However, I feel I can generally rely on particular vendor extensions on those vendors' platforms and that they are not so free to change them: having defined them, they have an obligation to retain them. However, I agree that it would be better if such extensions were provided using different identifiers, and if they are in the standard headers, with leading underscores. strdup is a good example, although why it's not simply included in the standard is a mystery.

    And I was in fact conflating gcc and the glibc library. The "sane" comment was just that on the windows platform it would be "safer" for even glibc to ensure that fflush(stdin) is well-defined, possibly doing nothing, possibly generating a specific error, or possibly doing what the MS version does. This because windows programmers may be used to it not blowing up on them. But that's obviously not much of a reason, though it may be practical.
    The cost of software maintenance increases with the square of the programmer's creativity. - Robert D. Bliss

  10. #25
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    holy crud I did something stupid

    ok, I was reading the wrong file. No, when it hits that
    ZNU_0041233_02:00:12 <02:00:08> CMDLN 0E0*

    line, it does NOT read the next line at all. Not even in my test.

    (I had two files - test.txt and text.txt. I used the wrong one. hah)

    It looks to me like it's getting to that 0E0* and there should be a \r or \n there, but because it's converting it to viewable text for me I can't see what IS there... but neither \r nor \n are being picked up by the system, so i isn't resetting. As a result, it can't pick up the stuff at the beginning of the next line.

    It's showing 125 characters at the end of the line, which isn't possible unless i isn't resetting.
    Last edited by reillan; 01-30-2014 at 04:43 PM.

  11. #26
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    @reillan

    I'm sorry for the partial hijack; I am, but I'm still not going to take a long look at your code.

    If you want to remove all those magic values--replacing with character literals--and break the individual tokens into functions, I'll be happy to help in recompense.

    Otherwise, I can't deal with all with the code so can't help.

    Soma
    “Salem Was Wrong!” -- Pedant Necromancer
    “Four isn't random!” -- Gibbering Mouther

  12. #27
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    No worries, I got it working.
    I'm not sure what you mean by "magic values" or, for that matter, "character literals" as I'm still a complete noob I'm torn whether or not to take this particular piece of code further, as it's working

    Thanks everyone for all your help.

  13. #28
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Quote Originally Posted by reillan
    I'm not sure what you mean by "magic values" or, for that matter, "character literals"
    Magic values/numbers refers to the many places where you directly use a number instead of a named constant, and it is not obvious to the reader what does the number mean. You have used character literals in your code, e.g., '\n'
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  14. #29
    Registered User
    Join Date
    Jan 2014
    Posts
    15
    Ohh... I didn't know that was undesirable, although usually I provide better comments to what those numbers do

  15. #30
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Instead of comments, or at least in addition to comments, you should use an enum, or the const keyword, or #define to define named constants that you can use in place of these magic numbers.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 17
    Last Post: 01-29-2013, 07:58 PM
  2. Replies: 48
    Last Post: 02-12-2012, 02:33 PM
  3. Replies: 3
    Last Post: 10-21-2010, 12:39 PM
  4. Array fills with junk - help
    By Lucky Luke in forum C Programming
    Replies: 1
    Last Post: 12-13-2009, 05:13 PM
  5. Replies: 6
    Last Post: 06-30-2009, 09:37 AM