How to make the console go away.

/* Hello people.
I'm here for some advise. About ten years ago a had a stroke and I am still
affected by it. Before that I was a network analyst for a local company.
Never much a C person, I did a couple of things with it. Anyway, I've
lost my notes and havn't any friends that know the language. I was wondering
if you could point me the right way on this.
The following is some code that when run puts out the prime numbers, up to
100. Change the types and it will go for 4.2 billion. That's OK.
How do I get it to stop showing changes? I mean I want it to put the
numbers in a text file, and then I'll have a look at the numbers afterwords.
Someone was trying to do something to the numbers like: dir > file,
but I don't see that working.
I have at least two problems. One, how to save the changes locally, and
two how to grab the numbers every thousand or so, and let it continue.
Thank you for any help.
Jim Devaney
*/

#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <sys\types.h>

FILE *test1, *test2;

long l;
long n = 2;
time_t s, t;

int main (void) {
if ((test1 = fopen("test1", "rt")) == NULL) {
fprintf(stderr, "Cannot open input file.\n");
return 1;
}
if ((test2 = fopen("test2", "wt")) == NULL) {
fprintf(stderr, "Cannot open output file.\n");
return 1;
}
/* seek to the beginning of the file */
fseek(test1, SEEK_SET, 0);
fseek(test1, SEEK_SET, 0);
while (!feof(test1))
fputc(fgetc(test1), test2);
fclose(test1);
fclose(test2);
while (++n <= 100L ) {
l = 1;
while ( ++l < n ) {
if (n % l == 0 )
break;
}
if ( l == n )
printf("%\ld ", l);
}
time(&t);
printf("\nToday's date and time: %s\n", ctime(&s));
printf("Today's date and time: %s\n", ctime(&t));
getch();
return 0;
}
I'm sorry to hear about the stroke. Best regards there.
For your program: dir > file looks more like a dos-based command from the command line than part of C/C++

0) to 'save' the changes, once you have the file open, you need to flush the buffer, or 'stream' that represents the file. for C its fflush(), and for an fstream, it's member function fstream::flush(). I think it will automatically flush when you close the file in either case, don't hold me to that though.

1) just a suggestion, but C++ streams are easier to use for IO than their original C counterparts, and there is some great info on them in our reference section - http://www.cplusplus.com/reference/iostream/ Then you could just create a file stream to read/write to your file.

2) it doesn't quite make sense why it looks like you are trying to read from one file and write to another. if you are just saving into one file, there isn't a need to have two, unless there is actual info in the second one that you need.

3) what do you mean by
grab the numbers every thousand or so,
... do you mean every thousand prime numbers, or a prime number roughly a thousand integers apart? either way, it's likely that an 'if' statement in the loop that is calculating the numbers will do the trick. you'll probably need a counting variable, then just test for a condition and write the number to the screen and/or file if the condition is met, then the loop will continue on it's own.

good luck! :)
Hi, Thanks for getting back to me. This code should show you what
I am trying to do. Yes, I think fflush (stream) is what I was trying to do.
I tried it a few weeks ago, but I missed it. It was there all along.
I'm using Borland C++ ver. 4.52, it's pretty old, at least 15 years.
Now every time I run the code if I put in it n = 70000 (showed primes
that are in it) then you see it loses the first answers (primes under
about 15000L) but keeps the newest ones. A file uses up about 32,000 of space.
I don't see "stream = fopen("DUMMY.FIL", "w");" getting me anywhere.
But there's a little button in the top left application window which
does what I talked about.
The notes I have are on screen or in Borland books.
The duphandle, how could I get that to help, is that possible?
Something that stops when I gets so full, allows me to save that
much space, keep that file, and go on to do another, and so on.
I still think there is a better way for when I save 1 million, or 10
million, etc.
Thanks again.
Jim
Mmm, if you are using Windows, I would suggest upgrading to something like VC++, otherwise you can go grab the Bloodshed group, both are good IMHO.

Anyway, do you mean that they are going off the screen or are they just not being output? And also, about the file problem, I don't really think there is a way to check the file size...you could try putting it all into a temporary string, then checking it's length, then writing it all to a file at the end.

Also, like Mal said, I would suggest going up to C++, since those streams/strings/file I/O is much easier then C.
Hello,
Here is the file now. It's borrowed from Borland C++ 4.52.
I am using XP. I have used Bloodshed.
It's only for prime numbers up to n = 100. I want to see it saved
though in a file if I go up to 1,000,000 or higher. You can watch
the numbers go by OK. I have a problem with putting the prime
numbers on disk. That "printf("%ld ", l);" doesn't do that. Check it out.
The screen lets me view the results, but only the latest
30.000 bytes or so. I want to get all of the numbers saved
on file. It sounds simple really.
Isn't there a way that I could change "printf("%ld ", l);"
to save it as binary? Or maybe the fflush isn't doing anything
here. That DUMMY.FIL doesn't do anything. What about duphandle?
I hope you can help.
Thank you.
Jim

