Thread: Writing a set of random integers to a file

  1. #1
    Registered User
    Join Date
    Feb 2003
    Posts
    28

    Writing a set of random integers to a file

    Hey guys, I have a stupid question. I am trying to make a program that writes a set of a random number of random integers to a file for a program that I am writing for a class assignment. The program I have to write for class takes a file of integers (one integer per line) and adds them up in two divide and conquer techniqes that involve shared memory, one program executing another, and forked processes...I'm getting ahead of myself, sorry. This is the code for my little program.

    Code:
    #include <stdio.h>
    #include <time.h>
    #include <stdlib.h>
    
    int main()
    {
      srand( ( unsigned ) time( NULL );
      FILE *fp;
      int i;
    
      printf( "Size of an integer on this machine: %d\n", sizeof( int ) );
    
      if( ( fp = fopen( "numbers.dat", "w" ) == NULL )
      {
        printf( "Can't open %s \n", "numbers.dat" );
        return( 1 );
      }
      else
        for( i = rand() % 200, i > 0, i-- )
          fprintf( fp, "%d\n", rand() );
    
      return( 0 );
    }
    Can you guys tell me what's wrong with it? It won't compile, citing errors with the srand statement, as well as *fp, among other things.
    Last edited by RazielX; 09-16-2004 at 12:55 PM.

  2. #2
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by RazielX
    It won't compile, citing errors with the srand statement
    Take them one at a time. If it says that it doesn't like the srand() statement, look at the srand() statement:

    Code:
      srand( ( unsigned ) time( NULL );
    (HINT: Count parentheses.)

    Dave

  3. #3
    Registered User
    Join Date
    Feb 2003
    Posts
    28
    Oops...sorry. I guess I was in too much of a hurry to see my mistakes. Thanks for your help and patience.

  4. #4
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >srand( ( unsigned ) time( NULL );
    >FILE *fp;
    >int i;
    Unless you're planning on compiling this as C99, C only allows declarations at the beginning of a block.

    >srand( ( unsigned ) time( NULL );
    Count your parens, you forgot to close the srand function call.

    >printf( "Size of an integer on this machine: %d\n", sizeof( int ) );
    sizeof gives you a size_t value, which is an unsigned quantity that could very well be larger than an int. In C89, it's best to use %lu and cast the result of the expression to unsigned long. That way you force the types to match while giving size_t the benefit of the doubt and using the largest standard unsigned integral type.

    >if( ( fp = fopen( "numbers.dat", "w" ) == NULL )
    Count the opening parens and compare with a count of the closing parens. Do they match? Try this instead:
    Code:
    if( ( fp = fopen( "numbers.dat", "w" ) ) == NULL )
    >printf( "Can't open %s \n", "numbers.dat" );
    Okay...I assume that "numbers.dat" is a placeholder for a string variable or macro? Otherwise there's no point in using a format modifier, you can just do this:
    Code:
    printf( "Can't open numbers.dat\n" );
    >return( 1 );
    A return value of 1 is not portable. The only three portable return values for main are 0, EXIT_SUCCESS and EXIT_FAILURE. The latter two are macros defined in stdlib.h.

    >for( i = rand() % 200, i > 0, i-- )
    You separate the parts of a for loop with a semicolon, not a comma.
    My best code is written with the delete key.

  5. #5
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Prelude
    A return value of 1 is not portable. The only three portable return values for main are 0, EXIT_SUCCESS and EXIT_FAILURE.
    I don't understand this. Does the standard say that main() can only return these values? I don't know what a "portable return value" would imply.

    I thought that main() could return any int value that it wanted to. Now, a program that invokes this program may treat the return value in whatever way it wants to (it may ignore returned values, for example), and that is beyond the power of the invoked program to control. What I mean to say is that use of return values is, obviously, not portable, but can't you return any int value you want?

    We have always been able to use returned values in any way we want. The convention has been (for values returned from main()):
    Return value of 0 ==> no error
    Return value of anything else ==> error

    Now, to indicate error severity, sometimes we use something like:

    Return value of 0 ==> no error
    Return value of 1 ==> data error
    Return value of 2 ==> file error (can't open file, for example).
    Return value of -1 ==> system error (used by execl to indicate that a fork failed, for example).

    These values would be published by the programmer as part of his Applications Programming Interface, and would be used by programs that invoked this program to do whatever error reporting (and/or error recovery attempts) that seem appropriate.

    Since lots of readers of this forum are Windows users, here's an example of how a batch file could use return values. (I'm using Windows XP, but the same kind of thing was done with earlier versions of Windows also.)

    Here's a program that can return any integer that you want it to:

    Code:
    /* z.c */
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
      int innum;
      int retval;
      char inbuf[BUFSIZ];
    
      printf("Enter an integer value to return to main: ");
      fgets(inbuf, BUFSIZ, stdin);
      if (sscanf(inbuf, "%d", &innum) == 1) {
        retval = innum;
      }
      else{
      else{
        printf("I was looking for an integer\n");
        retval = -99;
      }
      printf("I am returning with retval = %d\n", retval);
      return retval;
    }
    Now, save this as z.c, compile it (bcc32 z.c or cl z.c or whatever , and put the following batch file (call it go.bat, for example) in the same directory.


    @rem go.bat
    z.exe
    IF ERRORLEVEL 4 GOTO ER4
    IF ERRORLEVEL 3 GOTO ER3
    IF ERRORLEVEL 2 GOTO ER2
    IF ERRORLEVEL 1 GOTO ER1
    IF ERRORLEVEL 0 TOTO ER0
    @echo Errorlevel Less than 0
    goto fini
    :ER4
    @echo Errorlevel Greater than or equal to 4
    goto fini
    :ER3
    @echo Errorlevel = 3
    goto fini
    :ER2
    @echo Errorlevel = 2
    goto fini
    :ER1
    @echo Errorlevel = 1
    goto fini
    :ER0
    @echo Errorlevel = 0
    :fini
    @echo.
    @echo.
    Then enter

    go

    Give an integer value when prompted, and see how the batch file can categorize the return value.

    Regards,

    Dave

  6. #6
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    You describe return values as supported by your enviornment, and it is not unique in supporting return values other than EXIT_SUCCESS, EXIT_FAILURE, and 0. However, the standard only guarantees that those three will be legal.
    hello, internet!

  7. #7
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by moi
    You describe return values as supported by your enviornment, and it is not unique in supporting return values other than EXIT_SUCCESS, EXIT_FAILURE, and 0. However, the standard only guarantees that those three will be legal.
    Maybe my question got lost in my excess verbiage, code and .bat file.

    My question is, "What does one mean when one says, 'The only three portable return values for main are 0, EXIT_SUCCESS and EXIT_FAILURE'. "

    What's portable about them? What's less portable about other values? C programs return an int. Programs that invoke C programs may or may not be C programs. A C program, in general, has no way of knowing what kind of program invoked it. How can anyone say that certain return values are more portable than others?

    Are you saying that if my main() has a return -1; statement that the compiler can create code that returns any bloomin' value that it wants, since my return value is illegal? I will readily admit that I haven't read the C standard. I learned from K&R, and have supplemented my ad-hoc experiences by lurking on this board. I like to find out new things.

    Dave

    "I was born not knowing, and have only had a little time to change that, here and there."

    ---Richard Feynman

  8. #8
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    Well on a UNIX based system you can return any int number you like, but you are not guaranteed that number will return properly. If we use your example, you will get a return of 255, not -1.

  9. #9
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    Quote Originally Posted by Dave Evans
    Maybe my question got lost in my excess verbiage, code and .bat file.

    My question is, "What does one mean when one says, 'The only three portable return values for main are 0, EXIT_SUCCESS and EXIT_FAILURE'. "

    What's portable about them? What's less portable about other values? C programs return an int. Programs that invoke C programs may or may not be C programs. A C program, in general, has no way of knowing what kind of program invoked it. How can anyone say that certain return values are more portable than others?

    Are you saying that if my main() has a return -1; statement that the compiler can create code that returns any bloomin' value that it wants, since my return value is illegal? I will readily admit that I haven't read the C standard. I learned from K&R, and have supplemented my ad-hoc experiences by lurking on this board. I like to find out new things.

    Dave

    "I was born not knowing, and have only had a little time to change that, here and there."

    ---Richard Feynman
    The basic idea is that a program that adheres to the C standard can be compiled on any compiler that adheres to the C standard and will produce a program with predictable, defined behaviour; portability.
    hello, internet!

  10. #10
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by kermit
    Well on a UNIX based system you can return any int number you like, but you are not guaranteed that number will return properly. If we use your example, you will get a return of 255, not -1.

    So, what do you get when your main() returns EXIT_FAILURE (defined as 1). On my linux box I get 256, not 1. I don't see anything more portable about EXIT_FAILURE than any other value.

    Dave

    Test Code:
    Code:
    /* z.c                              */
    /* Compile this with gcc -o z z.c   */
    
    #include <stdio.h>
    int main()
    {
      int innum;
      int retval;
      char inbuf[BUFSIZ];
    
      printf("Enter an integer value to return to main: ");
      fgets(inbuf, BUFSIZ, stdin);
      if (sscanf(inbuf, "%d", &innum) == 1) {
        retval = innum;
      }
      else{
        printf("I was looking for an integer\n");
        retval = -99;
      }
      printf("I am returning with retval = %d\n", retval);
      return retval;
    }
    Code:
    /* y.c                             */
    /* compile this with gcc -o y y.c  */
    
    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
      int x;
      x = system("./z");
      printf ("x = %d, (0x%08x hex)\n", x,x);
      return 0;
    }
    now enter

    ./y

    and see what return values you get.

    Try it with execl, spawn, etc. Also try exit() instead of return().


    Regards,

    Dave
    Last edited by Dave Evans; 09-16-2004 at 05:34 PM.

  11. #11
    ... kermit's Avatar
    Join Date
    Jan 2003
    Posts
    1,534
    That is interesting - it returns 1 on my machine. What version of Linux / gcc are you running (not that it matters, but I am curious)

    Something else that I find interesting about the EXIT_SUCCESS, and EXIT_FAILURE macros is that they are traditionally 0 and 1 respectively on a UNIX based machine, but are not so on all implementations. I have wondered about how that would affect portability. No, I am not lashing out at the standard..

  12. #12
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by kermit
    That is interesting - it returns 1 on my machine. What version of Linux / gcc are you running (not that it matters, but I am curious)

    Something else that I find interesting about the EXIT_SUCCESS, and EXIT_FAILURE macros is that they are traditionally 0 and 1 respectively on a UNIX based machine, but are not so on all implementations. I have wondered about how that would affect portability. No, I am not lashing out at the standard..
    The machine that I just tested on has Fedora Core1, gcc version 3.3.2.

    I repeat that I am not familiar with the standard to the point where I can say it's non-compliant. The bottom line for me is that return values from main() aren't portable among the various Windows and Linux systems that I use.

    As far as traditional values, C programmers, of course, know that C functions typically return 0 for failure and non-zero for success, so we see things like
    Code:
    if (!isdigit()) {
      ...
    Whereas return from main() typically uses 0 for "OK", something else for "Not OK". I think that's why they put EXIT_SUCCESS and EXIT_FAILURE in stdlib.h. Still not portable, as far as the value that the invoking functions actually obtain through operating system calls.

    Regards,

    Dave

    "Everything should be made as simple as possible, but no simpler."
    --- Albert Einstein

    "Everything should be made as portable as possible, but no portablier."
    --- Dave Evans
    Last edited by Dave Evans; 09-16-2004 at 09:50 PM.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,661
    0 and EXIT_SUCCESS are synonymous, and mean that the program was successful
    EXIT_FAILURE means the program failed. The macros will always be the correct values for your OS, and 0 is always converted into whatever your OS uses for success.

    Take an odd OS like VAX-VMS, where (as far as the OS was concerned, 0 meant failure and 1 success). You would still use 0 or EXIT_SUCCESS for success and EXIT_FAILURE for failure.

    If you do an explicit
    return 1;
    then it may mean different things in different environments.

    > x = system("./z");
    This too is non-portable. system() typically has to mangle its own return code with the return code of the process it executed.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  14. #14
    Registered User
    Join Date
    Mar 2004
    Posts
    536
    Quote Originally Posted by Salem

    > x = system("./z");
    This too is non-portable. system() typically has to mangle its own return code with the return code of the process it executed.
    Of course it's non-portable. I was giving an example that shows (on my Linux box) the value that the operating system gives to calling programs is not what I might have guessed from the main() returned value. In other words use of the returned value (except for the value of 0) is non-portable, since my Windows compilers gave values that I actually returned.

    On my Linux box:

    Return 1 gave the result in hex as 0x00000100. This value, when printed as an int is 256.

    Return -1 gave the result in hex 0x0000ff00. This value, when printed as an int is 65280.

    On my Windows box:

    Return 1 gave the result in hex 0x00000001. This value, wnen printed as an int is 1

    Return -1 gave the result in hex 0xffffffff. This value, when printed as an int is -1

    My whole point is that I don't think return EXIT_FAILURE is any more portable than return 1 or return -1 or return anything else. (Except, I'm guessing, return 0 would always return a value of 0.)

    My remaining question is: Does the C standard say that there are only three legal values for return, namely 0, EXIT_FAILURE and EXIT_SUCCESS? If I return some other value, is the behavior undefined? (In which case the compiler can do any thing it wants.)

    Regards,

    Dave

  15. #15
    Registered User moi's Avatar
    Join Date
    Jul 2002
    Posts
    946
    regardless of where you compile, EXIT_FAILURE will return a value that is understood by the caller that the program has failed. Who knows what "1" or "-1" will do on a different system?
    hello, internet!

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Formatting a text file...
    By dagorsul in forum C Programming
    Replies: 12
    Last Post: 05-02-2008, 03:53 AM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. problem with open gl engine.
    By gell10 in forum Game Programming
    Replies: 1
    Last Post: 08-21-2003, 04:10 AM
  4. archive format
    By Nor in forum A Brief History of Cprogramming.com
    Replies: 0
    Last Post: 08-05-2003, 07:01 PM
  5. Need a suggestion on a school project..
    By Screwz Luse in forum C Programming
    Replies: 5
    Last Post: 11-27-2001, 02:58 AM