Swapping elements in Array of Pointers - arrays

I have the following array in C (Used random names)
char * inputs[6] = {
"Kangaroo my shoe", "Fly high dragonfly",
"Philosophical Monkey", "Jumping Ape",
"Fearful lemurs", "Tall Giraffes"
};
The goal is to swap the first element by the next. As in to do this
char * inputs[6] = {
"Fly high dragonfly", "Kangaroo my shoe",
"Jumping Ape", "Philosophical Monkey",
"Tall Giraffes", "Fearful lemurs"
};
I have tried the following and some more.
ArrSwap(char *Arr[]){
int i;
for(i=0;i<6;i++){
void*temp = Arr[i];
Arr[i]=Arr[i+1];
Arr[i+1] = temp;
}
}
Thanks in advance! I've spent some hours trying to figure this out, each time I do it it ends up with a messed up order or not swapping any elements expect for the first and last.

There are two problems in your code -
In function ArrSwap() you are looping over index 0 to 5. So, when i becomes 5, Arr[i+1] points to Arr[6] which leads to read from a memory past your array bounds. Which is undefined behavior.
Secondly, if I get your requirement correctly, you want to swap the first and second elements swapped, then third and fourth and so on. So, your code has a logic error. In that case, in ArrSwap() the loop needs to increment by 2 instead of 1.
So the code may look like this after both issues are addressed -
void ArrSwap(char *Arr[]){
int i;
for(i=0; i<5; i+=2) {
char *temp = Arr[i];
Arr[i]=Arr[i+1];
Arr[i+1] = temp;
}
}
Notice there are following changes done in the ArrSwap() function -
The loop test condition changed from i < 6 to i < 5 (the reason mentioned in point 1 above). As ikegami mentioned, best practice would be to pass the array size as an argument (say n) and use n - 1 in loop condition.
The logic is fixed (as mentioned in point 2 above)
For swap, use char * instead of void * (The type of elements in Arr is char *)
The return type of ArrSwap() is mentioned as void. With void it is clearly conveyed that ArrSwap() will not return anything.
After fix the inputs will be:
{"Fly high dragonfly", "Kangaroo my shoe", "Jumping Ape", "Philosophical Monkey", "Tall Giraffes", "Fearful lemurs"}

Related

code with array subscript references and pointer dereferencing compiles and runs but the results are unexpected

