C - Printing combinations in an array or list - c

I made a program that takes a string of characters, and prints out all the possible combinations of them. However, is there a way to record each combo in a list or an array instead of just printing them on screen? Because I need to be able to manipulate some of the combos rather than just looking at them.
void swap( char *a, char *b ){
char tmp;
tmp = *a;
*a = *b;
*b = tmp;
}
void permutation( char *c, int d, int e ){
int f;
if( d == e )
printf( "%s\n", c );
else{
for( f = d; f <= e; f++ ){
swap( ( c + d ), ( c + f ) );
permutation( c, d + 1, e );
swap( ( c + d ), ( c + f ) );
}
}
}
int main(){
char wordInput[25];
int len, arrLen, f;
printf( "\nEnter text: " );
gets( wordInput );
len = strlen( wordInput );
arrLen = len - 1;
permutation( wordInput, 0, arrLen );
return 0;
}

Just change permuation() to the following:
int permutation( char *c, int d, int e, int n, char **permuted_strings)
where n is the index of the next unused element in your array permuted_strings. permuted_strings should be an array of k! elements if your string has length k, as indicated in a comment. If your condition (d == e) is met, then you should save the string at permuted_strings[n] and increment n by 1 and return this value as the new value for n. The permutation() function should always return the current value of n, and n should be reset to the return value of permutation() when it is called, so that subsequent calls to permutation() know the correct value of n, i.e. where to store the next string.

Related

My swap function which takes in pointer address does not swap the pointer. Why is that?

Current Outcome is:
After swapping
The first word you entered is temp1
The second word you entered is temp2
Expected Outcome should be:
After swapping
The first word you entered is temp2 <<Expecting different results
The second word you entered is temp1 <<Expecting different results
#include <stdio.h>
#include <stdlib.h>
int main()
{
void swap1(char *pword1, char *pword2) {
printf("word1 is %p\n",pword1);
printf("word2 is %p\n",pword2);
char temp[50] = "\0";
char *ptemp = temp;
ptemp = pword1;
pword1 = pword2;
pword2 = ptemp;
printf("word1 is %p\n",pword1);
printf("word2 is %p\n",pword2);
return;
}
char word1[50];
char word2[50];
printf("Before swapping\n");
printf("Enter the first word\n");
scanf("%s",word1);
printf("The first word you entered is %s\n",word1);
char *pword1 = word1;
printf("Enter the second word\n");
scanf("%s",word2);
printf("The second word you entered is %s\n",word2);
char *pword2 = word2;
swap1(pword1,pword2);
printf("\nAfter swapping\n");
printf("The first word you entered is %s\n",pword1);
printf("The second word you entered is %s\n",pword2);
return 0;
}
You need one more level of indirection, but see my notes below.
Let's strip this down a bit - if you want a function to swap two values of any non-array type T, you must pass pointers to them:
void swap( T *a, T *b )
{
T tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
T x = some_T_value;
T y = some_other_T_value;
swap( &x, &y );
}
We have
a == &x // T * == T *
b == &y // T * == T *
*a == x // T == T
*b == y // T == T
Now let's replace T with the type P *:
void swap( P **a, P **b ) // T *a == P * *a == P **a
{
P *tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
P *x = some_Pstar_value;
P *y = some_other_Pstar_value;
swap( &x, &y );
}
Our relationships are still the same:
a == &x // P ** == P **
b == &y // P ** == P **
*a == x // P * == P *
*b == y // P * == P *
All the semantics are exactly the same - a and b are always one more level of indirection than x and y, tmp is always the same level of indirection as x and y, you always pass &x and &y - the only difference is the type. Just to drive the point home, we'll go one more level and replace P with R *:
void swap( R ***a, R ***b )
{
R **tmp = *a;
*a = *b;
*b = tmp;
}
int main( void )
{
R **x = some_Rstarstar_value;
R **y = some_other_Rstarstar_value;
swap( &x, &y );
}
NOTE - If you want to swap the contents of arrays, rather than pointers to arrays, you'll have to do something different:
void swapArr( T *a, T *b, size_t bytes )
{
T tmp[size];
memcpy( tmp, a, size );
memcpy( a, b, size );
memcpy( b, tmp, size );
}
int main( void )
{
T a[N] = { ... };
T b[N] = { ... };
swap( a, b, sizeof a ); // no & operator
}

C: Trying to insert a struct into a struct array

