Walk-through of a simple c program - c

I have this question to walk through and show the output when this program is run. The one thing I don't understand is how f is found to be four or even found at all.I know the correct answer is
7 falcon 3
9 RK 4
_
I just dont know how they found the f value to be 4 ,once i have that I can do the rest fine
#include <stdio.h>
#include <string.h>
void falcon(int f);
char a[20];
int main() {
int i, j;
a[3] = 'G';
a[1] = 'K';
i = 3 + 2 * 3;
j = 4;
a[2] = 'Y';
falcon(j);
printf("%d %s %d\n", i, a, j);
}
void falcon(int f) {
int j;
j = 11 % f;
printf("%d falcon %d\n", f+3, j);
a[2] = '\0';
a[0] = 'R';
}

Let's walk through the program together (with some of the irrelevant bits cut out).
#include <stdio.h>
#include <string.h>
void falcon(int f);
char a[20];
int main() {
int i, j;
j = 4;
falcon(j); // in other words, falcon(4). Now, let's go down to the
// falcon function where the first argument is 4.
printf("%d %s %d\n", i, a, j);
}
void falcon(int f) { // Except here we see that in this function,
// the first argument is referred to by 'f',
// which, as we saw, is 4.
int j;
j = 11 % f; // here, j is equal to the remainder of 11 divided by
// f, which is 4.
printf("%d falcon %d\n", f+3, j);
}

Now you see why code should not have is and js for variable names except in probably, loops.
Anyways,
char a[20]; on the top says that a is a globally declared character array.
int main()
{
int i, j; // declares two local stack variables, i and j
a[3] = 'G'; // sets 4th location in 'a'(remember, arrays start at 0) to 'G'{useless}
a[1] = 'K'; // sets 2nd location in 'a' array to 'K'
i = 3 + 2 * 3; // i is now 9 {remember, multiplication before addition}
j = 4; // j is now 4
a[2] = 'Y'; // a[2] is now 'Y'
falcon(j); // call to falcon, with argument 4, explained next
printf("%d %s %d\n", i, a, j); // prints "9 RK 4"
//return 0; -- this should be added as part of 'good' practices
}
void falcon(int f)
{
// from main(), the value of 'f' is 4
int j; // declares a local variable called 'j'
j = 11 % f; // j = 11 % 4 = 3
printf("%d falcon %d\n", f+3, j); // prints 7 falcon 3
a[2] = '\0'; // a[2] contains null terminating character, overwrites 'Y'.
a[0] = 'R'; // sets a[0] to 'R'. At this moment, printf("%s",a); must yield "RK"
}

Related

Swapping sections of an array

I was asked to make a function that swaps two sections in array.
Something like this,
array[] = {1 , 2, 5, 7, 8, a , b, c}
| |
sections: First Second
The signature is void reverse_reg(int *arr, int s, int k, int j) where arr is the array, s is the first index of the first section, k is the last index of the first section and j denotes the end of the second section, the start is k ( since indexing in C start from 0 )
So far I have something something like this,
void reverse_reg(int *arr, int s, int k, int j)
{
for (int i = s; i < j; i++)
{
if (i > k / 2) /* swap the rest */
{
swap(&arr[i], &arr[j - i + 1]); /* this is wrong */
}
else
{
swap(&arr[i], &arr[k + i + 1]);
}
}
}
I have tested the else block and so far it swaps successfully the second section, producing,
result:
a b c 7 8 1 2 5
Though, I haven't been able to find a way to swap the second part, since the if block, produces something completely wrong (and it makes sense), which makes me think that the initial logic is wrong. Any hints?
If it helps, the way I call the function is, reverse_reg(arr, 0, 4, 8);
The resulting array should be:
result:
a b c 1 2 5 7 8
As pointed out by #EugeneSh., a simple way is to reverse each section and then reverse the whole array. It could be as simple as:
void swap(int* i, int* j) {
int k = *i;
*i = *j;
*j = k;
}
void reverse(int arr[], int len) {
for (int i = 0; i < len / 2; i++) {
swap(arr + i, arr + len - i - 1);
}
}
void reverse_reg(int* arr, int s, int k, int j) {
// you use last index of initial section while I need index of second one
++k;
reverse(arr + s, k - s);
reverse(arr + k, j - k);
reverse(arr + s, j - s);
}
"12578abc"
"abc12578"
Assuming array is declared as unsigned char array[8];, this can be a rotate operation on 64-bit integer. Using a rotate function, we can shift "abc" to the left, and "12578" to the right, then combine their result:
uint64_t rot_left_64(uint64_t num, int n)
{
return (num << n) | (num >> (64 - n));
}
uint64_t num = 0x01020507080a0b0c;
num = rot_left_64(num , 8 * 5);
printf("%016llX\n", n); //output 0x0A0B0C0102050708

Concatenating two integer arrays in C