Why this program can compiling and run but the result is out of my expectation?`
#include<stdio.h>
int main(void)
{
char *message="hello";
for(int i=0;*message!='\0';i++)
{
printf("%c",message[i]);
}
return 0;
}
But this one can meet my expection.(print "hello" rightly)
int main(void)
{
char *message="hello";
for(int i=0;*message!='\0';i++)
{
printf("%c",*message++);
}
return 0;
}
In the C language,arr[i] is equal to *arr.But in the cases I show above,the result is totally different,when I run them in the devc++.Due to my limited knowledge ,I can't understand this.
Because I'm a student who is going to be a freshman after this summer vacation and only have some konwledge about C language,please answer my question in a more acceptable way. Thanks in advance!
***sorry ,the problem is caused because of my carelessness.I have learned my mistake.
In the C language, arr[i] is equal to *arr....
No, *arr is equal to arr[0].
In your first example, you type message++ which make et points on the next character.
So, the first code can be corrected that way:
for(int i=0; message[i]!='\0'; i++)
{
printf("%c",message[i]);
}
And the second can be simplified: (you don't need i):
for( ;*message!='\0'; )
{
printf("%c",*message++);
}
In the first code, the pointer message isn't changed and what the pointer message points at is also not changed, so the condition *message!='\0' is always true (doing 'h'!='\0').
Therefore, i will continuously be incremented and become so large that message[i] goes out of a region where access is allowed.
The condition should be message[i]!='\0' to avoid this error.
If you want to stick to use * operator for some reason, it should be *(message+i)!='\0'.
I rewrite the program with a slightly different appearance
#include<stdio.h>
int main(void)
{
char *message="hello";
for(int i=0; 'h'!='\0';i++) // notice the change here
{
printf("%c",message[i]);
}
return 0;
}
You see the problem now?
*message is always h, it's not changing with the loop iteration. The comparison is meaningless here, it does not terminate the loop as expected.
You need to ensure that you change the pointer to the next address every time you iterate, to ensure you are checking the value of the next element.
You can make use of the index value, like
for(int i=0; * (message + i) !='\0';i++)

array of pointer game not sure how to move pointers to back

there is a game that this program needs to play X-boom its supposed to take out the x player each turn and put it in the back of the array and then shorten the array so its no longer a part of it in that function. for example
player 1 2 3 4 and the x for the game is 3
players remaining: 1 2 4
players remaining: 1 4
players remaining: 1
i made this code that i think should do it but im not sure why its not working properly
i have a photo to how the output is supposed to look like but i dont know how to share it here if any one knows please tell me in the comments
my problem is mostly with the play function notice that is number 3 in the array was kicked you are supposed to keep on playing from number 3 just that there will be a new pointer there
i tried to solve this be just going to the one that needed to be kicked and doing a swap for it to go back while moving everyone else forward and then shortening the array by 1
in the end the main function will print the array and it needs to be in order that the first player to be kicked will be last in the array
void get_boom_number(int * i){
printf("enter the boom number\n");
scanf("%d",i);
return ;
}
#define LENGTH 31
void play(char * players[],int length,int boomnum){
int count=-1;
count = (count+boomnum-1)%(length);
char * temp;
for (int i = 0; i<30; i++) {
printf("%d\n",count);
for (int start=count; start<length-1; start++) {
temp=*(players+start);
*(players+start)=*(players+start+1);
*(players+start+1)=temp;
}
count=(count+boomnum-1)%(length);
length=length-1;
}
return ;
}
int main()
{
char * players[LENGTH]={"Tyrion Lannister","Daenerys Targaryen","Jon Snow","Arya Stark","Theon Greyjoy", "Joffrey Baratheon","Khal Drogo","Ted Mosby","Marshall Eriksen","Robin Scherbatsky","Barney Stinson", "Lily Aldrin", "Tracy McConnell", "Ted Mosby", "Leonard Hofstadter","Sheldon Cooper", "Penny", "Howard Wolowitz", "Raj Koothrappali", "Bernadette Rostenkowski-Wolowitz","Amy Farrah Fowler", "Gregory House", "Lisa Cuddy", "James Wilson","Eric Foreman", "Allison Cameron", "Robert Chase" ,"Lawrence Kutner", "Chris Taub","Remy 13 Hadley", "Amber Volakis"};
int boom_number, i;
get_boom_number(&boom_number);
play(players,LENGTH,boom_number);
and then just printing the array also we are not alowed to use "[]" for the hole thing.
A problem with your code is that count will become negative if the boomnum number is e.g. 1. I don't understand why count is initialized to -1 and why you subtract 1 more when recalculating count. Your code is the same as:
int count = (boomnum-2)%(length);
Again, it seems strange to subtract 2. Anyway, you must check that the result isn't negative.
Another problem is this:
count=(count+boomnum-1)%(length);
length=length-1;
This can cause count to be equal to length in the next iteration. I guess that's not what you want. You need to swap the two lines to avoid that. Like:
length=length-1;
count=(count+boomnum-1)%(length);
Doing that and input 2 for boom_number leads to the result:
Remy 13 Hadley
(Strange name by the way).
I would also change:
for (int i = 0; i<30; i++) {
to
while(length > 1) {
It's a bad idea to hard code the number of loops.
Further, this line:
count=(count+boomnum-1)%(length);
is also a problem. If boomnum is zero it may again cause count to become negative.

Trying to make a function which squares all values in an array. Getting strange number on the last value

int squaring_function (int *array, int i);
int main()
{
int array[5];
int i;
for(i=0; (i <= 5) ; i++)
{
array[i] = i;
printf("\nArray value %d is %d",i,array[i]);
}
for(i=0; (i <= 5) ; i++)
{
array[i] = (squaring_function(array, i));
printf("\nSquared array value %d is %d",i,array[i]);
}
return 0;
}
int squaring_function (int *array, int i)
{
return pow((array[i]),2);
}
I'm trying to use this squaring_function to square each value in turn in my array (containing integers 0 to 5). It seems to work however the last value (which should be 5)^2 is not coming up as 25. cmd window
I have tried reducing the array size to 5 (so the last value is 4) however this prints an incorrect number also.
I'm quite new to C and don't understand why this last value is failing.
I'm aware I could do this without a separate function however I'd quite like to learn why this isn't working.
Any help would be much appreciated.
Thanks,
Dan.
There are 2 bugs in your code. First is that you're accessing array out of bounds. The memory rule is that with n elements the indices must be smaller than n, hence < 5, not <= 5. And if you want to count up to 5, then you must declare
int array[6];
The other problem is that your code calculates pow(5, 2) as 24.99999999 which gets truncated to 24. The number 24 went to the memory location immediately after array overwriting i; which then lead to array[i] evaluating to array[24] which happened to be all zeroes.
Use array[i] * array[i] instead of pow to ensure that the calculation is done with integers.
The code
int array[5];
for(int i=0; (i <= 5) ; i++)
exceeds array bounds and introduces undefined behaviour. Note that 0..5 are actually 6 values, not 5. If you though see some "meaningful" output, well - good or bad luck - it's just the result of undefined behaviour, which can be everything (including sometimes meaningful values).
Your array isn't big enough to hold all the values.
An array of size 5 has indexes from 0 - 4. So array[5] is off the end of the array. Reading or writing past the end of an array invokes undefined behavior.
Increase the size of the array to 6 to fit the values you want.
int array[6];
The other answers show the flaws in the posted code.
If your goal is to square each element of an array, you can either write a function which square a value
void square(int *x)
{
*x *= *x;
}
and apply it to every element of an array or write a function which takes an entire array as an input and perform that transformation:
void square_array(int size, int arr[size])
{
for (int i = 0; i < size; ++i)
{
arr[i] *= arr[i];
}
}
// ... where given an array like
int nums[5] = {1, 2, 3, 4, 5};
// you can call it like this
square_array(5, nums); // -> {1, 4, 9, 16, 25}

Trying to print form array or array addresses...not getting it?

new here, trying to learn a piece of C with the great help of you guys, this could be a basic questions here....sorry you have start from basic.
void main()
{
char* arr[3] = {"baba","tata","kaka"};
char* arr1[3] = {"baba1","tata1","kaka1"};
char* arr2[3] = {"baba2","tata2","kaka2"};
char** array_all[] = {arr,arr1,arr2};
printf("%s\n",*array_all[0]);
//please guide me how to access individual entity(as arr[1], arr1[2],arr3[1]) //from each array using array_all
}
I'm not sure if this is exactly what you were looking for.. but this is what I understand so far.
You are wanting to access the individual elements of array_all (the elements arr, arr1 and arr2)? If so then all you do is...
array_all[0][i];
Where i is the element that you want to access.
The reason for this is because the index operators ([ and ]) actually dereferences a pointer and offsets the pointer (as in adds it by some integer, i.e. you move down in memory) that you specify. I recommend reading up on pointer arithmetic if you have no clue what happens if you add a pointer by some integer.
For example:
int x[] = { 1, 2, 3 };
// writing x[i] is the same as *(x + i)
int i = 2; // the element you wish to access
*(x + i) = 4; // set the ith (3rd) element to 4
*(x + 1) = 43; // set the 2nd element to 43
// Therefore...
// x now stores these elements:
// 1, 43, 4
// proof: print out all the elements in the array
for(int i = 0; i < 3; ++i)
{
printf("x[%i]=%i\n", i, x[i]);
}
Also, writing x[0] is the same as writing *x, since the array name actually points to the first element of the array.
OH and one thing, main should actually return an integer result. This is mainly used for error checking in your program, 0 usually means no error occurred and every other error-code (number other than 0) is some specific error related to your program, that you can choose.
i.e.
int main()
{
// e.g. for an error code
/*
if(someErrorOccured)
{
return SOME_ERROR_OCCURED_RETURN_VALUE;
}
*/
return 0; // this is at the end of the function, 0 means no error occured
}
change your printf statement line with this..
printf("%s\n",array_all[i][j]);
In place of i keep your array number and in place of k give your required element number. It works.

Trying to find numbers repeated in two arrays

I am trying to find all of the numbers that are repeated across two arrays..
For example:
array1[2]: 1,2
array2[2]: 1,5
The number that repeats itself is 1 so we create a new array that will contain 1.
array3[2]: 1
My code is:
int func1(int *str, int *str2)
{
int i,j,temp,c[10];
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
if(*(str+i) == *(str+j))
{
temp = *(str+i);
*(str+i) = temp;
temp = *(c+i);
return c[i];
}
}
}
return 0;
}
What is the problem?(logically)
Thanks.
There are multiple problems:
The conditions in the two for loops are odd and probably wrong. They are equivalent to:
for (i = 0; i < str1[i]; i++)
for (j = 0; j < str2[j]; j++)
You should probably specify the sizes of the input arrays in the function interface.
In C, you must make sure you always know the sizes of the arrays.
You should probably specify the output array in the function interface.
Since you will need to know how many values were found in common, you'll need to return that number from the function.
Your choice of the names str1 and str2 is unusual. Not technically wrong, but probably not a good idea. Such names should be reserved for character strings, not arrays of integers.
Your local array c is barely used, and is not used safely.
Your code returns when it finds the first pair of numbers that match, not all possible matches.
The first two lines of the body of the if statement elaborately copies the value in str[i] back to itself via temp.
The third line of the body of the if statement copies an uninitialized value from array c into the variable temp.
The last line of the body of the if then returns that uninitialized value.
This adds up to changes such as:
int func1(int *arr1, int num1, int *arr2, int num2, int *arr3)
{
int k = 0;
for (int i = 0; i < num1; i++)
{
for (int j = 0; j < num2; j++)
{
if (arr1[i] == arr2[j])
arr3[k++] = arr1[i];
}
}
return k;
}
Note that this code assumes that the size of arr3 (the array, not the pointer itself) is as big as the product of num1 and num2. If both arrays contain a list of the same value, then there will be one row in the output array, arr3, for each pair so it could use num1 * num2 rows. This points out that the code does not deal with suppressing duplicates; if you need that (you likely do), then the body of the if statement needs to search through the current values in arr3 to check that the new value is not present. It would be wise to add another parameter, int siz3, to indicate the size of the third array; if you run out of space for values, you could then return -1 as an error indication.
The coded algorithm is quadratic (or, more accurately, proportional to the product num1 * num2). If you know the arrays are sorted on entry, you can reduce it to a linear algorithm (proportional to num1 + num2). With duplicate elimination, it is a little more expensive - it isn't quite as simple as 'cubic'. If you know the input arrays contain unique values (no duplicates), then duplicate elimination is obviously not necessary.
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
Are wrong. You are applying '<' condition on an integer to itself and hence loop condition breaks. So, the loop never runs.
And why are you using these redundant statements?
temp = *(str+i);
*(str+i) = temp;
Also, this is wrong
temp = *(c+i);
return c[i];
Try more to correct those statements.If you can't do again, I will provide you a solution

Resources