#include <stdio.h>
#include <stdlib.h>
int* removeNegatives(int *v, int *totv){
int i, j, aux=(*totv), t=0;
for(i=0; i<aux; i++){
if(v[i]<0){
t=v[i];
for(j=i; j<=aux; j++){
v[j]=v[j+1];
}
v[(*totv)-1]=t;
aux--;
i=-1;
}
else{
continue;
}
}
totv=&aux;
v=(int*)realloc(v,(*totv)*sizeof(int));
return(v);
}
int main(){
int *totv=NULL, *v=NULL, *z=NULL, i, j=0, a;
printf("How many numbers are you entering?\n");
scanf("%d",&i);
printf("Enter them, then:\n");
totv=&i;
do{
if(j<(*totv)){
scanf("%d",&a);
v=(int*)realloc(v,++j*sizeof(int));
v[j-1]=a;
}
}while(j<(*totv));
printf("\n");
printf("Size before: %d\n",*totv);
z=retiraNegativos(v,totv);
printf("Size after: %d\n",*totv);
printf("\n");
printf("[ ");
for(i=0; i<(*totv); i++){
printf("%d ",z[i]);
}
printf("]");
printf("\n");
free(z);
return(0);
}
I'm resizing the vector "v" according to the number of negative numbers the user has entered.
But the problem is that the pointer "totv" is not updating after I call the fucntion "removeNegatives".
Your help is greatly appreciated!
This may look unrelated to your question, but it isn't.
Consider this:
int foo(int bar)
{
bar = 123;
}
...
int x = 1;
foo(x);
// What's the value of x here?
...
Will x be updated after the call to foo?
Problem is here:
totv=&aux;
You assign your local copy of some pointer to a new address. This does not have any visible effect outside your function. What you actually wanted is not changing the pointer, but the value it points to, thus you need:
*totv=aux;
Additionally, you have a problem here:
for(j=i; j<=aux; j++)
v[j]=v[j+1];
In the last iteration, you will access your array at positions aux and aux + 1, both out of range of your array, at least on the first removal! Instead, you need:
for(j = i; j < aux - 1; j++)
or a little more elegant in my eyes:
for(j = i + 1; j < aux; j++)
v[j - 1]= v[j];
Some further hints:
You do not need any else continue;, if there isn't anything to follow the else branch anyway.
No need to restart the loop (i = -1;) right from the start, you can simply go on with the value you just copied (--i;). However, although technically not incorrect, prefer not modifying the loop variable of a for loop. This is something one does not expect from this kind of loop. If you really have to, then prefer a while loop instead.
You do not need to copy the removed values to the end if you cut them off afterwards anyway.
And if you do not want to keep the removed values, do not copy all the subsequent values each time you remove one value, prefer copying every value to be kept just once, see below.
Moving all elements in one go:
int* p = v;
for(unsigned int i = 0; i < aux; ++i)
{
int tmp = v[i];
if(tmp >= 0)
*p++ = tmp; // copy current value to first free position
}
An array with values { 1, -2, -3, 4, 5, -6, 7 } would now look like this:
{ 1, 4, 5, 7, 5, -6, 7 }. The last values just remain unchanged, p points to the first position to be cut off. So:
aux = p - v;
*totv = aux;
return (int*) realloc(v, aux * sizeof(int));
Be aware that you could return NULL this way, if reallocation fails. I'd assume this to be very unlikely, if reducing size, but for correctness:
p = realloc(v, aux * sizeof(int));
return p ? p : v;
So you'd return the unchanged array on failure. Consider some more fine-tuned error handling...
Related
Given the code:
int vector[5] = {1, 2, 3, 4, 5};
int *pv = vector, value = 3;
for(int i = 0; i < 5; i++) {
*pv++ *= value;
}
for(int i = 0; i < 5; i++) {
printf("%d, ", *(pv+i));
}
I expect each individual element of the array pointed to by pv to be multiplied by 3.
Instead what I get as an output is:
32766, -1554513907, -527290408, -333409024, 32766,
What am I doing wrong?
The problem is that you incremented the pointer in the first for cycle in every loop, so when you get to the end of it, pv is already pointing to one past the end of vector.
For that reason all the values printed in the second for cycle represent residual values stored in addresses out of the bounds of the array, classic undefined behavior.
A quick fix would be to reset the pointer in between the two cycles:
for (int i = 0; i < 5; i++){
*pv++ *= value;
}
pv = vector; //here
for (int i = 0; i < 5; i++) {
printf("%d, ", *(pv + i));
}
Or use the iterator i in both cycles, since you already have it in the for, you might as well use it:
for (int i = 0; i < 5; i++){
pv[i] *= value;
}
for (int i = 0; i < 5; i++) {
printf("%d, ", pv[i]);
}
With this method the pointer is not incremented, it's always pointing to the beginning of the array, accessing its indexes is safe.
Note that I used array notation [] as it's slightly less cluttered than the pointer dereference notation.
In your program, the first for loop (ie)
for(int i = 0; i < 5; i++) {
*pv++ *= value;
}
Here, pointer(pv) gets incremented for 5 times and when the control exits the loop , pointer(pv) is now pointing to something which is out-of-bounds of your array size(vector)
Since you're using the same pointer variable in second for loop to print the array(vector) values, the garbage values gets printed.
You can solve this by reassigning your pointer variable(pv) back to the 1st position of your array either by
pv= vector;
// or
pv = &vector[0];
before your second for loop.
void interclas(int *ptr,int *vec, int *c, int n) {
int i,j,tmp;
tmp=0;
for (i=0;i++;i<n)
for (j=0;i++;j<n)
{
if (vec[j]<=ptr[i])
c[tmp]=vec[j];
else
c[tmp]=ptr[i];
tmp++;
}
}
int main() {
int i,n;
int *ptr,*vec,*c;
printf("Nr. of elements of initial arrays : 5 \n");
n=5;
vec=(int*)malloc( n * sizeof(int));
ptr=(int*)malloc( n * sizeof(int));
c=(int*)malloc( 2 * n * sizeof(int));
for (i=0;i<n;i++) {
scanf("%d",&ptr[i]);
}
for (i=0;i<n;i++) {
scanf("%d",&vec[i]);
}
printf("\n");
printf("Initial arrays are : ");
for (i=0;i<n;i++) {
printf("%d ",ptr[i]);
}
printf("\n");
for (i=0;i<n;i++) {
printf("%d ",vec[i]);
}
interclas(ptr,vec,&c,n);
printf("Merged array is : ");
for (i=0;i<10;i++) {
printf("%d ",c[i]);
}
return 0;
}
So I'm trying to merge two sorted arrays into one new one using pointers with the function 'interclas'. I tried using the same method to sort an array with a pointer in a function and it worked just fine. Now as you can see, it stores the adress of the variable rather than the variable itself.
If I run this, it stores the adresses of the arrays. How can I fix this? (I'm still new to pointers)
In your method's body, change:
for (i=0;i++;i<n)
for (j=0;i++;j<n)
to this:
for (i=0; i<n; i++)
for (j=0; j<n; j++)
and then change the call to your method, from this:
interclas(ptr, vec, &c, n);
to this:
interclas(ptr, vec, c, n);
since the prototype expects a pointer to an int, for the third parameter.
The logic of your method is also flawed, try to put some printfs (e.g. printf("here i = %d, j = %d, ptr[i] = %d, vec[j] = %d, tmp = %d\n", i, j, ptr[i], vec[j], tmp);) to see what values your variables have at its iteration - you only get the first two elements of the first array to be merged!
If you think about it, what you'd like to do is to go through the first element of array ptr and vec, and store the minimum of this two. If now that min was of array ptr, you'd like the next element of ptr to be taken into account, otherwise the next element of vec.
Take a pencil and a paper and sketch that algorithm - you'll see that it goes out nicely, but some leftover elements might be left behind, and not get inserted in the output array.
Driven from that observation, after traversing both the arrays and comparing elements, we will loop over the first array, if needed, to collect elements that were not visited. Similarly for the second array.
Coding that thought gives something like this:
void interclas(int *ptr,int *vec, int *c, int n) {
int i = 0, j = 0, tmp = 0;
// Traverse both arrays simultaneously,
// and choose the min of the two current elements.
// Increase the counter of the array who had
// the min current element.
// Increase the counter for the output array in
// any case.
while(i < n && j < n)
{
if(ptr[i] < vec[j])
{
c[tmp++] = ptr[i++];
}
else
{
c[tmp++] = vec[j++];
}
}
// Store remaining elements of first array
while (i < n)
c[tmp++] = ptr[i++];
// Store remaining elements of second array
while (j < n)
c[tmp++] = vec[j++];
}
Not the source of your problem, but Do I cast the result of malloc? No.
C language
I want to compare an array with it's reversed form and check to see if it's the same.
For example, arr1 = 5 5 8 8 5 5
Reversed arr1 = 5 5 8 8 5 5
Then output would be: Array is the same in reverse.
For some reason when I try to compare my two arrays, it ALWAYS says it is the same even if it is not.
For example : 7 8 9 is entered. The reverse is 9 8 7, which is not the same as what was entered. However, my code says it is.
How can I fix my comparison so that the results are accurate? Please advise, thank you!
I tried using goto to display results. This is my code (function):
void function(int *arr)
{
int j, c, temp, size;
size = sizeof(arr);
int old[size];
int new[size];
/*Prints original array from user input*/
printf("Input Array: ");
for(j=0; j<size; j++)
{
printf("%d ", arr[j]);
old[j] = arr[j];
}
printf("\n");
/* Reversing the array */
c = j - 1;
j = 0;
while (j < c)
{
temp = arr[j];
arr[j] = arr[c];
arr[c] = temp;
j++;
c--;
}
/* Print Reversed Array */
int i;
for(i=0; i<size; i++)
{
printf("%d ", arr[i]);
/*saved to new for possible comparison*/
new[i] = arr[i];
}
printf("\n");
/* Compare original array with reversed array */
if(temp = arr[j])
{
goto same;
} else {
goto notsame;
}
same:
printf("Array is the same in reverse\n");
return 0;
notsame:
printf("Array is not the same in reverse\n");
return 0;
}
You can't get the size of the array with sizeof. You should print out size and see what that value is giving you, it won't be the size of the array.
The reason you are always getting the "same" is that you aren't actually comparing values. You are assigning arr[j] to temp. if(temp = arr[j]) should be if(temp == arr[j]). I think you will find that it won't go to same anymore.
An easier way to solve this problem would be:
void checkReverse(int* arr, int arrSize)
{
// Loop through the array until you have hit the middle
for (int i = 0; i < (arrSize - i); i++)
{
// Check the element to the element in the same place counting from the back
if (arr[i] != arr[arrSize - i - 1])
{
// If we find any that don't match, we know it's not the same and can return
printf("Array is NOT the same in reverse.\n");
return;
}
}
// If we made it this far, they are the same
printf("Array is the same in reverse.\n");
return;
}
You need to modify your code with the following two points:
In your code, size means the number of elements in the array correct? so to calculate it correctly replace
size = sizeof(arr)/sizeof(int);
sizeof gives you the memory size occupied by the array, so for the array of three integers, it gives 3*int size. To count the elements of an array you need to use sizeof(array) and divide it with the size of the data type.
You need to traverse in the loop and compare each element of the original array and reversed array to confirm is it the same not.
So you need to replace your comparison logic with :
/* Compare original array with reversed array */
for(i=0;i < size;i++)
{
if(new[i] != old[i]){
printf("Array is not the same in reverse\n");
return;
}
}
printf("Array is the same in reverse\n");
return;
If you want to use recursion to solve this problem.
#include <stdio.h>
int compare(int *arr, int p, int q)
{
/* base case, if we are at or pass the middle point */
if (p >= q)
return 1;
if (arr[p] != arr[q]) {
return 0;
} else {
return compare(arr, p + 1, q - 1);
}
}
int main(int argc, char *argv[])
{
int arr1[] = {5, 5, 8, 8, 5, 5};
size_t array_size = sizeof(arr1) / sizeof(int);
int first = 0;
int last = array_size - 1;
if (compare(arr1, first, last)) {
printf("Array is same in reverse\n");
} else {
printf("Array is not same in reverse\n");
}
return 0;
}
Best solution to this question during an interview IMO: Use a stack:
step 1)
racecar -> push into stack -> STACK
step 2)
STACK-> pop from stack -> racecar
The input and output strings are the same, therefore the word is a palindrome.
As opposed to:
step 1) something -> push into stack -> STACK
step 2) STACK-> pop from stack -> gnihtemos
The input and output strings are NOT the same, therefore the word is NOT a palindrome.
I'm trying to make my own bubble-sort function in C.
As you can see in the code below this, I'm trying to only using while / if loop to create this function. I put 5 numbers (1,3,2,5,4) so that size of array of this would be 5, and I got 5 (I checked it with Python(C)tutor. However, It works well until tab[j] gets 3. I'm trying to figure it out, but couldn't figure it out why it keeps going out when tab[j] gets 3.
Could you anybody explain what's wrong to me? I would appreciate it.
Here is my code below:
#include <stdio.h>
void ft_sort_integer_table(int *tab, int size)
{
int i;
int j;
int tem;
i = 0;
j = 0;
while(tab[i] < size)
{
if(tab[j] > tab[j+1])
{
tem = tab[j];
tab[j] = tab[j+1];
tab[j+1] = tem;
printf("%d ", tab[j]);
j++;
}
else if(tab[j] < tab[j+1])
{
printf("%d ",tab[j]);
j++;
}
i++;
}
}
int main(void)
{
int tab[] = {1,3,2,5,4};
int size = sizeof(tab)/sizeof(*tab);
ft_sort_integer_table(tab, size);
return(0);
}
You'll need an inner loop in your bubble sort, which is responsible for moving the largest element to the back and performing swaps i times (these large elements are "bubbling up"). Start the inner loop at 0 on each iteration and iterate through size - i (we know that the last i elements are sorted and in their final positions).
i controls your outer loop and should be incremented at the end of the loop (just as you would with a for loop). j controls the inner loop and should be incremented at the end of the loop.
While you're at it, it's a good idea to move your printing out of the sort function, which causes an unnecessary side effect and might frustrate your debugging efforts.
Also, it's worth mentioning that (1) for loops are more semantically appropriate here and (2) there is an optimization available by adding a boolean--as soon as you have a pass through the inner loop that performs no swaps, end early!
#include <stdio.h>
void ft_sort_integer_table(int *tab, int size)
{
int i = 0, j, tem;
while (i < size)
{
j = 0;
while (j < size - i)
{
if (tab[j] > tab[j+1])
{
tem = tab[j];
tab[j] = tab[j+1];
tab[j+1] = tem;
}
j++;
}
i++;
}
}
int main(void)
{
int tab[] = {1,3,2,5,4,6,7,1,5,6,8,9,1,4,5,1,2};
int size = sizeof(tab) / sizeof(*tab);
ft_sort_integer_table(tab, size);
for (int i = 0; i < size; i++)
{
printf("%d ", tab[i]);
}
return(0);
}
Output:
1 1 1 1 2 2 3 4 4 5 5 5 6 6 7 8 9
I'm trying to figure it out, but couldn't figure it out why it keeps
going out when tab[j] get 3.
From your code above, j increment in the same fashion as i. That means both variables will have the same value since j will be incremented by one after the if-then-else statement, and i will also be incremented by one at the end of each loop. Therefore, tab[j] is referencing the same value as tab[i]
With that being said, the boolean condition in the while loop checks whether the value in the tab[i] is less than the value of size.
When i == 3, tab[i] == 5 since in the loop, only the values in the array of index less then i are swapped/changed. Since the size variable holds that value of 5, tab[i] < size will result in a false value and exit the loop.
More information on bubble sort can be found here, https://www.geeksforgeeks.org/bubble-sort/
I am participating in Harvard's opencourse ware and attempting the homework questions. I wrote (or tried to) write a program in C to sort an array using bubble sort implementation. After I finished it, I tested it with an array of size 5, then 6 then 3 etc. All worked. then, I tried to test it with an array of size 11, and then that's when it started bugging out. The program was written to stop getting numbers for the array after it hits the array size entered by the user. But, when I tested it with array size 11 it would continuously try to get more values from the user, past the size declared. It did that to me consistently for a couple days, then the third day I tried to initialize the array size variable to 0, then all of a sudden it would continue to have the same issues with an array size of 4 or more. I un-did the initialization and it continues to do the same thing for an array size of over 4. I cant figure out why the program would work for some array sizes and not others. I used main to get the array size and values from the keyboard, then I passed it to a function I wrote called sort. Note that this is not homework or anything I need to get credit, It is solely for learning. Any comments will be very much appreciated. Thanks.
/****************************************************************************
* helpers.c
*
* Computer Science 50
* Problem Set 3
*
* Helper functions for Problem Set 3.
***************************************************************************/
#include <cs50.h>
#include <stdio.h>
#include "helpers.h"
void
sort(int values[], int n);
int main(){
printf("Please enter the size of the array \n");
int num = GetInt();
int mystack[num];
for (int z=0; z < num; z++){
mystack[z] = GetInt();
}
sort(mystack, num);
}
/*
* Sorts array of n values.
*/
void
sort(int values[], int n)
{
// this is a bubble sort implementation
bool swapped = false; // initialize variable to check if swap was made
for (int i=0; i < (n-1);){ // loops through all array values
if (values[i + 1] > values [i]){ // checks the neighbor to see if it's bigger
i++; // if bigger do nothing except to move to the next value in the array
}
else{ // if neighbor is not bigger then out of order and needs sorting
int temp = values[i]; // store current array value in temp variable for swapping purposes
values[i] = values[i+1]; //swap with neighbor
values[i+1] = temp; // swap neighbor to current array value
swapped = true; // keep track that swap was made
i++;
}
// if we are at the end of array and swap was made then go back to beginning
// and start process again.
if((i == (n-1) && (swapped == true))){
i = 0;
swapped = false;
}
// if we are at the end and swap was not made then array must be in order so print it
if((i == (n-1) && (swapped == false))){
for (int y =0; y < n; y++){
printf("%d", values[y]);
}
// exit program
break;
}
} // end for
// return;
}
You can easily use 2 nested for loops :
int i, j, temp ;
for ( i = 0 ; i < n - 1 ; i++ )
{
for ( j = 0 ; j <= n - 2 - i ; j++ )
{
if ( arr[j] > arr[j + 1] )
{
temp = arr[j] ;
arr[j] = arr[j + 1] ;
arr[j + 1] = temp ;
}
}
}
also you should now it's a c++ code not a c, because c doesn't have something like :
int mystack[num];
and you should enter a number when you're creating an array and you can't use a variable (like "int num" in your code). This is in C, but in C++ you're doing right.
The first thing to do when debugging a problem like this is ensure that the computer is seeing the data you think it should be seeing. You do that by printing out the data as it is entered. You're having trouble with the inputs; print out what the computer is seeing:
static void dump_array(FILE *fp, const char *tag, const int *array, int size)
{
fprintf(fp, "Array %s (%d items)\n", tag, size);
for (int i = 0; i < size; i++)
fprintf(fp, " %d: %d\n", i, array[i]);
}
int main(void)
{
printf("Please enter the size of the array \n");
int num = GetInt();
printf("num = %d\n", num);
int mystack[num];
for (int z = 0; z < num; z++)
{
mystack[z] = GetInt();
printf("%d: %d\n", z, mystack[z]);
}
dump_array(stdout, "Before", mystack, num);
sort(mystack, num);
dump_array(stdout, "After", mystack, num);
}
This will give you direct indications of what is being entered as it is entered, which will probably help you recognize what is going wrong. Printing out inputs is a very basic debugging technique.
Also, stylistically, having a function that should be called sort_array_and_print() suggests that you do not have the correct division of labour; the sort code should sort, and a separate function (like the dump_array() function I showed) should be used for printing an array.
As it turns out the reason why it was doing this is because when comparing an array's neighbor to itself as in:
if (values[i + 1] > values [i])
The fact that I was just checking that it is greater than, without checking if it is '=' then it was causing it to behave undesirably. So if the array is for example [1, 1, 5, 2, 6, 8] then by 1 being next to a 1, my program did not account for this behavior and acted the way it did.