I am trying to concatenate two integer arrays. This method works well for strings (char*), but for integer arrays the content of the second array is changed.
int main() {
int* a = malloc(8); // 2 integers
int* b = malloc(12); // 3 integers
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(20); // 5 integers
memcpy(c, a, 8);
memcpy(c+8, b, 12);
printf("%d\n", c[0]); // Excpected 1. Prints 1.
printf("%d\n", c[1]); // Excpected 2. Prints 2.
printf("%d\n", c[2]); // Excpected 3. Prints something random.
printf("%d\n", c[3]); // Excpected 4. Prints something random.
printf("%d\n", c[4]); // Excpected 5. Prints something random.
return 0;
}
Forget all about hard-coding variable sizes. That's the root of your problems and makes the code brittle.
The specific problem here though, is that c+8 does pointer arithmetic on an int*. So it means "go 8 int forward from c". Not 8 bytes - it is equivalent to &c[8], which is obviously wrong.
You should rewrite your code according to this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void) {
int* a = malloc(2*sizeof(int));
int* b = malloc(3*sizeof(int));
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(5*sizeof(int));
memcpy(c, a, 2*sizeof(int));
memcpy(c+2, b, 3*sizeof(int));
printf("%d\n", c[0]);
printf("%d\n", c[1]);
printf("%d\n", c[2]);
printf("%d\n", c[3]);
printf("%d\n", c[4]);
return 0;
}
An optional syntax for malloc is to do int* a = malloc(2 * sizeof(*a)), which is fine too, it's a matter of coding style preference.
Due to the pointer arithmetic in this call of memcpy
memcpy(c+8, b, 12);
there is specified an incorrect destination address.
You allocated an array for 5 elements (provided that sizeof( int ) is equal to 4)
int* c = malloc(20)
So due to the pointer arithmetic c + 0 is the address of the first element, c + 1 is the address of the second element, c + 2 is the address of the third element and so on.
As you are trying to fill the array starting from its third element then you have to write
memcpy(c+2, b, 12);
^^^^
It is the same as if to write
memcpy( &c[2], b, 12);
Also do not use magic numbers like 12 or 20. Take into account that sizeof( int ) is implementation defined. So it would be much better to write for example
int* c = malloc( 5 * sizeof( int ) );
or
memcpy( c + 2, b, 3 * sizeof( int ) ;
Your program could look the following way.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main( void )
{
size_t n1 = 2;
size_t n2 = 3;
int *a = malloc( n1 * sizeof( int ) );
int *b = malloc( n2 * sizeof( int ) );
int init_value = 1;
for ( size_t i = 0; i < n1; i++ )
{
a[i] = init_value++;
}
for ( size_t i = 0; i < n2; i++ )
{
b[i] = init_value++;
}
size_t n3 = n1 + n2;
int *c = malloc( n3 * sizeof( int ) );
memcpy( c, a, n1 * sizeof( int ) );
memcpy( c + n1, b, n2 * sizeof( int ) );
for ( size_t i = 0; i < n3; i++ )
{
printf("c[%zu]: %d\n", i, c[i] );
}
putchar( '\n' );
free( c );
free( b );
free( a );
return 0;
}
The program output is
c[0]: 1
c[1]: 2
c[2]: 3
c[3]: 4
c[4]: 5
You have to replace memcpy(c+8, b, 12); to memcpy(c+2, b, 12); because first argument of the memcpy function is mean The pointer to the destination array where the content is to be copied, type-casted to a pointer of type void.*
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int* a = malloc(8); // 2 integers
int* b = malloc(12); // 3 integers
a[0] = 1;
a[1] = 2;
b[0] = 3;
b[1] = 4;
b[2] = 5;
int* c = malloc(20); // 5 integers
memcpy(c, a, 8);
memcpy(c+2, b, 12);//
printf("%d\n", c[0]); // Excpected 1. Prints 1.
printf("%d\n", c[1]); // Excpected 2. Prints 2.
printf("%d\n", c[2]); // Excpected 3. Prints something random.
printf("%d\n", c[3]); // Excpected 4. Prints something random.
printf("%d\n", c[4]); // Excpected 5. Prints something random.
return 0;
}

How can I print the following 2D array?