in my code I have student profiles with name, age, and GPA. I also have an array with each profile. I'm trying to create an insert function that inserts another student profile into the array and display an error if the index is not valid. I'm trying to do so by moving adding another space in the array for the new student, then moving over the places of students occupying the wrong space by one space to the right.
Ex. If I want to put a student in index 2, the function would move the student occupying that space to 3, and the student in 3 would be moved to space 4.
Here's what I have so far, but I'm getting an error on array[i+1] = isaying "incompatible types when assigning to type Student from type type int." I tried changing i to type Student, I got several more errors all over the loop saying that it was an invalid initializer and that I couldn't use >=, and that i was the "wrong type to decrement
For starters it is unclear why the parameter index has the signed type int instead of the unsigned type size_t. The unsigned type allows to avoid this redundant check
if (index < 0 || index > *size) {
^^^^^^^^^
Also if the value of index is greater than the current value of *size then it is enough just to append the passed item to the array.
So in general this check
if (index < 0 || index > *size) {
is redundant.
The function declaration is too complicated. There is no need to return pointer to the first element of the passed array. The function declaration will look more simpler if to write it like
size_t insert( Student a[], size_t n, size_t i, const Student *student );
That is the function returns the new size of the updated array.
This statement
array[i+1] = i;
does not make any sense because the left operand has the type Student while the right operand has the type int. Moreover it has a logical error because instead of the index i + 1 you have to use the index i.
And instead of the manually written loop you could use the standard C function memmove.
Here is a demonstrative program that shows how the function can be defined.
#include <stdio.h>
#include <string.h>
#define MAX_LEN 10
typedef struct Student
{
char name[MAX_LEN];
unsigned int age;
} Student;
size_t insert( Student a[], size_t n, size_t i, const Student *student )
{
if ( n < i ) i = n;
if ( i < n )
{
memmove( a + i + 1, a + i, ( n - i ) * ( sizeof( Student ) ) );
}
a[i] = *student;
return ++n;
}
int main(void)
{
enum { N = 10 };
Student a[N] = { 0 };
Student student = { "A", 20 };
size_t n = insert( a, 0, 0, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "B" );
++student.age;
n = insert( a, n, 0, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "C" );
++student.age;
n = insert( a, n, 2, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
strcpy( student.name, "E" );
++student.age;
n = insert( a, n, 1, &student );
for ( size_t i = 0; i < n; i++ )
{
printf( "{ %s, %u } ", a[i].name, a[i].age );
}
putchar( '\n' );
return 0;
}
The program output is
{ A, 20 }
{ B, 21 } { A, 20 }
{ B, 21 } { A, 20 } { C, 22 }
{ B, 21 } { E, 23 } { A, 20 } { C, 22 }
The used indentation style makes it difficult to easily see if the parenthesis are correctly closed. Please use an automatic formatter, example: clang-format
Your function is not very safe. It should take another parameter max_size so the assigned memory is known
If a return is used in if branch, the else branch does not have to be explicitly declared.
A for loop already has a condition, if the only functionality in the loop is an if, it can be hoisted up into that condition.
To move students from a place in an array a "copy" of the student has to be made to the new location - not just it's index.
Fixed:
Student* insert(Student* array, int max_size, int* size, int index, Student s)
{
//error message and return NULL if space is - or > array size
if (index < 0 || index > *size || *size + 1 > max_size)
{
printf("ERROR\n");
array = NULL;
return array;
}
for (int i = *size; i > index && i > 0; --i)
{
//move students at index or > over to make open space
array[i] = array[i - 1];
}
//put new student in correct location
array[index] = s;
*size += 1;
return array;
}

odd or even number using pointer in C

I have an array, the elements inside this array should be assigned randomly
then I create two more arrays one for odd and one for even numbers
using pointers I want to put the odd numbers inside the odd array, and the even numbers in the even one.
how can I assign it using pointers?
I came up with this:
int main()
{
int array[10];
int *arrayPtr = &array;
int arrayEven[10];
int *pEven = &arrayEven;
int arrayOdd[10];
int * pOdd = &arrayOdd;
int i, j;
for(i=0; i<10; i++)
{
array[i] =rand()%100 ;
if(array[i] %2 ==0)
{
printf("%d\n", array[i]);
printf("Even number");
}
else
{
printf("%d\n", array[i]);
printf("Odd number");
}
}
These declarations of pointers
int *arrayPtr = &array;
int *pEven = &arrayEven;
int * pOdd = &arrayOdd;
are incorrect. The initializers have the type int( * )[10] according to the declarations of the arrays as for example of the variable array
int array[10];
while the declared pointers has incompatible type int *.
What you need is declarations like this
int *arrayPtr = array;
There is no great sense to define arrays of the same size as the source array because for example the source array can have no odd or even numbers. You should deal with arrays depending on the number of odd and even numbers in the source array. If your compiler supports variable length arrays then you can use them. Or you should dynamically allocate arrays.
Here is a demonstrative program that shows how the assignment can be done using variable length arrays and pointers.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void copy_if( const int a1[], size_t n, int *a2, int *a3, int predicate( int ) )
{
for ( const int *p = a1; p != a1 + n; ++p )
{
if ( predicate( *p ) )
{
*a2++ = *p;
}
else
{
*a3++ = *p;
}
}
}
size_t count_if( const int a[], size_t n, int predicate( int ) )
{
size_t cnt = 0;
for ( const int *p = a; p != a + n; ++p )
{
if ( predicate( *p ) ) ++cnt;
}
return cnt;
}
int is_even( int x )
{
return x % 2 == 0;
}
int main(void)
{
enum { N = 10 };
int a1[N];
srand( ( unsigned int )time( NULL ) );
for ( int *p = a1; p != a1 + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = a1; p != a1 + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
size_t cnt = count_if( a1, N, is_even );
if ( cnt != 0 && cnt != N )
{
int a2[cnt];
int a3[N-cnt];
copy_if( a1, N, a2, a3, is_even );
for ( const int *p = a2; p != a2 + cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = a3; p != a3 + N - cnt; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
}
return 0;
}
The program output might look like
6 3 3 8 3 0 5 5 3 2
6 8 0 2
3 3 3 5 5 3
If to use your straightforward approach then the program can look the following way
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(void)
{
enum { N = 10 };
int array[N];
int *arrayPtr = array;
srand( ( unsigned int )time( NULL ) );
for ( int *p = arrayPtr; p != arrayPtr + N; ++p )
{
*p = rand() % N;
}
for ( const int *p = arrayPtr; p != arrayPtr + N; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
int arrayEven[10];
int *pEven = arrayEven;
int arrayOdd[10];
int *pOdd = arrayOdd;
int *pEvenEnd = pEven;
int *pOddEnd = pOdd;
for ( const int *p = array; p != arrayPtr + N; ++p )
{
if ( *p % 2 == 0 )
{
*pEvenEnd++ = *p;
}
else
{
*pOddEnd++ = *p;
}
}
for ( const int *p = pEven; p != pEvenEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
for ( const int *p = pOdd; p != pOddEnd; ++p )
{
printf( "%d ", *p );
}
putchar( '\n' );
return 0;
}
Its output might look for example like
1 0 0 3 4 5 2 1 9 5
0 0 4 2
1 3 5 1 9 5
For it to work you need two additional coutner variables
int oddCount, evenCount;
these need to be initialized to be 0 (i.e. how many odd/even number you have inserted so far). Then while iterating your first array you increment the respective coutner if you encounter an even/odd number. Also you can just use these variables to know where you need to put the next even/odd number in their respective array.
You can use binary comparison since all odd finish by 1 in binary mode :
If( a & 1)
//Odd
Else
//Even

converted string failed to contain correct values of float

I am facing problem in converting float to char*.
I have written a function that will put integer part of float in string and then decimal values. I need it for two places of decimal. But something is horribly wrong. Either it ouputs integer value or just 1 place after decimal. Can someone please guide me?
Below is my attempt
void float_to_str(char *str, float f, char size)
{
char pos; // position in string
char len; // length of decimal part of result
char* curr; // temp holder for next digit
int value, i ; // decimal digit(s) to convert
float temp;
pos = 0; // initialize pos, just to be sure
value = ( int )f; // truncate the floating point number
snprintf( curr, sizeof(curr), "%d", value);
strncmp( str, curr, strlen( curr ) );
// now str array has the digits before the decimal
if (f < 0 ) // handle negative numbers
{
f *= -1;
value *= -1;
}
len = strlen( str );
pos = len; // position the pointer to the end of the integer part
str[pos++] = '.'; // add decimal point to string
f = f -( float ) value + 0.005;
printf( " the value of f = %f\n", f );
for( i = 0; i < size; ++i )
{
temp = f* 10;
value = ( int )temp ;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
}
str[ pos ] = '/0';
printf(" debug --> the string is %s \n", str ); // prints only 5 instead of 6455.56
}
int main()
{
float test = 555564.5555;
char arr[ 40 ];
memset(arr, 0, 40 );
FloatToStringNew( arr,test, 2 );
printf( " the float to string is %s", arr ); // OUT Put is 5 which is wrong
return 0;
}
The entire float_to_string can be reduced to (as suggested by BLUEPIXY):
void float_to_str(char *str, float f, char size)
{
sprintf(str, "%.*f", size, f);
}
However, if you are interested in the bug in your code, it is in the for loop:
for( i = 0; i < size; ++i )
{
temp = f* 10; // Value of f stays the same in every iteration
value = ( int )temp ;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
}
Fix:
for( i = 0; i < size; ++i )
{
f = f * 10; // Modify f each iteration
value = ( int )f;
snprintf( curr, sizeof(curr),"%d", value );
str[ pos++ ] = *curr;
f = f - (int)f; // Remove the integer part
}
Edit:
There are a couple of other stuff in the function that needs fixing:
strncmp should be strcpy
pos should be of type int or size_t
curr should be an array instead of a pointer.
The call from main should be to float_to_string, not FloatToStringNew
The compiler helped me locate them when I compiled with warnings (I used -Wall in gcc).

how to store o/p into a buffer,and then from buffer to file

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include<stdbool.h>
int compare (const void *a, const void * b){
return ( *(char *)a - *(char *)b ); }
// A utility function two swap two characters a and b
void swap (char* a, char* b)
{
char t = *a;
*a = *b;
*b = t; }
int findCeil (char str[], char first, int l, int h)
{
// initialize index of ceiling element
int ceilIndex = l;
int i;
// Now iterate through rest of the elements and find
// the smallest character greater than 'first'
for (i = l+1; i <= h; i++)
if (str[i] > first && str[i] < str[ceilIndex])
ceilIndex = i;
return ceilIndex;
}
// Print all permutations of str in sorted order
void sortedPermutations ( char str[] )
{
FILE *fp;
fp = fopen("out.txt","w+");
char buffer[100];
memset(buffer,'\0',100);
// Get size of string
int size = strlen(str);
// Sort the string in increasing order
qsort( str, size, sizeof( str[0] ), compare );
// Print permutations one by one
bool isFinished = false;
while ( ! isFinished )
{
// print this permutation
setvbuf(str, buffer, _IONBF, 1024);
printf ("%s \n", str);
fprintf(fp,"%s\n",buffer);
// Find the rightmost character which is smaller than its next
// character. Let us call it 'first char'
int i;
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1])
break;
// If there is no such chracter, all are sorted in decreasing order,
// means we just printed the last permutation and we are done.
if ( i == -1 )
isFinished = true;
else
{
// Find the ceil of 'first char' in right of first character.
// Ceil of a character is the smallest character greater than it
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
// Swap first and second characters
swap( &str[i], &str[ceilIndex] );
// Sort the string on right of 'first char'
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
fclose(fp);
}
}
int main()
{
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
Hi ,I am trying jumble solver .I want to store the result of permutation to a buffer and then from buffer to some file,so that I can compare it with dictionary. getting errors for setvbuf.
My C is very rusty,not able to get the desired results.
there are plenty of errors. First you use setvbuf with wrong arguments and do that in cycle. Then you fprintf buffer value instead of str. And also close file in cycle.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int compare (const void *a, const void * b) {
return ( *(char *)a - *(char *)b );
}
void swap (char* a, char* b) {
char t = *a;
*a = *b;
*b = t;
}
int findCeil (const char str[], char first, int l, int h) {
int ceilIndex = l;
int i;
for (i = l+1; i <= h; i++) {
if (str[i] > first && str[i] < str[ceilIndex]) {
ceilIndex = i;
}
}
return ceilIndex;
}
void sortedPermutations ( char str[] ) {
FILE *fp;
char buffer[1024];
int size = strlen(str);
int isFinished = 0;
fp = fopen("out.txt","w+");
memset(buffer, 0, 100);
qsort( str, size, sizeof( str[0] ), compare );
setvbuf(fp, buffer, _IOFBF, 1024);
while ( !isFinished ) {
int i;
printf("%s \n", str);
fprintf(fp, "%s\n", str);
for ( i = size - 2; i >= 0; --i )
if (str[i] < str[i+1]) {
break;
}
if ( i == -1 ) {
isFinished = 1;
} else {
int ceilIndex = findCeil( str, str[i], i + 1, size - 1 );
swap( &str[i], &str[ceilIndex] );
qsort( str + i + 1, size - i - 1, sizeof(str[0]), compare );
}
}
fclose(fp);
}
int main() {
char str[] = "ABCD";
sortedPermutations( str );
return 0;
}
setvbuf is used to set custom buffer. It is used, for example, to set big buffer and to have direct access to it. fprintf will print to file only when buffer is full, or when you flush, or close file. And you also use _IONBF which means that stream is not buffered at all.
So - it works only, because it is not buffered, as you send buffer [100], and then try to print 1024. So also change size of buffer to 1024 and use _IOFBF.

Resources