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
Related
I am new to pointers so I tried inventing this simple problem. why is it not working? other than saying what mistake I made I'd greatly appreciate if you guys could tell me an alternative to this method
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]) {
int *p;
int i, j;
i = 0;
p = (int *)malloc(sizeof(int) * (i + 1));
scanf("%d", p);
do {
i++;
p = realloc(p, sizeof(int) * i);
scanf("%d", (p + i));
} while (*(p + i) > 0);
for (j = 0; j < i; j++) {
printf("%d\n", *(p + j));
}
free(p);
return 0;
}
This statement
p=(int *)malloc(sizeof(int) * (i+1));
is redundant. It is better to write
p = NULL;
And in a call of scanf use an object of the type int not the pointer.
There can be redundant memory allocation if for example the first entered value will be negative
In this call
scanf("%d", (p+i));
there is an access beyond the allocated memory. You should at least write
scanf("%d", (p + i -1));
It is better to specify an intermediate pointer in this statement
p=realloc(p,sizeof(int)*i);
because the function can return NULL. In this case the address of the previously allocated memory will be lost.
And the condition in the loop
}while(*(p+i)>0);
does not check that the value is not negative.
The program can look the following way
#include <stdio.h>
#include <stdlib.h>
int main( void )
{
int *p = NULL;
size_t n = 0;
int value;
for ( int *tmp;
scanf( "%d", &value ) == 1 &&
!( value < 0 ) &&
( tmp = realloc( p, ( n + 1 ) * sizeof( int ) ) ) != NULL;
++n )
{
p = tmp;
*( p + n ) = value;
}
for ( size_t i = 0; i < n; i++ )
{
printf( "%d ", *( p + i ) );
}
putchar( '\n' );
free( p );
return 0;
}
If to enter
0 1 2 3 4 5 6 7 8 9 -1
the program output will be
0 1 2 3 4 5 6 7 8 9
To put it bluntly, as it stands, I am not very good at coding at this current time. I am really trying to get these functions completed, I am just having trouble with the execution on some of them.
Basically, there are 10 functions ( 6 of which I have finished? ) that need to be created.
There is an int main() but, besides a string that needs to be fixed, the int main() does not need to be touched.
I will post the program (mostly so you can see my work) in addition to the int main() so that if someone wants to check the intent, they can see it. Even though I have posted the whole program, the only ones that I really want to focus on are the makeUpper, and the functions that have nothing in them because I really don't understand how to copy and edit a string into another array.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
void makeUpper( char orig[], char result[] )
{
/*
int i = 0;
while ( str[i] != '\0' )
{
if ( str[i] >= 'a' && str[i] <= 'z' )
str[i] = str[i] - 32;
k++;
}
*/
}
int countDigit( char str[] )
{
int i;
int count = 0;
int len;
len = strlen(str);
for ( i = 0; i < len; i++ )
{
if ( i >= '0' && i <= '9' )
count++;
}
return count;
}
int onlyLetters( char orig[], char letters[] )
{
}
int countOdd( int A[], int N )
{
int i;
int odd = 0;
for ( i = 0; i < N; i++ );
{
if ( A[i] % 2 != 0 )
odd++;
}
return odd;
}
int sumList( int A[], int N )
{
int i;
int sum = 0;
for ( i = 0; i < N; i++ );
sum = sum + A[i];
return sum;
}
void addToEach( int A[], int N, int val )
{
int i;
for ( i = 0; i < N; i++ )
A[i] + val;
printf("%d", A[i]);
}
void copyNumList( int orig[], int N, int result[] )
{
}
// populate list A with N items, random in range L to H
void fillNumList( int A[], int N, int L, int H )
{
}
// print the list, 10 items per line
void printList( int A[], int N )
{
int i;
for ( i = 0; i < N; i++ )
printf("%d ", A[i]);
printf("\n");
}
void rept( int n, char c )
{
int i;
for ( i = 0; i < n; i++ )
printf("%c", c);
printf("\n");
}
int main()
{
char line[100], other[100];
int i, len;
printf("Phrase: ");
fgets( line, 100, stdin );
// fix the string....
// ...
// really, do this
// ...
rept(10,'-');
printf("Orig: ##%s##\n", line);
rept(10,'-');
makeUpper( line, other );
printf("toupper: %s\n", other);
rept(10,'-');
i = countDigit( line );
printf("%d digits\n", i);
rept(10,'-');
len = onlyLetters( line, other );
printf("only letters: %s\n", other );
printf(" new len %d\n", len);
int nums[30], vals[30];
int many = 19;
rept(5, '-');
fillNumList( nums, many, 3, 11 );
printList( nums, many );
rept(5, '-');
i = countOdd( nums, many );
printf("%d odd values\n", i);
rept(5, '-');
i = sumList( nums, many );
printf("%d is sum\n", i);
rept(5, '-');
copyNumList( nums, many, vals );
printf("Copy\n");
printList( vals, many );
rept(5, '-');
addToEach( vals, many, 4 );
printf("Add 4\n");
printList( vals, many );
rept(5, '-');
printf("Orig\n");
printList( nums, many );
rept(5, '-');
return 0;
}
To answer the one almost-well-defined question (regarding makeUpper):
First, str is not a variable. You have orig and result, and haven't declared str anywhere.
Now, if str were orig, you'd be correctly uppercasing the characters in the original string. However, the task is to leave the original string alone and make an uppercased copy. The former is called "destructive operation" (as the original contents are not preserved); the latter, a "non-destructive operation" (for obvious reasons). Here are the changes needed to make your function non-destructive:
void makeUpper( char orig[], char result[] )
{
int k = 0;
do
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
} while ( orig[k++] != '\0' );
}
Notice that I iterate and test on orig, but assign to result.
onlyLetters should be similar; but you will need two index variables, not just k, since you will want to progress through orig and result at different pace (you'll only want to copy a character when it's a letter, and you'll only want to progress through result when you do a copy - as opposed to orig, which you'll always consume one character per loop).
As you have not stated what your misunderstanding is about copyNumList and fillNumList, I cannot give you any help there.
EDIT: I forgot about the terminator (and didn't test it); thanks Tom Karzes! Because the zero also needs to be copied, your loop is changed from while (condition) { ... } to do { ... } while (condition) - instead of testing whether we're at end and then doing things if we're not, we'll do the thing first, and only afterwards ask if we're done. This also requires the increment to be done after the test, so k++ got moved. If this is too weird for you, you can get the same effect like this, by explicitly adding the terminator after the loop is done:
void makeUpper( char orig[], char result[] )
{
int k = 0;
while ( orig[k] != '\0' )
{
if ( orig[k] >= 'a' && orig[k] <= 'z' )
result[k] = orig[k] - 32;
else
result[k] = orig[k];
k++;
}
result[k] = '\0';
}
I have an array of char pointers (string array), which contains some duplicate values. I've found an algorithm that truncates the array by removing its duplicate values.
Here is a code sample :
int i, j , k;
int n = 10;
char *teams[n];
for(i=0;i<n;i++){
for(j=i+1;j<n;){
if(*(team[j]==*(team[i])){
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
n--;
}else{
j++;
}
}
}
I've read that the only way to copy strings between string arrays is to use strcpy(s1, s2). But in my case I can't use it, because strcpy function permits to copy s2 into s1 only if s2 has a lenght equal or bigger than the lenght of s1. So how can I implement this algorithm if I can't put the string pointed by the pointer team[k+1] in team[k] ?
It seems you need to remove duplicated string representations instead of duplicated addresses to strings.
If so then this if statement (if to add missed closed parenthesis)
if( *(team[j] ) ==*( team[i] ) ){
compares only first characters of strings instead of comparing strings pointed to by the pointers.
In this loop
for(k=j;k<n;k++){
//strcpy(team[k], team[k+1]);
team[k] = team[k+1];
}
each time when a duplicates string is found there is copied the whole array of pointers. Moreover there is an attempt to access memory beyond the array in this statement when k is equal to n-1
team[k] = team[k+1];
^^^^
You can write a separate function that will "remove" duplicates. The function can for example return pointer after the last unique element in the modified array.
#include <stdio.h>
#include <string.h>
char ** unique( char *s[], size_t n )
{
size_t i = 0;
for ( size_t j = 0; j < n; j++ )
{
size_t k = 0;
while ( k < i && strcmp( s[k], s[j] ) != 0 ) ++k;
if ( k == i )
{
if ( i != j ) s[i] = s[j];
++i;
}
}
return s + i;
}
int main(void)
{
char * s[] = { "A", "B", "A", "C", "A" };
const size_t N = sizeof( s ) / sizeof( *s );
for ( size_t i = 0; i < N; i++ ) printf( "%s ", s[i] );
printf( "\n" );
char **p = unique( s, N );
size_t n = p - s;
for ( size_t i = 0; i < n; i++ ) printf( "%s ", s[i] );
printf( "\n" );
return 0;
}
The program output is
A B A C A
A B C
#include <stdio.h>
#include <string.h>
unsigned dedup(char **arr, unsigned count)
{
unsigned this, that ;
for(this=0;this<count;this++){
for(that=this+1;that<count;){
if( strcmp(arr[that], arr[this])) {that++; continue; }
#if PRESERVE_ORDER
memmove(arr+that, arr+that+1, (--count - that) * sizeof arr[that] );
#else
arr[that] = arr[--count];
#endif
}
}
return count; /* the count after deduplication */
}
char *array[] = { "one", "two", "three", "two", "one", "four", "five", "two" };
int main(void)
{
unsigned count, index;
count = dedup(array, 8);
for (index = 0; index < count; index++) {
printf("%s\n", array[index] );
}
return 0;
}
[UPDATED]: I added the PRESERVE_ORDER version
I would to extend the array until the program receive "-1" as input. Every time I extend by 1 the current array but after 7 input I have "invalid next size:0x0000000000d47010"
void extend(int *v, int i)
{
int *p;
p= (int *) realloc(v, (i+1)*sizeof(int));
if(p!=NULL)
v=p;
}
int main()
{
int *v;
v= malloc(sizeof(int));
int n=0;
int i=0;
while(n!=-1)
{
scanf("%d", &n);
v[i]=n;
extend(v,i);
i++;
}
return 0;
}
EDIT
possible solution that made this working
void extend(int *v, int i)
{
int *p;
p= (int *) realloc(v, (i+1)*sizeof(int));
if(p!=NULL)
v=p;
}
int main()
{
int *v;
v= malloc(sizeof(int));
int n=0;
int i=0;
while(n!=-1)
{
scanf("%d", &n);
if(n!=-1)
{
extend(v,i);
v[i]=n;
i++;
}
}
prodottoScalare(v, i);
return 0;
}
Function parameters are its local variables. So in the function extend in this statement
v=p;
there is assigned local variable v that is destroyed after exiting the function. The original pointer itself used as the argument will not be changed.
You need to pass the original pointer to the function by reference.
Also the logic of this while loop
while(n!=-1)
{
scanf("%d", &n);
v[i]=n;
extend(v,i);
i++;
}
is incorrect. The entered value by the scanf can be equal to -1 or the end of the stream can be encountered. Nevertheless the array is extended.
Also you should free all allocated memory.
Take into account that in C main without parameters should be declared like
int main( void )
The program can look the following way
#include <stdlib.h>
#include <stdio.h>
size_t extend( int **a, size_t n, int value )
{
int *p = realloc( *a, ( n + 1 ) * sizeof( int ) );
if ( p != NULL )
{
*a = p;
( *a )[n++] = value;
}
return n;
}
int main( void )
{
int *a = NULL;
size_t n = 0;
int value;
while( scanf( "%d", &value ) == 1 && value != -1 )
{
n = extend( &a, n, value );
}
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
printf( "\n" );
free( a );
return 0;
}
If to enter
0 1 2 3 4 5 6 7 8 9 -1
then the program output will look like
1 2 3 4 5 6 7 8 9
Another function's implementation can look like
#include <stdlib.h>
#include <stdio.h>
_Bool /* or int */ extend( int **a, size_t n )
{
int *p = realloc( *a, ( n + 1 ) * sizeof( int ) );
_Bool /* or int */ success = p != NULL;
if ( success ) *a = p;
return success;
}
int main( void )
{
int *a = NULL;
size_t n = 0;
int value;
while( scanf( "%d", &value ) == 1 && value != -1 )
{
if ( extend( &a, n ) ) a[n++] = value;
}
for ( size_t i = 0; i < n; i++ ) printf( "%d ", a[i] );
printf( "\n" );
free( a );
return 0;
}
The result will be the same as in the first demonstrative program for the same input.
Notice that the pointer v int *vof the function extend is passed by value, assignment statement v=p would not change the value passed to function extend. So, argument passed by reference here for int *v:
void extend(int *&v, int i)
{
int *p;
p= (int *) realloc(v, (i+1)*sizeof(int));
if(p!=NULL)
v=p;
}
int main()
{
int *v;
v= malloc(sizeof(int));
int n=0;
int i=0;
while(n!=-1)
{
scanf("%d", &n);
v[i]=n;
extend(v,i);
i++;
}
return 0;
}
I have a code like this:
char* s[4][10] = { "abc\0", "aab\0", "cbb\0" };
a want to type a character, like.. 'a', and iterate through the array of strings, check on each string if there's 'a' on it, and then count how many there's on it..
In this case, what I wanted to get is "abc" : 1, "aab" : 2, "cbb" : 0 ...
how can I do the loops to get this result?
char input = '\0';
scanf("%c", &input);
int i, j;
for(i=0; i<4; i++)
{
int count = 0;
for(j=0;j<10;j++)
{
if(s[i][j] == input) count++;
}
printf("%s : %d", s[i], count);
}
although please note, that simply copying and pasting will not teach you anything.
Here is a demonstrative program that shows how you can deal with different declarations of arrays
#include <stdio.h>
int main(void)
{
char* s[4][10] = { { "abc", "aab", "cbb" } };
for ( int i = 0; i < 4; i++ )
{
for ( int j = 0; j < 10; j++ )
{
if ( s[i][j] )
{
size_t count = 0;
for ( char *p = s[i][j]; *p != '\0'; ++p )
{
if ( *p == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", s[i][j], count );
}
}
}
printf( "\n" );
char* t[4] = { "abc", "aab", "cbb" };
for ( char **p = t; *p != NULL; ++p )
{
size_t count = 0;
for ( char *q = *p; *q != '\0'; ++q )
{
if ( *q == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", *p, count );
}
printf( "\n" );
char u[4][10] = { "abc", "aab", "cbb" };
for ( int i = 0; i < 4; i++ )
{
if ( u[i][0] != '\0' )
{
size_t count = 0;
for ( char *p = u[i]; *p != '\0'; ++p )
{
if ( *p == 'a' ) ++count;
}
printf( "\"%s\": %zu\n", u[i], count );
}
}
return 0;
}
The program output is
"abc": 1
"aab": 2
"cbb": 0
"abc": 1
"aab": 2
"cbb": 0
"abc": 1
"aab": 2
"cbb": 0
It seems that you mean either the second variant of the array declaration or the third variant of the array declaration. The first variant looks strange.:)
Take into account that string literals already contain terminating zero. So there is no sense to write, for example
"abc\0"
It is enough to write simply
"abc"
The sizeof( "abc" ) is equal to 4 due to the presence of the terminating zero.
#include <stddef.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char s[10][4] = { "abc", "aab", "cbb" };
size_t i;
for (i = 0; i != sizeof(s) / sizeof(s[0]); i++) {
fprintf(stdout, "%zu: %s\n", i, s[i]);
}
return 0;
}
or
#include <stddef.h>
#include <stdio.h>
int main(int argc, char *argv[]) {
char *s[4] = { "abc", "aab", "cbb" };
size_t i;
for (i = 0; i != 3; i++) {
fprintf(stdout, "%zu: %s\n", i, s[i]);
}
return 0;
}
Note that the original declaration
char* s[4][10] = { "abc\0", "aab\0", "cbb\0" };
had several errors:
char * instead of char
[4][10] instead of [10][4]
"abc\0" instead of "abc" (the trailing '\0' is implicit).