C pointer arithmetic palindrome - c

I'm a java student who's currently learning about pointers and C.
I tried to make a simple palindrome tester in C using a single array and pointer arithmetic.
I got it to work without a loop (example for an array of size 10 :*(test) == *(test+9) was true.
Having trouble with my loop. School me!
#include<stdio.h>
//function declaration
//int palindrome(int *test);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
int *ptr;
ptr = &numArray[0];
output = palindrome(ptr);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test) {
int i;
for (i = 0; i <= (sizeof(test) / 2); i++) {
if (*(test + i) == *(test + (sizeof(test) - i)))
return 1;
else
return 0;
}
}

The Name of the array will itself acts as a pointer to an first element of the array, if you loose the pointer then there is no means for you to access the element of the array and hence you can send just the name of the array as a parameter to the function.
In the palindrome function:
you have used sizeof(test)/2. what happens is the address gets divided which is meaningless and hence you should not use that to calculate the mid element.
sizeof the pointer will be the same irrespective of the type of address that gets stored.

Why do you copy your pointer in another variable?
int *ptr;
ptr = &numArray[0];
Just send it to you function:
palindrome(numArray);
And sizeof(test) give you the memory size of a pointer, it's not what you want. You have to give the size in parameter of your function.
int palindrome(int *test, int size){
...
}
Finally your code must look like this:
#include<stdio.h>
int palindrome(int *test, int size);
int main()
{
int output;
int numArray[10] = {0,2,3,4,1,1,4,3,2,0};
output = palindrome(numArray, 10);
printf("%d", output);
}
//function determine if string is a palindrome
int palindrome(int *test, int size) {
int i;
for (i = 0; i < size / 2; i++) {
if (*(test + i) != *(test + (size - 1) - i))
return 0;
}
return 1;
}

Related

Pointers and arrays without using index

I have been asked to sum up an int array and return the sum not using index.
(function needs to get the array and the size)
I know I should've set a pointer to the array and compare the pointer to the array address and use pointer++ to run over the array.
Tho, I wrote down the following code :
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
while(*nNumArray <= &nNumArray[nSize-1])
{
nSum += *nNumArray;
nNumArray++;
}
return nSum;
}
which works perfectly,
thing is *nNumArray is referring to values and &nNumArray[nSize-1] is referring to an address.
I'm trying to understand how come this way works.
Will appreciate some insights. Thanks.
The while loop condition is incorrect:
while(*nNumArray <= &nNumArray[nSize-1])
because you are comparing an integer (*nNumArray) with a pointer (&nNumArray[nSize-1]). Compiler must be giving warning message on this statement.
Instead, you can do:
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
while(nSize--)
{
nSum += *nNumArray;
nNumArray++;
}
return nSum;
}
"which works perfectly" : this is impossible
(*nNumArray <= &nNumArray[nSize-1]) : you compare an int into the vector (and later outside it) and an address of an int into the vector ( and in fact after its end). A priori your compiler signal the error
Furthermore &nNumArray[nSize-1] will not be the end of the vector after the first loop because you modify nNumArray
If you want to use a pointer you can use an other variable to store it to not modify nNumArray, and to change test like (ptr <= &nNumArray[nSize-1]) :
#include <stdio.h>
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
int * ptr = nNumArray;
while(ptr <= &nNumArray[nSize-1])
{
nSum += *ptr++;
}
return nSum;
}
int main()
{
int a[3] = {1,2,3};
printf("%d\n", sumArray(a, 3));
return 0;
}
First error here :
(*nNumArray <= &nNumArray[nSize-1])
The name of the array variable itself is considered as a pointer in C, thus *nNumArray represents the reference of an pointer.
It should be nNumArray to make it compare the address.
Second error :
It won't work perfectly if only the first error is fixed.
The index operation works like this :
&nNumArray[nSize-1] works the same as nNumArray + nSize - 1
Thus the while loop might looks like this :
while(nNumArray <= nNumArray + nSize - 1){
nSum += *nNumArray;
nNumArray++;
}
(This might makes it more simple to see where is wrong)
The while loop will run forever until *nNumArray accessed an int which is out of the array that causes a segmentation fault.
You might want to do it by using another pointer to compare with nNumArray + nSize - 1, and the whole sumArray function should look like this:
int sumArray(int nNumArray[], int nSize)
{
int nSum = 0;
int *ptr = nNumArray;
while(ptr <= nNumArray + nSize - 1)
{
nSum += *ptr;
ptr++;
}
return nSum;
}
And now it should work perfectly :)

Array pointers and functions