/*******************************************************/
/* Copyright (c) 1990, 1992, Borland International */
#include <stdio.h>
#include <conio.h>
#include <time.h>
#include <io.h>
long prime(long n)
{
long l;
if (n % 2 == 0)
return (n==2);
if (n % 3 == 0)
return (n==3);
if (n % 5 == 0)
return (n==5);
for (l=7; l*l <= n; l+=2)
if (n % l == 0)
return 0;
return 1;
}
void flush(FILE *stream);
FILE *stream;
void main(void)
{
long int l, n;
time_t s, t;
time(&s);
stream = fopen("DUMMY.FIL", "w");
n = 100L;
/**************************************************/
for (l=2; l<=n; l++)
if (prime(l))
printf("%ld ", l);
/**************************************************/
time(&t);
printf("\nToday's date and time: %s\n", ctime(&s));
printf("Today's date and time: %s\n", ctime(&t));
flush(stream);
getch();
}
void flush(FILE *stream)
{
int duphandle;
/* flush the stream's internal buffer */
fflush(stream);
/* make a duplicate file handle */
duphandle = dup(fileno(stream));
/* close the duplicate handle to flush the DOS buffer */
close(duphandle);
}
Unless you are developing code for Borland, get rid of that copyright at the top of the file. You own it. Not Borland. (It is very dishonest for them to stick that in there.)


Please use [code] tags. If your code looks like it does here when you are editing it, you will never figure out what is wrong. The way you physically organize your code has a causal effect on the quality of the code and your understanding of it.

In the following example, I've simply added some proper whitespace to your prime() function (which is otherwise very nice, if simple):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
long prime(long n)
{
  long l;

  if (n % 2 == 0) return (n==2);
  if (n % 3 == 0) return (n==3);
  if (n % 5 == 0) return (n==5);

  for (l=7; l*l <= n; l+=2)
    if (n % l == 0)
      return 0;

  return 1;
}
More on prime() later...

