Using while loop to print Ascii Table with 10 characters per line - c

I'm at a very basic level of C programming: I can print out an ASCII table.
The problem is printing out 10 of the ASCII characters per line, e.g.:
characters 1-10 (newline)
characters 10-20...
and so on up to 255
int main() {
int i;
while (i <= 255) {
printf("%c", i);
i = i + 1;
}
exit(0);
}

the following proposed code
cleanly compiles
performs the desired functionality
also labels each line
makes use of isprint() from ctype.h to determine if outputs current character or outputs a '.'
And now, the proposed code:
#include <stdio.h>
#include <ctype.h>
int main( void )
{
for( int i = 0; i<256; i++ )
{
if( !( i%10 ) )
{
printf( "\n%3d thru %3d ", i, i+9 );
}
if( isprint( i ) )
{
putchar( i );
}
else
{
putchar( '.' );
}
}
}
The output from the above code is:
000 thru 009 ..........
010 thru 019 ..........
020 thru 029 ..........
030 thru 039 .. !"#$%&'
040 thru 049 ()*+,-./01
050 thru 059 23456789:;
060 thru 069 <=>?#ABCDE
070 thru 079 FGHIJKLMNO
080 thru 089 PQRSTUVWXY
090 thru 099 Z[\]^_`abc
100 thru 109 defghijklm
110 thru 119 nopqrstuvw
120 thru 129 xyz{|}~...
130 thru 139 ..........
140 thru 149 ..........
150 thru 159 ..........
160 thru 169 ..........
170 thru 179 ..........
180 thru 189 ..........
190 thru 199 ..........
200 thru 209 ..........
210 thru 219 ..........
220 thru 229 ..........
230 thru 239 ..........
240 thru 249 ..........
250 thru 259 ......
You may want to modify the proposed code, such that:
it does not output an initial blank line
it stops the last label at 255 rather than 259
does not print leading '0's
does not print the labels

Amending the previous answer it is not good to print non ascii chars as the console (terminal) behaviour can be weird. Print something else instead - for example dot,
#define MINCHAR 32
#define MAXCHAR 127
int main() {
int i = 0;
while(i<=255) {
putchar((i >= MINCHAR && i <= MAXCHAR) ? i : '.');
if(!(i % 10) && i) putchar('\n');
i = i + 1;
}
putchar('\n');
}

So if you want afte every 10 character a new line, this code should work.
int main() {
int i = 0;
while(i<=255) {
printf("%c", i);
if(i % 10 == 0)
printf("\n");
i = i + 1;
}
exit(0);
}

Related

Problem in the change of line when reading files in C

I'm reading a .pgm file (like the lines below) with "fgetc(file)". When getting only the numbers with a loop in which I avoid the spaces in between (it seems it treats each space, no matter how big it is, as a single character), it joints the last number of a line and the first one from the following line (ex, 146 last number and 105 first number, it gives 146105).
113 116 97 124 146
105 100 112 98 88
100 117 98 87 126
131 101 87 137 161
When simply printing the contents of the file, I get a lot of spaces on the change of line in the console, like this:
113 116 97 124 146
105
When printing the contents, each character on a single line, i get this other output:
9
7
//one line
1
2
4
//one line
1
4
6
//change of linne in the file, two lines here!!!!
1
0
5
//one line
1
0
0
Any ideas about how I should treat this part of the file?
Here is my code:
int get_number(int current[4], int n)
{
int final_number, index = 0, max = n;
while (index < max)
{
final_number += current[index] * pow(10, (n-1));
index++;
n --;
}
return final_number;
}
file = fopen("baboon.pgm", "r");
int info = fgetc(file), n;
while (info != EOF)
{
n = 0;
while (info != ' ' || info != ' ' || info != ' ' || info != ' ')
{
printf("%c", info);
int current_number[4];
n++;
}
if (current_number[0] != 0)
{
printf("%d ", get_number(current_number, n));
}
info = fgetc(file);
}
I think that with this piece of the code you can get an idea. If need more, say it. I also leave you here a link to download the image file if you want: https://drive.google.com/file/d/1ZYIU6fcUOnhRND2zph5MUr8545P6U8bX/view?usp=sharing

Finding prime numbers using C does not work

I am currently learning C and trying to solve a problem. I need to find all the prime numbers from 2 to 100, using arrays and loops.
I already know of a solution to this problem however I am having trouble finding the error in my code. This is my first time using StackOverflow so hopefully I commented everything properly :)
#include <stdio.h>
#include <stdlib.h>
int main(){
int prime_numbers[50] = {2,3}; //initializes the array which will be printed at the end
int counter = 1; //initializes the index of the last prime element in array
int checker = 0; //initializes a checker used to determine if the number is prime
for(int i = 5; i <= 100; i++) { //goes through numbers 5 to 100 as the first two primes are hard coded
for(int j = 0; j <= counter; j++){ //goes through array untill it reaches last prime using the before initialized counter
if(i % prime_numbers[j] != 0) { //check to see if a number that is being checked is not divisible by j'th element in array
checker++; //if so, checker is incremented
}
if(checker == counter + 1) { //check to see if number was not divisible by any prime in our array
checker = 0; //if so checker is reset to 0 for the next iteration
++counter; //counter is incremented as there is one more prime in our array
prime_numbers[counter] = i; //add inside array the found prime number
break; //break should not be necessary, however for some reason, it yields a different result when I don't put it in
} //most likely the error in the code. Need to find out why loop does not stop after second if is done
}
}
for(int g = 0; g <= 50; g++) { //prints out all the prime numbers in array
if(prime_numbers[g] != 0) {
printf("%d ", prime_numbers[g]);
}
}
return 0;
}
I expect the program to print all the prime numbers from 0 to 100 with spaces in between.
The program also finds numbers that are not prime. Its logic is a rather strange inversion. The candidate needs to be divisible by only one prime in the array. The reporting also breaks the array bounds.
The corrected code:
#include <stdio.h>
int main(void) { // correct function signature
int prime_numbers[50] = {2,3};
int counter = 1;
int checker; // initialise within each loop
for(int i = 5; i <= 100; i++){
checker = 0; // inintialise here
for(int j = 0; j <= counter; j++) {
if(i % prime_numbers[j] == 0) { // opposite test to yours
checker++; // flag a non-prime
break;
}
}
if(checker == 0) { // moved outside the loop
++counter;
prime_numbers[counter] = i;
}
}
for(int g = 0; g < 50; g++) { // corrected the bounds error
if(prime_numbers[g] != 0){
printf("%d ", prime_numbers[g]);
}
}
printf("\n"); // flush the output buffer
return 0;
}
Program output:
2 3 5 7 11 13 17 19 23 29 31 37 41 43 47 53 59 61 67 71 73 79 83 89 97
The reporting loop relies on the array being initialised to 0s and a better way would be
for(int j = 0; j <= counter; j++) {
printf("%d ", prime_numbers[j]);
}
printf("\n");
The following code works well.
int main()
{
int k=1,temp,j;
const int N_prime = 10000; // number of primes to be generated
int primes[N_prime]; // array to save primes
primes[0] = 2;
primes[1] = 3;
temp = 5;
while (k!=N_prime-1){ // generating only N_prime prime numbers
for (j = 0; j <= k && primes[j] * primes[j] <= temp; j++){
if (temp%primes[j] == 0){ // if temp%primes[j] == 0 then temp is divisible by
temp += 2; // a prime and is not a prime itself, therefore
break; // immediately break
}
else if (primes[j+1] * primes[j+1]>temp){ // if no such primes found, temp is prime,
primes[k + 1] = temp; // save it and increase the value for
k++; // next check
temp += 2;
}
}
}
for (int ind = 0; ind < N_prime; ind++) printf("%d\n",primes[ind]);
getch();
return 0;
}
with the output:
2
3
5
7
11
13
17
19
23
29
31
37
41
43
47
53
59
61
67
71
73
79
83
89
97
101
103
107
109
113
127
131
137
139
149
151
157
163
167
173
179
181
191
193
197
199
211
223
227
229
233
239
241
251
257
263
269
271
277
281
283
293
307
311
313
317
331
337
347
349
353
359
367
373
379
383
389
397
401
409
419
421
431
433
439
443
449
457
461
463
467
479
487
491
499
503
509
521
523
541
As I noticed, your code generates all the odd numbers up to 100.

Generate Unique Values

I want to create a C program to generate numbers from 0 to 999999, keeping in mind that the number generated should not have any digits that are repetitive within it. For example, "123" is an acceptable value but not "121" as the '1' is repeated. I have sourced other program codes that check if an integer has repeated digits:
Check if integer has repeating digits. No string methods or arrays
What is the fastest way to check for duplicate digits of a number?
However these do not really solve my problem and they are very inefficient solutions if I were to perform the check for 1,000,000 different values. Moreover, the solution provided is for int and not char[] and char *, which I use in my program. Below is my code thus far. As you can see I have no problems handling values of up to "012", however the possibilities for values with 3 digits and above are too many to list and too inefficient to code. Would appreciate some help.
int i, j;
char genNext[7] = "0";
printf("%s\n", genNext);
// loop through to return next pass in sequence
while (1) {
for (i = 0; i < sizeof(genNext) / sizeof(char); i++) {
if (genNext[i] == '9') {
char * thisPass = strndup(genNext, sizeof(genNext));
int countDigit = (int) strlen(thisPass);
switch (countDigit) {
case 1:
genNext = "01";
break;
case 2:
if (strcmp(genNext, "98")) {
if (i == 0) {
genNext[1] += 1;
} else {
genNext[0] += 1;
genNext[1] == '0';
}
} else {
genNext = "012";
}
break;
case 3:
if (strcmp(genNext, "987")) {
// code to handle all cases
} else {
genNext = "0123";
}
break;
case 4:
case 5:
case 6:
// insert code here
}
break;
} else if (genNext[i] == '\0') {
break;
} else if (genNext[i+1] == '\0') {
genNext[i] += 1;
for (j = 0; j < i; j++) {
if (genNext[i] == genNext[j]) {
genNext[i] += 1;
}
}
} else {
continue;
}
}
printf("%s\n", genNext);
if (strcmp(genNext, "987654") == 0) {
break;
}
}
The main problem that I am facing is the cases when '9' is part of the value that is being tested. For example, the next value in the sequence after "897" is "901" and after "067895" comes "067912" based on the rules of non-repetitiveness as well as sequential returning of the result.
A desired output would be as follows:
0
1
2
3
...
8
9
01
02
03
...
09
10
12
13
...
97
98
012
013
014
...
098
102
103
...
985
986
987
0123
0124
...
etc etc.
Any assistance is appreciated, and if any part of my question was unclear, feel free to clarify. Thanks!
EDIT: How do I generate all permutations of a list of numbers? does not solve my question as the increment from "120398" to "120435" as the next "legal" value in the sequence.
EDIT 2: Updated question to include desired output
There are three variant algorithms below. Adapt variant 3 to suit your requirements.
Variant 1
This is one way to do it. It implements a minor variant of the initialize a table of 10 digit counts to 0; scan the digits, increment the count for each digit encountered, then check whether any of the digit counts is more than 1 algorithm I suggested in a comment. The test function returns as soon as a duplicate digit is spotted.
#include <stdio.h>
#include <stdbool.h>
enum { MAX_ITERATION = 1000000 };
static bool duplicate_digits_1(int value)
{
char buffer[12];
snprintf(buffer, sizeof(buffer), "%d", value);
char digits[10] = { 0 };
char *ptr = buffer;
char c;
while ((c = *ptr++) != '\0')
{
if (++digits[c - '0'] > 1)
return true;
}
return false;
}
int main(void)
{
int count = 0;
for (int i = 0; i < MAX_ITERATION; i++)
{
if (!duplicate_digits_1(i))
{
count += printf(" %d", i);
if (count > 72)
{
putchar('\n');
count = 0;
}
}
}
putchar('\n');
return 0;
}
When run, it produces 168,571 values between 0 and 1,000,000, starting:
0 1 2 3 4 5 6 7 8 9 10 12 13 14 15 16 17 18 19 20 21 23 24 25 26 27 28 29
30 31 32 34 35 36 37 38 39 40 41 42 43 45 46 47 48 49 50 51 52 53 54 56 57
58 59 60 61 62 63 64 65 67 68 69 70 71 72 73 74 75 76 78 79 80 81 82 83 84
85 86 87 89 90 91 92 93 94 95 96 97 98 102 103 104 105 106 107 108 109 120
123 124 125 126 127 128 129 130 132 134 135 136 137 138 139 140 142 143 145
146 147 148 149 150 152 153 154 156 157 158 159 160 162 163 164 165 167 168
169 170 172 173 174 175 176 178 179 180 182 183 184 185 186 187 189 190 192
193 194 195 196 197 198 201 203 204 205 206 207 208 209 210 213 214 215 216
217 218 219 230 231 234 235 236 237 238 239 240 241 243 245 246 247 248 249
250 251 253 254 256 257 258 259 260 261 263 264 265 267 268 269 270 271 273
…
987340 987341 987342 987345 987346 987350 987351 987352 987354 987356 987360
987361 987362 987364 987365 987401 987402 987403 987405 987406 987410 987412
987413 987415 987416 987420 987421 987423 987425 987426 987430 987431 987432
987435 987436 987450 987451 987452 987453 987456 987460 987461 987462 987463
987465 987501 987502 987503 987504 987506 987510 987512 987513 987514 987516
987520 987521 987523 987524 987526 987530 987531 987532 987534 987536 987540
987541 987542 987543 987546 987560 987561 987562 987563 987564 987601 987602
987603 987604 987605 987610 987612 987613 987614 987615 987620 987621 987623
987624 987625 987630 987631 987632 987634 987635 987640 987641 987642 987643
987645 987650 987651 987652 987653 987654
Before you decide this is 'not efficient', measure it. Are you really exercising it often enough that the performance is a real problem?
Variant 2
Creating the alternative version I suggested in the comments: use strchr() iteratively, checking whether the first digit appears in the tail, and if not whether the second digit appears in the tail, and so on is very easy to implement given the framework of the first answer:
static bool duplicate_digits_2(int value)
{
char buffer[12];
snprintf(buffer, sizeof(buffer), "%d", value);
char *ptr = buffer;
char c;
while ((c = *ptr++) != '\0')
{
if (strchr(ptr, c) != NULL)
return true;
}
return false;
}
When the times are compared I got these results (ng41 uses duplicate_digits_1() and ng43 uses duplicate_digits_2().
$ time ng41 > /dev/null
real 0m0.175s
user 0m0.169s
sys 0m0.002s
$ time ng43 > /dev/null
real 0m0.201s
user 0m0.193s
sys 0m0.003s
$
Repeated timings generally showed similar results, but sometimes I got ng43 running faster than ng41 — the timing on just one set of one million numbers isn't clear cut (so YMMV — your mileage may vary!).
Variant 3
You could also use this technique, which is analogous to 'count digits' but without the conversion to string first (so it should be quicker).
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
enum { MAX_ITERATION = 1000000 };
static bool duplicate_digits_3(int value)
{
char digits[10] = { 0 };
while (value > 0)
{
if (++digits[value % 10] > 1)
return true;
value /= 10;
}
return false;
}
int main(void)
{
int count = 0;
const char *pad = "";
for (int i = 0; i < MAX_ITERATION; i++)
{
if (!duplicate_digits_3(i))
{
count += printf("%s%d", pad, i);
pad = " ";
if (count > 72)
{
putchar('\n');
count = 0;
pad = "";
}
}
}
putchar('\n');
return 0;
}
Because it avoids conversions to strings, it is much faster. The slowest timing I got from a series of 3 runs was:
real 0m0.063s
user 0m0.060s
sys 0m0.001s
which is roughly three times as fast as either of the other two.
Extra timing
I also changed the value of MAX_ITERATION to 10,000,000 and ran timing. There are many more rejected outputs, of course.
$ time ng41 >/dev/null
real 0m1.721s
user 0m1.707s
sys 0m0.006s
$ time ng43 >/dev/null
real 0m1.958s
user 0m1.942s
sys 0m0.008s
$ time ng47 >/dev/null
real 0m0.463s
user 0m0.454s
sys 0m0.004s
$ ng41 | wc
69237 712891 5495951
$ ng43 | wc
69237 712891 5495951
$ ng47 | wc
69237 712891 5495951
$ cmp <(ng41) <(ng43)
$ cmp <(ng41) <(ng47)
$ cmp <(ng43) <(ng47)
$
These timings were more stable; variant 1 (ng41) was always quicker than variant 2 (ng43), but variant 3 (ng47) beats both by a significant margin.
JFTR: testing was done on macOS Sierra 10.12.1 with GCC 6.2.0 on an old 17" MacBook Pro — Early 2011, 2.3GHz Intel Core i7 with 16 GB 1333 MHz DDR3 RAM — not that memory is an issue with this code. The program numbers are consecutive 2-digit primes, in case you're wondering.
Leading zeros too
This code generates the sequence of numbers you want (though it is only configured to run up to 100,000 — the change for 1,000,000 is trivial). It's fun in a masochistic sort of way.
#include <assert.h>
#include <stdbool.h>
#include <stdio.h>
#include <string.h>
enum { MAX_ITERATIONS = 100000 };
/* lz = 1 or 0 - consider that the number has a leading zero or not */
static bool has_duplicate_digits(int value, int lz)
{
assert(value >= 0 && value < MAX_ITERATIONS + 1);
assert(lz == 0 || lz == 1);
char digits[10] = { [0] = lz };
while (value > 0)
{
if (++digits[value % 10] > 1)
return true;
value /= 10;
}
return false;
}
int main(void)
{
int lz = 0;
int p10 = 1;
int log_p10 = 0; /* log10(0) is -infinity - but 0 works better */
int linelen = 0;
const char *pad = "";
/* The + 1 allows the cycle to reset for the leading zero pass */
for (int i = 0; i < MAX_ITERATIONS + 1; i++)
{
if (i >= 10 * p10 && lz == 0)
{
/* Passed through range p10 .. (10*p10-1) once without leading zeros */
/* Repeat, adding leading zeros this time */
lz = 1;
i = p10;
}
else if (i >= 10 * p10)
{
/* Passed through range p10 .. (10*p10-1) without and with leading zeros */
/* Continue through next range, without leading zeros to start with */
p10 *= 10;
log_p10++;
lz = 0;
}
if (!has_duplicate_digits(i, lz))
{
/* Adds a leading zero if lz == 1; otherwise, it doesn't */
linelen += printf("%s%.*d", pad, log_p10 + lz + 1, i);
pad = " ";
if (linelen > 72)
{
putchar('\n');
pad = "";
linelen = 0;
}
}
}
putchar('\n');
return 0;
}
Sample output (to 100,000):
0 1 2 3 4 5 6 7 8 9 01 02 03 04 05 06 07 08 09 10 12 13 14 15 16 17 18 19
20 21 23 24 25 26 27 28 29 30 31 32 34 35 36 37 38 39 40 41 42 43 45 46 47
48 49 50 51 52 53 54 56 57 58 59 60 61 62 63 64 65 67 68 69 70 71 72 73 74
75 76 78 79 80 81 82 83 84 85 86 87 89 90 91 92 93 94 95 96 97 98 012 013
014 015 016 017 018 019 021 023 024 025 026 027 028 029 031 032 034 035 036
037 038 039 041 042 043 045 046 047 048 049 051 052 053 054 056 057 058 059
061 062 063 064 065 067 068 069 071 072 073 074 075 076 078 079 081 082 083
084 085 086 087 089 091 092 093 094 095 096 097 098 102 103 104 105 106 107
108 109 120 123 124 125 126 127 128 129 130 132 134 135 136 137 138 139 140
…
901 902 903 904 905 906 907 908 910 912 913 914 915 916 917 918 920 921 923
924 925 926 927 928 930 931 932 934 935 936 937 938 940 941 942 943 945 946
947 948 950 951 952 953 954 956 957 958 960 961 962 963 964 965 967 968 970
971 972 973 974 975 976 978 980 981 982 983 984 985 986 987 0123 0124 0125
0126 0127 0128 0129 0132 0134 0135 0136 0137 0138 0139 0142 0143 0145 0146
0147 0148 0149 0152 0153 0154 0156 0157 0158 0159 0162 0163 0164 0165 0167
…
0917 0918 0921 0923 0924 0925 0926 0927 0928 0931 0932 0934 0935 0936 0937
0938 0941 0942 0943 0945 0946 0947 0948 0951 0952 0953 0954 0956 0957 0958
0961 0962 0963 0964 0965 0967 0968 0971 0972 0973 0974 0975 0976 0978 0981
0982 0983 0984 0985 0986 0987 1023 1024 1025 1026 1027 1028 1029 1032 1034
1035 1036 1037 1038 1039 1042 1043 1045 1046 1047 1048 1049 1052 1053 1054
1056 1057 1058 1059 1062 1063 1064 1065 1067 1068 1069 1072 1073 1074 1075
…
9820 9821 9823 9824 9825 9826 9827 9830 9831 9832 9834 9835 9836 9837 9840
9841 9842 9843 9845 9846 9847 9850 9851 9852 9853 9854 9856 9857 9860 9861
9862 9863 9864 9865 9867 9870 9871 9872 9873 9874 9875 9876 01234 01235 01236
01237 01238 01239 01243 01245 01246 01247 01248 01249 01253 01254 01256 01257
01258 01259 01263 01264 01265 01267 01268 01269 01273 01274 01275 01276 01278
01279 01283 01284 01285 01286 01287 01289 01293 01294 01295 01296 01297 01298
…
09827 09831 09832 09834 09835 09836 09837 09841 09842 09843 09845 09846 09847
09851 09852 09853 09854 09856 09857 09861 09862 09863 09864 09865 09867 09871
09872 09873 09874 09875 09876 10234 10235 10236 10237 10238 10239 10243 10245
10246 10247 10248 10249 10253 10254 10256 10257 10258 10259 10263 10264 10265
…
98705 98706 98710 98712 98713 98714 98715 98716 98720 98721 98723 98724 98725
98726 98730 98731 98732 98734 98735 98736 98740 98741 98742 98743 98745 98746
98750 98751 98752 98753 98754 98756 98760 98761 98762 98763 98764 98765 012345
012346 012347 012348 012349 012354 012356 012357 012358 012359 012364 012365
012367 012368 012369 012374 012375 012376 012378 012379 012384 012385 012386
…
098653 098654 098657 098671 098672 098673 098674 098675 098712 098713 098714
098715 098716 098721 098723 098724 098725 098726 098731 098732 098734 098735
098736 098741 098742 098743 098745 098746 098751 098752 098753 098754 098756
098761 098762 098763 098764 098765
Using a loop (from 0 to 999,999, inclusive), and rejecting values with repeating digits sounds like the most straightforward implementation to me.
The reject-if-duplicate-digits function can be made to be pretty fast. Consider, for example,
int has_duplicate_digits(unsigned int value)
{
unsigned int digit_mask = 0U;
do {
/* (value % 10U) is the value of the rightmost
decimal digit of (value).
1U << (value % 10U) refers to the value of
the corresponding bit -- bit 0 to bit 9. */
const unsigned int mask = 1U << (value % 10U);
/* If the bit is already set in digit_mask,
we have a duplicate digit in value. */
if (mask & digit_mask)
return 1;
/* Mark this digit as seen in the digit_mask. */
digit_mask |= mask;
/* Drop the rightmost digit off value.
Note that this is integer division. */
value /= 10U;
/* If we have additional digits, repeat loop. */
} while (value);
/* No duplicate digits found. */
return 0;
}
This is actually a classical combinatorial problem. Below is a proof of concept implementation using Algorithm L in TAOCP 7.2.1.2 and Algorithm T in TAOCP 7.2.1.3. There might be some errors. Refer to the algorithms for details.
Here is a bit of explanation. Let t be the number of digits. For t == 10, the problem is to generate all t! permutations of the set {0,1,2,...,9} in lexicographic order (Algorithm L).
For t > 0 and t < 10, this breaks down to 1) Generate all combinations of t digits from the 10 possible digits. 2). For each combination, generate all t! permutations.
Last, you can sort all 10! + 10! / 2 + 10! / 3! + .. + 10 results. The sorting might look expensive at first. But first, the combination generating is already in lexical order. Second, the permutation generating is also in lexical order. So the sequence is actually highly regular. A QSort is not really too bad here.
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
static inline int compare_str(const void *a, const void *b)
{
return strcmp(a, b);
}
static inline int compare_char(const void *a, const void *b)
{
char ca = *((char *) a);
char cb = *((char *) b);
if (ca < cb)
return -1;
if (ca > cb)
return 1;
return 0;
}
// Algorithm L in TAOCP 7.2.1.2
static inline char *algorithm_l(int n, const char *c, char *r)
{
char a[n + 1];
memcpy(a, c, n);
a[n] = '\0';
qsort(a, n, 1, compare_char);
while (1) {
// L1. [Visit]
memcpy(r, a, n + 1);
r += n + 1;
// L2. [Find j]
int j = n - 1;
while (j > 0 && a[j - 1] >= a[j])
--j;
if (j == 0)
break;
// L3. [Increase a[j - 1]]
int l = n;
while (l >= 0 && a[j - 1] >= a[l - 1])
--l;
char tmp = a[j - 1];
a[j - 1] = a[l - 1];
a[l - 1] = tmp;
// L4. [Reverse a[j]...a[n-1]]
int k = j + 1;
l = n;
while (k < l) {
char tmp = a[k - 1];
a[k - 1] = a[l - 1];
a[l - 1] = tmp;
++k;
--l;
}
}
return r;
}
// Algorithm T in TAOCP 7.2.1.2
static inline void algorithm_t(int t, char *r)
{
assert(t > 0);
assert(t < 10);
// Algorithm T in TAOCP 7.2.1.3
// T1. [Initialize]
char c[12]; // the digits
for (int i = 0; i < t; ++i)
c[i] = '0' + i;
c[t] = '9' + 1;
c[t + 1] = '0';
char j = t;
char x = '0';
while (1) {
// T2. [Visit]
r = algorithm_l(t, c, r);
if (j > 0) {
x = '0' + j;
} else {
// T3. [Easy case?]
if (c[0] + 1 < c[1]) {
++c[0];
continue;
}
j = 2;
// T4. [Find j]
while (1) {
c[j - 2] = '0' + j - 2;
x = c[j - 1] + 1;
if (x != c[j])
break;
++j;
}
// T5. [Done?]
if (j > t)
break;
}
// T6. [Increase c[j - 1]]
c[j - 1] = x;
--j;
}
}
static inline void generate(int t)
{
assert(t >= 0 && t <= 10);
if (t == 0)
return;
int n = 1;
int k = 10;
for (int i = 1; i <= t; ++i, --k)
n *= k;
char *r = (char *) malloc((t + 1) * n);
if (t == 10) {
algorithm_l(10, "0123456789", r);
} else {
algorithm_t(t, r);
}
qsort(r, n, t + 1, strcmpv);
for (int i = 0; i < n; ++i, r += t + 1)
printf("%s\n", r);
}
int main()
{
for (int t = 1; t <= 10; ++t)
generate(t);
}
Efficiency: This is implementation is not very efficient. It is a direct translation from the algorithm, for easier understanding. However it is still a lot more efficient than iterating over 10^10 numbers. It takes about 2.5 seconds to generate all numbers from 0 to 9876543210. This includes the time of writing them to a file, a 94MB output file, with one number a line. For up to 6 digits, it takes about 0.05 seconds.
If you want these numbers come in the order you want in program, it might be better to generate the numbers as above to prepare a table and use the table later. Even for the table from 0 to 9876543210, there are less than ten million numbers, which is not a really big number in today's computers. In your case, up to six digits, there are only less than one million numbers.

I need to find the prime numbers from 1 to 300 using C. I am using the following code

I know that there is mistake in second for loop but I am not able to figure out. I think after if the continue will take it to to for loop if a%i ==0 and if a%i!=0 than it should print a which would be an prime number , but instead it is printing all the numbers from 2 to 300. Please help!!
The continue and break instructions both instruct the inner i loop. So whatever happens, your code prints every value of a in the outer loop.
#include <stdio.h>
int main(void) {
int a, i;
for (a=1; a<=300; a++) {
for (i=2; i<a; i++) { // changed from the clumsy i<=a-1
if (a % i == 0)
break; // end loop if i is a divisor
}
if (i == a) // if the loop completed
printf ("%d\t", a);
}
return 0;
}
Program output:
2 3 5 7 11 13 17 19 23 29
31 37 41 43 47 53 59 61 67 71
73 79 83 89 97 101 103 107 109 113
127 131 137 139 149 151 157 163 167 173
179 181 191 193 197 199 211 223 227 229
233 239 241 251 257 263 269 271 277 281
283 293
It's also a rather crude way to figure out primes, but first things first.
Better try this:
#include<stdio.h>
int main()
{
int i,j,isPrime;
for(i=2;i<300;i++)
{
isPrime = 1; //Firstly we assume that the number is prime;
for(j=2;j<i-1;j++) // you can also use i/2 or sqrt(i) for checking
{
if(i%j==0) //This condition only evaluates to true when j is factor of i
{
isPrime = 0;
break; //Now as we have a factor we are sure its not prime,So break the loop;
}
}
if(isPrime == 1) printf("%d\t",i);
}
return 0;
}
In your inner loop, you do either a break or a continue. But this merely breaks or continues the inner loop, and the printf will be executed irrespective of which is chosen. If you'd pasted the code as text, I might have fixed it for you!

Scanf two numbers at a time from stdout

I have a program that outputs a huge array of integers to stdout, each integer in a line. Ex:
103
104
105
107
I need to write another program that reads in that array and fill up the spaces where the number isn't an increment of 1 of the previous number. The only different between numbers is going to be 2 (105,107), which makes it easier.
This is my code to do that logic:
printf("d",num1);
if ((num2-num1) != 1)
numbetween = num1 + 1;
printf("%d", numbetween);
printf("%d", num2);
else(
printf("%d",num2);
)
So the output of this program will now be:
103
104
105
106
107
My issue is reading the numbers. I know I can do while (scanf("%hd", &num) != EOF) to read all the lines one at a time. But to do the logic that I want, I'm going to need to read two lines at a time and do computation with them, and I don't know how.
You could always just read the first and last numbers from the file, and then print everything in between.
int main( void )
{
// get the first value in the file
int start;
if ( scanf( "%d", &start ) != 1 )
exit( 1 );
// get the last value in the file
int end = start;
while ( scanf( "%d", &end ) == 1 )
;
// print the list of numbers
for ( int i = start; i <= end; i++ )
printf( "%d\n", i );
}
Read first num then add missing if needed when you read next int
#include <stdio.h>
#include <stdlib.h>
int main()
{
int previous = 0;
int num;
scanf("%hd", &previous);
while (scanf("%hd", &num) != EOF) {
for (int i = previous; i < num; i++) {
printf("%d\n" , i);
}
previous = num;
}
printf("%d\n" , previous);
return 0;
}
this input
100
102
103
105
107
110
returns this output
100
101
102
103
104
105
106
107
108
109
110
While you can read the first and last, to fill the range, what you are really doing is finding the min and max and printing all values between them inclusively. Below the names are left first and last, but they represent min and max and will cover your range regardless whether the values are entered in order. Taking that into consideration, another approach insuring you cover the limits of the range of int would be:
#include <stdio.h>
int main (void) {
int num = 0;
int first = (1U << 31) - 1; /* INT_MAX */
int last = (-first - 1); /* INT_MIN */
/* read all values saving only first (min) and last (max) */
while (scanf (" %d", &num) != EOF) {
first = num < first ? num : first;
last = num > last ? num : last;
}
/* print all values first -> last */
for (num = first; num <= last; num++)
printf ("%d\n", num);
return 0;
}
Input
$ cat dat/firstlast.txt
21
25
29
33
37
41
45
49
53
57
61
65
69
73
77
81
85
89
93
97
101
Output
$ ./bin/firstlast < dat/firstlast.txt
21
22
23
24
25
26
27
28
29
<snip>
94
95
96
97
98
99
100
101
Note: you can change the types to conform to your expected range of data.

Resources