I have a basic text file I point my program at to run that has numbers line by line such as:
3
30
300
3000
30000
300000
3000000
30000000
300000000
-3
-30
-300
-3000
-30000
-300000
-3000000
-30000000
-300000000
and I need to print them out into evenly spaced columns and I want them to fit into 40 characters (4 columns wide). I want to use the sprintf function to do this. So basically print each number out plus 2 spaces for formatting and fit within 40 characters total. So far this is what I have.
int main(int argc, char *argv[]){
int a, b, num[1000], nums = 0;
char str[40];
FILE *pt;
int col, max, w;
if(argc < 2){
printf("Usage %s <No Files>\n", argv[0]);
return 1;
}
if((pt = fopen(argv[1], "r")) == NULL){
printf("Unable to open %s for reading.\n", argv[1]);
return 1;
}
while(fscanf(pt, "%d", &b) == 1){
num[nums++] = b;
}
w = sprintf(str, "%*d", num[a]);
if(max < w){
col = 40 / (max + 2);
printf("%d %d\n", w, num[a]);
}
return 0;
}
I just get garbage when I point it to the text file mentioned in the above. Any advice?
To print N numbers in 4 columns with width 10 characters use printf("%10d") inside the loop that add new line (\n) after each 4th printing, e.g.:
for (int i = 1; i <= nums; i++)
{
printf("%10d", num[i-1]); // or printf("%-10d", num[i-1]);
if (i % 4 == 0)
printf("\n"); // or putchar ('\n')
}
sign - in the format %-10d change alignment.
As you see sprinf is not used here, I use printf for each number to print the value at screen (standard output).
UPDATE:
If you want to find optimal width of the column, and use it for output, e.g. using the number of digits in your biggest number (let it be maxValue an integer value found in the array num), you can find the minimum required number of digits (let it be minWidth), like:
char buff[20] = {0};
int minWidth = strlen(_itoa(maxValue,buff,10));
and then change the printing loop like:
for (int i = 1; i <= nums; i++)
{
printf("%*d", minWidth + 1, num[i - 1]);
if (i % 4 == 0) putchar('\n');
}
here vlaue minWidth + 1 will be used in format specifier %*d instead of *, and +1 is used for minimum separation between columns in one space (of course, there can be 2 or 3).
Finally, having the column width calculated, you can find the number of column for your screen and use this value for starting new line, e.g.:
const int screenWidth = 80;
int colWidth = minWidth + 2; // here 2 is added for minimum separation of columns
int colNum = screenWidth / colWidth;
for (int i = 1; i <= nums; i++)
{
printf("%*d", colWidth, num[i - 1]);
if ( !(i % colNum) ) putchar('\n'); // !(i % colNum) is the same to i % colNum == 0
}
This is my second answer for the same question, but this answer more close to the topic - here output is made to the string with sprintf.
So, lets we have array of numbers int num[1000] and we need to print nums of them to several string (length is limited by value stringMaxLength) using formatting as columns with width depending on length of number representation (maximum number in the array).
The following snippet has comments for all operations
// string that will be made from numbers
const int stringMaxLength = 120;
char str[stringMaxLength + 1]; // just one string
// find longest number considering sign
char buff[20] = { 0 };
int maxNumWidth = 0, numWidth;
int n;
for (n = 0; n < nums; n++)
{
numWidth = strlen(_itoa(num[n], buff, 10));
if (numWidth > maxNumWidth)
maxNumWidth = numWidth;
}
int colWidth = maxNumWidth + 1; // a column size with one space between columns
int colNum = stringMaxLength / colWidth; // number of columns in one string
int s, i; // i - nums counter, s - strings counter
for (i = 0, s = 1; i < nums; s++) // loop counts strings but with condition for nums
{
int sizeCnt = 0; // start making new string str
// loop works while there are numbers and the line is not filled completely
while (i < nums)
{
// add next number (column) to the string and increase string size
sizeCnt += sprintf(str + sizeCnt, "%*d", colWidth, num[i++]);
if (i % colNum == 0) // if string has colNum numbers it is full
{
break; // stop while loop
}
}
// next string is ready and can be used
printf("%d : %s\n", s, str); // e.g. for output
}
Related
i am new to c, and I am building a cipher text converter. I have a main function to take a Key value (int k) from the user and pass that value to this function:
int ciphertextCoverter (int k)
{
printf("key=%i\n",k);
char ciphertext[] = "";
string plaintext = get_string("plaintext: ");
for (int n = 0, x = strlen(plaintext); n < x; n++)
{
printf("key in FOR loop: %i",k);
if isupper(plaintext[n])
{
printf("key in IF loop: %i",k);
ciphertext[n] = (plaintext[n] - 'A'+ k ) % 26 + 65;
printf("plaintext- %i %c %i %i %i %i %i\n",k, plaintext[n],plaintext[n], plaintext[n]-'A', (plaintext[n] - 'A'+ k), (plaintext[n] - 'A'+ k) % 26, (plaintext[n] - 'A'+ k) % 26+ 65);
}
else
{
ciphertext[n] = (plaintext[n] - 'a'+ k) % 26 + 97;
}
}
printf("ciphertext: %s\n",ciphertext);
return 0;
}
I used printf to find out that the value of int k which I passed on from the main function has changed value in the for loop, but I want to stay as a const. Please help me! what have I done wrong?
You are declaring ciphertext as an array of size 1, so you cannot write any data to it. Give it some size; something like:
string plaintext = get_string("plaintext: ");
char ciphertext[strlen(plaintext) + 1];
should work. Just remember to write the null terminator at the end: ciphertext[x] = '\0'
You have declared character array of size 1. And you are storing x characters in ciphertext[]. First declare array of any size or create array dynamically.
char ciphertext[] = "";
I'm trying to error check command line arguments to make sure they are integers, and surprisingly having a difficult time doing so. Here is a snippet of code I have that works when all the command line arguments are integers.
Program can have infinite values passed into it.
One example: ./program -p 45 67 3 9 1
for (argCounter = 2; argCounter < argc; argCounter++)
{
total = total * atoi(argv[argCounter]);
}
What happens when a user types 5g? atoi() converts it to 5. I need to it to return an error. For some reason I was having trouble getting isdigit() to work properly as well. I tried so many random things that my head is spinning at this point. So what I'm trying to do is:
for (argCounter = 2; argCounter < argc; argCounter++)
{
//pseudocode
if (argv[argCounter] != integer)
{
printf("Error!");
return 0;
}
total = total * atoi(argv[argCounter]);
}
You can use sscanf(). Its %n placeholder can be used to determine the number of characters consumed, which you can compare to the string length:
for (argCounter = 2; argCounter < argc; argCounter++)
{
int value, consumed;
if ((sscanf(argv[argCounter], "%d%n", &value, &consumed) != 1) ||
(argv[argCounter][consumed] != '\0'))
{
printf("Error!");
return 0;
}
total *= value;
}
Or, you can use strtol(). It can output a pointer to the first unparsed character. You can check to see if that character is a null terminator or not:
for (argCounter = 2; argCounter < argc; argCounter++)
{
char *end;
errno = 0;
long value = strtol(argv[argCounter], &end, 10);
if ((end == argv[argCounter]) ||
(*end != '\0') ||
(((value == LONG_MIN) || (value == LONG_MAX)) && (errno == ERANGE)))
{
printf("Error!");
return 0;
}
total *= value;
}
Well I'm quite a beginner and I don't exactly understand what you want to do exactly?
if I understand, you want to check if all arguments are numbers (only digits) included in the integer range you want that total contain the produce of the multiplication of all these integers (and I assume you also want total to be in integer range?)
long long total = 1;
for (argCounter = 1; argCounter < argc; argCounter++)
{
char *check_end;
long long nbr = stroll(arg[argCounter], &check_end, 10);
if (!argv[argCounter][0]|| *check_end || nbr > INT_MAX || nbr < INT_MIN || nbr * total > INT_MAX || nbr * total < INT_MIN)
{
total = 0;
printf("Error\n");
break;
}
total *= nbr;
}
maybe this should help, stroll convert a string (given as first parameter) in a base(given as third parameter) to a long long and set the string's pointer (given as second parameter) to the place on the string where the conversion stopped (\0 if only digits after the sign) you could check the stroll man; anyway im not sure my code is very optimised or functional and you may want to get an int at the end so cast as int total variable to an int variable.
You are tasked to create a program that will read in a text file and compute statistics on the contents. Your program will count the number of alphabetic characters using isalpha(), the number of digits using isdigit() and the number of punctuation using ispunct(). (Zybook module 11). Your program will provide an appropriate report to display the analysis results to the user. Your program should work with any text file and the user should be able to select the file for input. You may create a test text file for testing and development. I suggest a short paragraph with punctuation and numbers that you can easily test the values with. Your array may be a VLA or FLA array. I suggest using an array of pointers and for each line of the text file allocate an array using calloc(). You may declare a static array, so long as it will hold 100 lines of 80 characters. A line length of 80 characters will be assumed.
Ive written most of the code but am getting a couple warnings and the program terminates abruptly and gives me a segmentation error.
#include <stdio.h>
#include <ctype.h>
#include <string.h>
int main(void) {
//Declarations
char paragraphArray[100][80], filename[50];
int i = 0, puncts = 0, alphas = 0, nums = 0, line = 0;
//Ask user what file to load and assign it to filename
printf("Enter the filename to wish to load: ");
scanf("%s", filename);
//FIle pointer is tagged
FILE *fPoint;
//Opens file pointer as the user-named file in read mode
fPoint = fopen(filename, "r");
//If file not found, a NULL value is assigned and prints to screen.
if(fPoint == NULL)
printf("Cannot open file");
//Else statement that reads the file line by line starting at index i=0
else
{ i=0;
while(fgets(paragraphArray[i], 80, fPoint))
{ paragraphArray[i][(strlen(paragraphArray[i]))-1]='\0';
i++;
}
//After while loop is finished, the value of i is stored as number of lines.
line = i;
}
//Closing the file
fclose(fPoint);
//Function Calls
alphas = IsAlpha(paragraphArray, i);
nums = IsDigit(paragraphArray, i);
puncts = IsPunct(paragraphArray, i);
//Display statistics to screen.
printf("There are %d alphabet characters.\n", alphas);
printf("There are %d numerical digits.\n" , nums);
printf("There are %d punctuation marks.\n" , puncts);
}
//Function Definitions
int IsAlpha(char paragraphArray[100][80], int line){
int alphaCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer loop that iterates through each line of the paragraph.
for(i = 0; i < line; i++){
//Inner loop that compares elements of the array to ASCII values
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//if statement that does the comparison and adds to count value
if((asciiValue <= 90 && asciiValue >= 65) || (asciiValue >= 97 && asciiValue <= 122))
alphaCount++;
}
}
//Returns count of alphabet characters after all iterations.
return alphaCount;
}
int IsDigit(char paragraphArray[100][80], int line){
int digitCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer loop that iterates through each line of paragraph
for(i = 0; i < line; i++){
//Inner loop that compares elements of array to ASCII values.
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//If statement that does the comparison and adds count value.
if(asciiValue >= 48 && asciiValue <= 57)
digitCount++;
}
}
//Returns count of numbers after all iterations.
return digitCount;
}
int IsPunct(char paragraphArray[100][80], int line){
int punctCount = 0, i = 0, j = 0, asciiValue = 0;
//Outer Loop that iterates through each line of paragraph.
for(i = 0; i < line; i++){
//Inner loop that compares elements of array to ASCII Values
for(j = 0; j < 80; j++){
asciiValue = paragraphArray[i][j];
//If statement that does comparison and adds count value.
if((asciiValue >= 33 && asciiValue <= 47) || (asciiValue >= 58 && asciiValue <= 64) || (asciiValue >= 91 && asciiValue <= 96) ||(asciiValue >= 123 && asciiValue <= 126))
punctCount++;
}
}
return punctCount;
}
Your problem is in for loop condition.
You itterate with the condition i < 80, but, if your line is lower than 80,
you compare undefined value.
Instead of 80 use strlen.
You can also use valgrind or gdp to debug your program. :)
I am working on a string search and replace project. I can only change 1 of the target pattern in the sentence. But I can find both.
Example: just do it. you will do it.
find: do
replace: think
expected---> just think it. you will think it.
what actually happened ---> just do it. you will think it.
How can I replace both of them?
I read the sentence from file input.txt
# include <limits.h>
# include <string.h>
# include <stdio.h>
#include <sys/time.h>
# define NO_OF_CHARS 256
# define MAX 10000
int sum = 0;
int control = 0;
// A utility function to get maximum of two integers
int max (int a, int b) { return (a > b)? a: b; }
// The preprocessing function for Boyer Moore's bad character heuristic
void badCharHeuristic( char *str, int size, int badchar[NO_OF_CHARS]) {
int i;
// Initialize all occurrences as -1
for (i = 0; i < NO_OF_CHARS; i++)
badchar[i] = -1;
// Fill the actual value of last occurrence of a character
for (i = 0; i < size; i++)
badchar[(int) str[i]] = i;
}
/* A pattern searching function that uses Bad Character Heuristic of Boyer Moore Algorithm */
void search( char *txt, char *pat,char temp3[MAX],int k,char*r) {
int m = strlen(pat);
int n = strlen(txt);
char src[MAX],p[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int badchar[NO_OF_CHARS],i,leng,l,count;
char v;
/* Fill the bad character array by calling the preprocessing function badCharHeuristic() for given pattern */
badCharHeuristic(pat, m, badchar);
leng = strlen(pat);
strcpy(tempP,r);
//strcat(tempP,"</mark>");
leng = strlen(pat);
l = strlen(txt);
int s = 0; // s is shift of the pattern with respect to text
while(s <= (n - m)) {
int j = m-1;
/* Keep reducing index j of pattern while characters of pattern and text are matching at this shift s */
while(j >= 0 && pat[j] == txt[s+j]) {
count++;
j--;
}
/* If the pattern is present at current shift, then index j will become -1 after the above loop */
if (j < 0) {
//printf("pattern occurs at shift = %d\n", s);
/* Shift the pattern so that the next character in text
aligns with the last occurrence of it in pattern.
The condition s+m < n is necessary for the case when
pattern occurs at the end of text */
printf("The desired pattern was found starting from %d. line at position %d\n",k,s+1);
strncpy(temp, txt, s);
temp[s] = '\0';
//strcat(temp,"<mark>");
control++;
strcat(temp,tempP);
for(i=0;i<MAX;i++) {
if((s+leng+i)<strlen(txt))
temp2[i] = txt[s+leng+i];
else
temp2[i] = v;
}
strcat(temp,temp2);
strcpy(temp3,temp);
s += (s+m < n)? m-badchar[txt[s+m]] : 1;
}
else
/* Shift the pattern so that the bad character in text
aligns with the last occurrence of it in pattern. The
max function is used to make sure that we get a positive
shift. We may get a negative shift if the last occurrence
of bad character in pattern is on the right side of the
current character. */
s += max(1, j - badchar[txt[s+j]]);
}
sum +=count;
}
/* Driver program to test above funtion */
int main() {
char txt[MAX],p[MAX],r[MAX],temp[MAX],temp2[MAX],tempP[MAX],out[MAX];
int k = 1;
FILE *input = fopen("input.txt","r");
FILE *output = fopen("output.txt","w");
printf("Enter the text in which pattern is to be searched:");
fgets(p, MAX, stdin);
printf("Enter the text in which pattern is to be replaced:");
fgets(r, MAX, stdin);
struct timeval tv1, tv2;
gettimeofday(&tv1, NULL);
p[strlen(p)-1]='\0';
temp[1]='a';
while(!feof(input)){
if(fgets (txt, MAX, input)!=NULL) {
txt[strlen(txt)-1] = '\0';
search(txt, p,temp,k,r);
if(temp[1]!='a') {
fprintf(output,"%s\n",temp);
temp[1]='a';
}
else
fprintf(output,"%s\n",txt);
}
k++;
}
if(control==0) {
printf("\nThe pattern was not found in the given text\n\n");
}
gettimeofday(&tv2, NULL);
printf ("Total time = %f seconds\n", (double) (tv2.tv_usec - tv1.tv_usec) / 1000000 + (double) (tv2.tv_sec - tv1.tv_sec));
fclose(input);
fclose(output);
printf("The number of character comparison: %d\n",sum);
return 0;
}
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
I need a clean c code to find out combination of numbers.
Any number of numbers and any size of combination.
Such as for {1,2,3}
output should be {1,2,3,12,13,23,123}, note 23 and 32 as same.
Is there any clean c program for that ?
Best regards,
There are many ways of doing this. Here's a way using bit manipulation.
Let the given set be a.
The code for this is pretty small. Understand the following and you will understand how that tiny snippet of code works.
The first thing you have to realize here is that you are finding the (2n - 1) subset of the given set.
Any set has 2n subsets and here, you have excluded the null set. Hence (2n - 1)
Now, to generate these subsets we need an algorithm.
Observe the following:
001 --- 1
010 --- 2
011 --- 3
100 --- 4
101 --- 5
110 --- 6
111 --- 7
The left digits constitute the binary representation of the right decimal numbers.
If we write out for binary numbers with 4 digits, there would be 15 combinations. Notice that I am excluding the combination where all digits are zero in the above example.
In general, for n-bit binary numbers, there are (2n - 1) different combinations of the digits. We can use this to generate the subsets, in a very simple fashion.
For every element in the set, you are allowed to:
Choose the element for the current subset.
Don't choose that element for the current subset.
Leave out the situation where you choose none.
(Hence, there are (2n - 1) subsets)
Now, I say do the following:
for i in [1,2^n - 1]:
Let b = binary representation of i.
for every jth bit in b:
if the jth bit is set:
print a[j]
print a newline character.
Here is the C code:
// include your headers
int isJthBitSet(int i,int j)
{
// returns 1 if jth bit is set in the binary representation of i.
return (i & (1 << j));
}
int main()
{
int n = 3; // The size of the set for example.
int a[] = {1,2,3}; // the given set, for example.
for(int i = 1; i < (1 << n); i++) // i is from 1...2^n - 1
{
for(int j = 0; j < n; j++) // for every jth bit in the n-bit representation of i
{
if(isJthBitSet(i,j)) // if the bit is set
printf("%d ", a[j]); // print the corresponding element
}
printf("\n");
}
return 0;
}
And that would be pretty much it.
While I normally frown upon showing complete solutions, based on a few relatively recent similar questions and their answers, it seems that some examples of how to solve these types of combinatorics problems are warranted.
An easy way to construct all unique sets with k elements out of n elements, is to use k nested loops, where the loop indexes are always in increasing order. For example, to print all unique 3 char triplets, from a set of N chars, you could use
const char all[N] = ...;
char set[4];
size_t i, j, k;
set[3] = '\0'; /* End of string mark */
for (i = 0; i < N-2; i++) {
set[0] = all[i];
for (j = i+1; j < N-1; j++) {
set[1] = all[j];
for (k = j+1; k < N; k++) {
set[2] = all[k];
puts(set);
}
}
}
Now, the OP wants all unique subsets with up to k elements out of a set of n elements, which means we need cannot use nested loops as above (since we don't know the maximum k). Explicitly, anyway. Instead, we need to think of how to rewrite that.
To get a better grip on the construction, let's look at say the three-out-of-five case. The ten result sets are
1 2 3
1 2 4
1 2 5
1 3 4
1 3 5
1 4 5
2 3 4
2 3 5
2 4 5
3 4 5
There is clear order, and clear logic: increase the rightmost, unless it would become too large. Then, find the next index to the left that we can increment without going over (keeping enough elements for those on its right side). If we cannot increment even the leftmost without going over, we have produced all sets. (If you think about it, this is also quite a straightforward implementation of variably-nested loops.) After incrementing, set the elements to the right in ascending order.
In most cases, we'd like some sort of structure or object that keep tracks of the state and the current subset, with functions to initialize, free, and to switch to the next subset. Here is one possibility:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>
typedef struct {
char *buffer; /* Symbol buffer */
size_t length; /* Number of symbols to choose */
size_t *index; /* Index of each symbol */
char *symbol; /* Array of symbols */
size_t symbols; /* Number of symbols to choose from */
} generator;
void generator_free(generator *const g)
{
if (g) {
free(g->buffer);
free(g->index);
free(g->symbol);
g->buffer = NULL;
g->length = 0;
g->index = NULL;
g->symbol = NULL;
g->symbols = 0;
}
}
const char *generator_current(generator *const g, const char *const none)
{
return (g && g->buffer) ? g->buffer : none;
}
int generator_init(generator *const g, const char *const symbol, const size_t choose)
{
const size_t symbols = (symbol) ? strlen(symbol) : 0;
size_t i;
if (!g || symbols < 1 || choose < 1 || choose > symbols)
return EINVAL;
g->buffer = malloc(choose + 1);
g->index = malloc((choose + 1) * sizeof g->index[0]);
g->symbol = malloc(symbols + 1);
if (!g->buffer || !g->index || !g->symbol) {
free(g->buffer);
free(g->index);
free(g->symbol);
g->buffer = NULL;
g->length = 0;
g->index = NULL;
g->symbol = NULL;
g->symbols = 0;
return ENOMEM;
}
memcpy(g->buffer, symbol, choose);
g->buffer[choose] = '\0';
g->length = choose;
for (i = 0; i < choose; i++)
g->index[i] = i;
g->index[choose] = symbols;
memcpy(g->symbol, symbol, symbols);
g->symbol[symbols] = '\0';
g->symbols = symbols;
return 0;
}
int generator_next(generator *const g)
{
size_t i;
if (!g || !g->buffer || g->length < 1 || !g->index)
return EINVAL;
if (g->index[0] >= g->symbols - g->length)
return ENOENT;
if (++g->index[g->length - 1] >= g->symbols) {
i = g->length - 1;
while (i > 0 && g->index[i] + 1 >= g->symbols - i)
i--;
g->index[i]++;
if (!i && g->index[0] > g->symbols - g->length) {
memset(g->buffer, '\0', g->length + 1);
return ENOENT;
}
while (i++ < g->length)
g->index[i] = g->index[i-1] + 1;
}
for (i = 0; i < g->length; i++)
g->buffer[i] = g->symbol[g->index[i]];
g->buffer[g->length] = '\0';
return 0;
}
generator_current() provides the current set (as a string). Instead of returning NULL when there is no valid set, it returns the string you specify as the second parameter. (It's just for convenience, no real reason behind this.)
generator_free() discards the generator, generator_init() initializes a new generator, and generator_next() advances the generator to the next subset.
Note that generator_init() also initializes the first subset; the one where the elements are chosen consecutively. (Although the ->symbol is only a character array containing all characters in the overall set, the function appends an end-of-string mark, so you can treat it as a string, too.)
The first if clause in generator_next() just makes sure the generator is initialized; it's just a sanity check. The second one checks if the generator is complete.
The third if clause in generator_next() increments the rightmost index, changing the last element in the subset. If it runs out of valid elements, the while loop searches for the index i for an index that can be incremented without running out of elements. Note that because the indexes are in ascending order (that ensures unique subsets), this must remember to account for the elements needed for the rest of the position.
If i becomes zero and overflows, there are no more subsets, and the ->buffer member is cleared to an empty string (just in case).
Otherwise, the second while loop fills in the indexes to the right of i with consecutive values. (See the above example for three-out-of-five, the case where the first element changes from 1 to 2, for illustration of why this is needed.)
Finally, the for loop is used to copy the elements from the ->symbol array, according to the indexes, to ->buffer.
For the askers case, the size of the subsets varies, so to generate all subsets, a loop is needed. For example:
generator g;
size_t i;
for (i = 1; i <= 2; i++) {
if (generator_init(&g, "123", i)) {
fprintf(stderr, "generator_init() failed!\n");
exit(EXIT_FAILURE);
}
do {
/* Print the set and a newline */
puts(generator_current(&g, ""));
} while (!generator_next(&g));
generator_free(&g);
}
For testing, I used the following helper function and main():
int parse_size(const char *s, size_t *const dst)
{
const char *endptr = NULL;
unsigned long value;
size_t result;
int skip = -1;
if (!s || !*s)
return EINVAL;
errno = 0;
value = strtoul(s, (char **)&endptr, 0);
if (errno)
return errno;
if (!endptr || endptr == s)
return EEXIST;
(void)sscanf(endptr, " %n", &skip);
if (skip > 0)
endptr += skip;
if (*endptr)
return EEXIST;
result = (size_t)value;
if ((unsigned long)result != value)
return EDOM;
if (dst)
*dst = result;
return 0;
}
int main(int argc, char *argv[])
{
generator g;
size_t symbols, length, len;
if (argc != 3 || !strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) {
fprintf(stderr, "\n");
fprintf(stderr, "Usage: %s [ -h | --help ]\n", argv[0]);
fprintf(stderr, " %s DIGITS LENGTH\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "This will print each unique set of LENGTH characters from DIGITS,\n");
fprintf(stderr, "one set per line.\n");
fprintf(stderr, "\n");
return EXIT_FAILURE;
}
symbols = (argv[1]) ? strlen(argv[1]) : 0;
if (symbols < 1) {
fprintf(stderr, "No DIGITS specified.\n");
return EXIT_FAILURE;
}
if (parse_size(argv[2], &length) || length < 1 || length > symbols) {
fprintf(stderr, "%s: Invalid LENGTH.\n", argv[2]);
return EXIT_FAILURE;
}
for (len = 1; len <= length; len++) {
if (generator_init(&g, argv[1], len)) {
fprintf(stderr, "Generator initialization failed.\n");
return EXIT_FAILURE;
}
do {
puts(generator_current(&g, ""));
} while (!generator_next(&g));
generator_free(&g);
}
return EXIT_SUCCESS;
}
In Linux, I prefer to compile the above using gcc -Wall -Wextra -ansi -pedantic -O2 main.c -o example. The original question asked for
./example 123 2
which outputs
1
2
3
12
13
23
A larger example is much more interesting. For example,
./example 12345 3
lists all one, two, and three-digit sets from the set of first five digits. The output is
1
2
3
4
5
12
13
14
15
23
24
25
34
35
45
123
124
125
134
135
145
234
235
245
345
Questions?