I have to write a C program to do the following:
Write a function that takes three arguments: a pointer to the first
element of a range in an array, a pointer to the element following
the end of a range in an array, and an int value. Have the function
set each element of the array to the int value.
My code is not working. Here is what I have so far. Any help is appreciated.
#include <stdio.h>
#include <iostream>
int listNumbers[3]{ 1,2,3 };
void Sorter(int *first, int * last, int *value);
int * first = &listNumbers[0];
int * last = &listNumbers[2];
int value;
int main() {
printf("your list numbers are:\n");
int i;
for (int i = 0; i < 3; ++i) {
printf("%d", listNumbers[i]);
}
printf("\n");
printf("enter an integer:\n");
scanf_s("%d", &value);
Sorter( first, last, &value);
printf("your new list numbers are:\n");
int j;
for (int j = 0; j < 3; ++j) {
printf("%d", listNumbers[j]);
}
printf("\n");
system("PAUSE");
return 0;
}
void Sorter(int *first, int * last, int *value) {
int i=0;
printf("value = %d\n", &value);
*first = value;
while (i <= *last) {
*(first + i) = value;
i++;
}
}
First, work out the different between the 2 pointers.
int count = last - first + 1;
The compiler will automatically divide by the size of an integer. We add 1 to make the range inclusive. Now just iterate through each element:
for (int i = 0; i < count; i++) {
first[i] = value;
}
Also, why are you passing the value as a pointer? This should just be a value.
void Sorter(int *first, int *last, int value) {
And when you call it...
Sorter(first, last, value);
Your Sorter function does not satisfy the problem criteria. The parameters are supposed to be two pointers into an array, and an int. Your function instead accepts three pointers.
You could nevertheless have made it implement at least the apparent spirit of the exercise, by using the value to which the third argument points as the fill value, but you don't do that. Instead you assign the pointer itself to each array element. That ought to at least elicit a warning from your compiler, and you ought not to be ignoring its warnings, especially when your code it not doing what you think it should.
Furthermore, the last pointer is expected to point to just past the last element to set, but you use it as if it points to an integer offset from the start pointer. This is almost the opposite of the previous problem: here, you need to use the pointer value itself, not the int to which it points.

Passing entire array to the function in C

I have written a program for insertion shot like following:
int _tmain(int argc, _TCHAR* argv[])
{
int arr[10] = {1,2,3,10,5,9,6,8,7,4};
int value;
cin >> value ;
int *ptr;
ptr = insertionshot(arr); //here Im passing whole array
BinarySearch(arr,value);
return 0;
}
int * insertionshot(int arr[])
{
//Changed after a hint (now, its fine)
int ar[10];
for(int i =0;i < 10; i++)
{
ar[i] = arr[i];
}
//Changed after a hint
int arrlength = sizeof(ar)/sizeof(ar[0]); //here array length is 1, it should be 10
for(int a = 1; a <= arrlength -1 ;a++)
{
int b = a;
while(b > 0 && ar[b] < ar[b-1])
{
int temp;
temp = ar[b-1];
ar[b-1] = ar[b];
ar[b] = temp;
b--;
}
}
return ar;
}
The problem is after passing the whole array to the function, my function definition only shows 1 element in array and also "arraylength" is giving 1.
int arr[] in a function formal parameter list is a syntax quirk, it is actually processed as int *arr. So the sizeof trick doesn't behave as you expect.
In C it is not possible to pass arrays by value; and furthermore, at runtime an array does not remember its length.
You could include the length information by passing a pointer to the whole array at compile time:
int * insertionshot(int (*arr)[10])
Of course, with this approach you can only ever pass an array of length 10. So if you intend to be able to pass arrays of differing length, you have to pass the length as another parameter.

C Pointer: char to binary value

#include <stdio.h>
#include <string.h>
int * bin(char a);
int main(void){
char a='a';
int k=0;
int *binary;
binary=bin(a);
for(k=0; k<8; k++){
printf("%d", *binary++);
printf("\n");
}
return 0;
}
int *bin(char a){
int i=0;
int *arr;
int output[8];
char c=a;
for (i = 0; i <8 ; ++i) {
output[8-i-1] = (a >> i) & 1;
}
arr=&output[0];
// for (i = 0; i <8 ; ++i) {
// printf("%d", output[i]);
// }
// printf("\n");
return arr;
}
The ouptut should be the binary value of the char 'a'which is:
0
1
1
0
0
0
0
1
but i got this instead:
0
-1216804320
-1218095335
-1216804320
10
-1076423592
-1218208721
-1216804320
Is this a pointer problem?
How do i fix it so it would print the right answer? thx!!
You're returning a pointer to a local variable (arr), whose contents are no longer valid when the function returns. Use malloc instead:
int main(void){
...
int *arr = bin(a);
...
free(arr);
return 0;
}
int *bin(char a){
int *arr = malloc(8 * sizeof int);
...
return arr;
}
First error I can notice is Scope problem, that you are returning address of local variable output[8];
arr=&output[0];
return arr;
That is wrong, scope of output[] is inside bin() function only.
You should allocate memory for output[] dynamically if you want to access it outside bin() function, like:
int *output = calloc(8, sizeof(int));
even you don't need extra variable just return output from bin()
I have corrected you code like below without much change:
int *bin(char a){
int i=0;
int *output = calloc(8, sizeof(int));
for (i = 0; i <8 ; ++i) {
output[8-i-1] = (a >> i) & 1;
}
return output;
}
Notice removed unused variables c and arr
additionally, don't forgot to free dynamically allocated memory explicitly:
Second (Notice) be aware of Memory Clobbering Error because you are updating binary variable by ++ in printf function.
Just simple don't free(binary); it will produce run time error because you are modifying binary variable inside printf *binary++: first save return address in a extra pointer variable then free that. Like I am doing:
b = binary=bin(a);
// loop
printf("%d", *binary++);
// ^ changing binary variable to point new memory location
// after loop
free(b);
If you free(binary) then it would be wrong because you would free a memory location that is not allocated dynamically because your are changing binary variable.
get a working code here, read comments.

C: Accessing a pointer from outside a function

I have the following code:
int takeEven(int *nums, int numelements, int *newlist) {
newlist = malloc(numelements * sizeof *newlist);
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if (!(*nums % 2)) {
*(newlist++) = *nums;
found++;
}
}
newlist -= found;
printf("First number found %d\n", *newlist); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
The output of the above code:
-1
2088999640
2088857728
If I try printing the first element of the newlist pointer before returning the function (printf("First number found %d\n", *newlist);), it works as intended, but why is it that when I try to access the pointer from outside of the function I get those values from seemingly unmalloced addresses?
You are passing the newList pointer by value, so it will not be modified by your function. You should do instead.
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof *newlist);
...
}
...
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
You need to pass in a pointer to pointer, i.e. int **newlist. Specifically, newlist is being passed into your function by value, so the newlist in main and inside your function are two completely different variables.
There is also a bug in your test for even numbers:
#include <stdio.h>
#include <stdlib.h>
int takeEven(int *nums, int numelements, int **newlist) {
int *list = malloc(numelements * sizeof **newlist);
*newlist = list; // this modifies the value of newlist in main
int i, found = 0;
for(i = 0; i < numelements; ++i, nums++) {
if ((*nums % 2) == 0) {
*(list++) = *nums;
found++;
}
}
list -= found;
printf("First number found %d\n", *list); // <= works correctly
return found;
}
int main()
{
int nums[] = {1,2,3,4,5};
int *evenNums;
int i;
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
for (i = 0; i < n; ++i) {
printf("%d\n", *(evenNums++));
}
return 0;
}
You can also take a look at this question from the C-FAQ which deals with your problem also:
Q: I have a function which accepts, and is supposed to initialize, a pointer:
void f(int *ip)
{
static int dummy = 5;
ip = &dummy;
}
But when I call it like this:
int *ip;
f(ip);
the pointer in the caller remains unchanged.
A: Are you sure the function initialized what you thought it did? Remember that arguments in C are passed by value. In the code above, the called function alters only the passed copy of the pointer. To make it work as you expect, one fix is to pass the address of the pointer (the function ends up accepting a pointer-to-a-pointer; in this case, we're essentially simulating pass by reference):
void f(ipp)
int **ipp;
{
static int dummy = 5;
*ipp = &dummy;
}
...
int *ip;
f(&ip);
Another solution is to have the function return the pointer:
int *f()
{
static int dummy = 5;
return &dummy;
}
...
int *ip = f();
See also questions 4.9 and 4.11.
The newlist you have at the end of the function is not the same as you have when calling the function.
You are passing a copy of a pointer, then malloc changes that pointer(internal to the function) to point to allocated memory, but the outside one is still unmodified.
You need to use a pointer to pointer as a parameter so that you can set where the ourtside one points by double indirection.
int use_pointed_memory(char **pointer){
*pointer = malloc();
}
char *myptr;
use_pointed_memory(&myptr);
So effectively you are giving the function the place where you store the address of what you want and asking the function to store there a valid memory pointer.
You're passing a pointer by value here:
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), evenNums);
Which means that a copy of the pointer is made within that function. You then overwrite that copy:
newlist = malloc(numelements * sizeof *newlist);
Since it is but a copy, the caller won't see the result of your assignment. What you seemingly want here is to pass a pointer by reference - for that, you need a pointer to pointer:
int takeEven(int *nums, int numelements, int **newlist) {
*newlist = malloc(numelements * sizeof **newlist); // apply * to newlist
...
}
int n = takeEven(nums, sizeof(nums) / sizeof(*nums), &evenNums);
And don't forget to free:
free(evenNums);
In C, everything is passed by value. So you are passing a copy of evenNums to the function. Whatever you modify it inside the function doesn't get reflected outside. You need to int** as the third parameter.

Resources