By the way, use good variable names. By that I mean that your variable names should tell you something about the variable's meaning. I will spare the lecture here, but every programmer should be made to read and understand the document:
Ottinger's Rules For Variable and Class Naming http://www.objectmentor.com/resources/articles/naming.htm
In particular, never use 'l' and 'O' for variable names. (That's a lowercase 'L' and an uppercase 'o'.)

A good throw-away name here might be i or x, since these are common counter names. A better name would be something like divisor or factor.

-------------------------------------------------------------------------------------------------

Ok, enough of that stuff. On to your actual question. You wish to save the list of numbers to file. To do that, use fprintf() instead of printf().
1
2
3
  for (n=2; n<=max_n; n++)
    if (prime(n))
      fprintf(primes_file, "%ld ", n);
(Notice how I renamed some stuff.)

-------------------------------------------------------------------------------------------------

That flush() function is completely unnecessary. Don't second-guess the standard library or the operating system. If you really want unbuffered output, use setbuf( primes_file, NULL );. That is really a bad idea though. Leave the buffering to the default and you'll be fine. I recommend that you output a newline instead of a space after every prime number, and set your buffering to line-buffered:
1
2
3
  setvbuf(primes_file, NULL, _IOLBF, 1024);
  ...
      fprintf(primes_file, "%ld\n", n);
Doing so will greatly reduce the likelihood of a corrupt output (should your program be unceremoneously killed, or crash).

-------------------------------------------------------------------------------------------------

You can save your numbers as binary if you like, but it introduces the effort of handling binary file I/O --which is not as simple as text file I/O, particularly when handling the minimum required size for each output datum. If you are concerned about space, then it is probably a good idea. Otherwise it isn't worth the effort.

-------------------------------------------------------------------------------------------------

If you really plan to print a lot of prime numbers, you will need to improve your prime number routine. I suggest you check-out the Strong Compositeness Test to determine potential primality (it is the simplest method, using Fermat's Little Theorem), and only if the test indicates that you have a potential prime should you spend additional time verifying it is not a Carmichael number (which is not a prime). Prime testing gets slow, fast.

There are more sophisticated methods, such as the Rabin-Miller test, which is also probablistic, but is probably the fastest you will find. It is also relatively easy to turn into a deterministic test. For more on primality testing, see the Wikipedia
http://en.wikipedia.org/wiki/Primality_test

-------------------------------------------------------------------------------------------------

You may also want to find yourself a bignum library. The following is a good one:
GNU MP Bignum Library http://gmplib.org/
It is LGPL so you can use it without being obligated to release your source, should you desire to distribute only binaries of your application. (If you don't plan to distribute anything at all, then licensing is a moot point.)

-------------------------------------------------------------------------------------------------

One thing I think you wondered is how to pick-up at the last-output prime number and continue from there. I would make a little function to do it. Something like:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
/*
 * prepare_to_write()
 *
 *   function
 *     Positions the write pointer in the file such that it is ready to
 *     receive more prime numbers.
 *
 *   arguments
 *     f  -- The file
 *
 *   returns
 *     A bignum: The last complete prime number listed in the file.
 *
 *     If there aren't any prime numbers in the file (for example, if the
 *     file was just created prior to calling this function), returns zero.
 */
mpz_t prepare_to_write( FILE* f )
  {
  On error: return 0
  1. seek to the end of the file
  2. move backwards until you come to the beginning of a number
  3. remember the file position
  4. repeat step 2
  5. read the last two numbers from the file
  6. if (mpz_cmp( penultimate_number, last_number ) > 0)
       result <-- penultimate_number
       seek to file position remembered in step 3
     else
       result <-- last_number
       seek to end of file
  7. return the result
  }

Whew. Hope this helps.
Thank you Sir, that was great.
Yes, that statement "fprintf(primes_file, "%ld ", n);" did the trick. It will take me a while to get into all of what you said.
I'm sorry to do this but I do have a couple of questions. Remember:

long prime(long n)
{
long l;

if (n % 2 == 0) return (n==2);
if (n % 3 == 0) return (n==3);
if (n % 5 == 0) return (n==5);
/*****************************/
for (l=7; l*l <= n; l+=2)
if (n % l == 0)
return 0;
/*****************************/
return 1;
}

Well, I don't get that bit inside the qoutes. Can you say it in words:

for (l=7; l*l <= n; l+=2)
if (n % l == 0)
return 0;

I think I know what it is doing, but what is it doing?

And also, I did to 10000000L OK, but now the present machine is doing fine until 4000, then for 5000+ it comes back ′″‵‷ㄱㄠ″㜱ㄠ‹㌲㈠‹ㄳ㌠‷ㄴ㐠″㜴 etc.".
That is with BC 4.52 as well as Bloodshed. Do you know why this is?
Thank you again.
Jim
1
2
3
for (l=7; l*l <= n; l+=2)
   if (n % l == 0)
      return 0;


Set integer l to 7
While l*l is less then or equal to n, if n modulus l is 0, return 0. Every loop, increment l by 2.

Basically it is working up to the square root of n (odd #s from 7 up) and if l is a multiple of n (using modulus checking) it will return 0.
Hmm, I thought you wrote that routine.

Basically it is checking every odd number from 7 to the integer square root of n (inclusive) to see if it evenly divides n. If any such number exists, then n must be composite. [Sorry FD, I started answering before you did... I just took an hour to eat dinner before finishing... :-]

I don't know where you got that function, but it could be improved quite a bit.

Here is how I would rewrite it (I have not improved the algorithm --only its readability and the data types):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
/*
 * I like boolean values to be labeled as such.
 *
 * It is not strictly necessary here, but my personal
 * pleasure is "the more obvious, the better".
 *
 * I don't know whether you are using C99 or not;
 * So this will work in either case.
 */
#if (__STDC_VERSION__ >= 199901L)
  #include <stdbool.h>
#else
  typedef enum { false = 0, true = 1 } bool;
#endif

/*
 * This is the same function as above, with
 * a corrected (and explicit) return type.
 */
bool isprime( unsigned long n )
  {
  unsigned long divisor;

  /* Eliminate the easy stuff:
   * Is n a multiple of 2, 3, or 5 ?
   * Yes --> n is composite if n is not 2, 3, or 5.
   */
  if ((n % 2) == 0) return (n == 2);
  if ((n % 3) == 0) return (n == 3);
  if ((n % 5) == 0) return (n == 5);

  /* All right, now for the pedantic way.
   * Starting with 7 (the next prime after 5), check to see if
   * the divisor evenly divides n. We stop checking at the
   * square-root of n, since we already implicitly tested divisors
   * greater than that.
   */
  for (divisor = 7;  (divisor * divisor) <= n;  divisor += 2)
    if ((n % divisor) == 0)
      return false;

  return true;
  }
The loop is actually just a little tricky at fenceposts. For example, consider why n=7 returns true and n=8 returns false. Sometimes you will also see people adding one to the square-root... which is not necessary. The floor of the square-root is sufficient.

Why have I taken this time? To model some code for you. You will likely differ in some details, but as long as you use proper whitespace and make things readable you will have an easier time of understanding things (or of realizing that you need to stop and figure things out before you continue coding).

Calculating prime numbers takes a little bit of math. You will have to work on that.


As for the errors on 4000-5000+ numbers, I don't know. A long is supposed to be 32-bits --but even if it is only 16-bits with such an ancient compiler as BC 4.52, you should still make it up to 32767 (the maximum 15-bit value) before error.

In any case, make sure to use a modern compiler. All of the following are 100% free to use.

Borland http://www.turboexplorer.com/cpp
MinGW (GCC) http://www.mingw.org/
Microsoft http://www.microsoft.com/express/vc/

It is entirely possible (and legal) to install more than one Turbo Explorer identity. See http://andy.jgknet.de/blogx/archives/31-TurboMerger-Build-your-Turbo-Explorer-Studio.html and http://www.delphipraxis.net/topic91774,0,asc,90.html

For MinGW, follow the HOWTO Install directions. Make sure to get at least version 3.4.5. I use the alpha 4.3.0 without any problems. And the packages listed on the MinGW page.
http://www.mingw.org/wiki/MinGW
http://www.delphipraxis.net/topic91774,0,asc,90.html

I haven't been able to get VC++Express to like my computer...

Good luck!
Topic archived. No new replies allowed.