#include <stdio.h>
#include <stdlib.h>
int ** letters (int*arr, int nr_elem)
{
char **mat=(char**)malloc( nr_elem * sizeof(char*));
int max =0;
for (int i =0; i<nr_elem;i++)
{
if( *(arr + i) > max)
max = *(arr + i);
}
for (int i=0; i<nr_elem; i++)
{
*mat=(char*)malloc((*(arr+i))*sizeof(char));
}
for(int i=0; i<nr_elem;i++)
{
for(int j=0; j<(*(arr+i)); j++)
{
mat[i][j] = 'a'+ (*(arr+i))-1;
printf("mat[%d][%d] = %c\n", i, j, mat[i][j]);
}
}
}
int main()
{
int a[] = {3, 4, 5, 2, 3};
int n = 5;
letters(a, n);
return 0;
}
My final goal is to make the function print a matrix with 5 rows on which it will print the corresponding letter from array a, that same amount of times. For example line 1, will have letter 'c' printed 3 times, line 2 will have 'd' printed 4 times etc.
For now I just want to print the matrix (i know the rest is not completely implemented, but I want to see what i have so far). it will show me that :
m[0][0] = 'c'
m[0][1] = 'c'
m[0][2] = 'c'
m[1][0] = 'd'
m[1][1] = 'd'
m[1][2] = 'd'
m[1][3] = 'd'
but then it cracks. Why?
You have an error in the second for loop inside your letters function, where you should be allocating a char* pointer to each element of mat:
for (int i=0; i<nr_elem; i++)
{
// *mat=(char*)malloc((*(arr+i))*sizeof(char)); // *mat keeps getting overwritten!
mat[i] = malloc((*(arr+i))*sizeof(char)); // Allocates new block for each loop
}
In your code, your only ever assign the return from malloc to the first element of the mat array - each loop just overwrites the previously assigned value (i.e. *mat is the same as mat[0]).
Also, please see this post on (not) casting the return value of malloc: Do I cast the result of malloc?

Print Array Pointer value in Reverse Order

I want to Print Pointer Array value in Reverse
#include <stdio.h>
#define size 5
int main()
{
int a[size] = {1,2,3,4,5};
int i;
int *pa = a;
for(i = size; i >0; i--)
{
printf("a[%d] = %d\n",i,*pa);
pa++;
}
return 0;
}
Output:
a[5] = 1
a[4] = 2
a[3] = 3
a[2] = 4
a[1] = 5
The output I want is:
a[5] = 5
a[4] = 4
a[3] = 3
a[2] = 2
a[1] = 1
replace with this
#include <stdio.h>
#define size 5
int main()
{
int a[size] = {1,2,3,4,5};
int i;
int *pa = (a+size-1);
for(i = size; i >0; i--)
{
printf("a[%d] = %d\n",i,*pa);
pa--;
}
return 0;
}
You're making this too hard. Given a pointer into an array, you can use the indexing operator on it just as you would on the array itself:
int a[size] = {1,2,3,4,5};
int i;
int *pa = a;
for (i = size - 1; i >= 0; i--) {
printf("a[%d] = %d\n", i, pa[i]);
}
Alternatively, if you want to avoid the indexing operator for some reason, then just start your pointer at one past the end ...
*pa = a + size;
... and decrement it as you proceed through the loop:
for (i = size - 1; i >= 0; i--) {
pa--;
printf("a[%d] = %d\n", i, *pa);
}
Do note, by the way, that array indexing in C starts at 0, as the example codes above properly account for.
You don't have to use pointer. A simpler implementation
#include <stdio.h>
#define size 5
int main()
{
int a[size] = {1,2,3,4,5};
for(int i = size-1; i >=0; i--)
printf("a[%d] = %d\n",i,a[i]);
return 0;
}

Converting a string into an array of characters

Am trying to convert user's input of at least 17 characters into an array. Say for example the user's input is 25281582252, by using x = arr[1] , 5 is assigned to variable x.
I've not had success yet. I get a "undefined reference to log10" with gcc on linux. Here is my code
#include <stdio.h>
#include <math.h>
int main(){
int x;
printf("enter x");
scanf("%d",x);
int numOfDigits = log10(x) + 1;
char* arr = calloc(numOfDigits, sizeof(char));
for(int i=0;i<numOfDigits;i++,x/=10){
arr[i] = x % 10;
}
printf("first num: %d",arr[0]);
return 0;
}
Thanks in advance
I get a "undefined reference to log10"
You need to link your program with the math library using -lm.
But this is just a start. Fix the following issues:
a) allocate extra character for null string terminator if you want your string to be properly terminated.
b) scanf("%d",x); requires pointer to x
c) int variable cannot store 17 numbers, use long int
d) you cannot store int into char array, your digit has to be converted to ASCII char.
f) your algorithm stores characters in a reverse order, you need to reverse your string
e) allocated memory has to be freed.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void reverse_in_place(char * str, size_t len) {
size_t i, j;
for (i = 0, j = len - 1; i < j ; i++, j--) {
char a = str[i];
char z = str[j];
str[i] = z;
str[j] = a;
}
}
int main(void){
long int x;
int i;
printf("enter x:\n");
scanf("%ld",&x);
int numOfDigits = (int) (log10(x) + 1);
printf("numOfDigits = %d\n", numOfDigits);
char* arr = calloc(numOfDigits + 1, 1);
for(i=0; i < numOfDigits; i++){
arr[i] = (char) ((x % 10) + '0');
printf(" %c", arr[i]);
x /= 10;
}
reverse_in_place(arr,strlen(arr));
printf("\nFirst num is: %c in string %s",arr[0], arr);
free(arr);
return 0;
}
Output:
enter x:
451236789012345678
numOfDigits = 18
8 7 6 5 4 3 2 1 0 9 8 7 6 3 2 1 5 4
First num is: 4 in string 451236789012345678

Resources