#include <stdio.h>
#include <malloc.h>
//#include "ans.c"
int *decompressRLElist(int *nums, int numsSize, int *returnSize);
int main()
{
int nums[] = {39, 1};
int length = 2;
int returnlength;
int *p = decompressRLElist(nums, length, &returnlength);
int *pp = p;
while (returnlength-- != 0)
{
putchar(*(p++)+'0');
}
system("pause");
return 0;
}
int *decompressRLElist(int *nums, int numsSize, int *returnSize)
{
int *ans = (int *)malloc(100);
int *p = ans;
*returnSize = 0;
numsSize /= 2;
while (numsSize-- != 0)
{
while ((*nums)-- != 0)
{
*(p++) = *(nums + 1);
(*returnSize)++;
}
nums += 2;
}
return ans;
}
I am working on a leetcode problem, after running the debugger there is an exception named trace/breakpoint trap occurred. It is confusing that when the length of array is shorter than 39, the error does not occur, but when equal or longer than 39, the error occurs.
One integer is usually 4 bytes, though it can be different deppending on your system, so when you allocate 100 bytes it's only good for 25 integers, you should use:
int *ans = malloc(100 * sizeof(*ans));
The malloc cast is also unnecessary.
The fact that the error only starts at array size of 39 can only be attributed to undefined behaviour.
Related
I have a problem. I have to divide array into dynamic array and return pointer with parameter.
When I try to run this code, I get (interrupted by signal 11: SIGSEGV) this message. I think it is something with my pointers. But I don't even get any warnings, I don't know where to look else.
#include <stdio.h>
#include <stdlib.h>
int splitData(int data[], int size, int splitPlace, int **firstArray);
int main() {
int data[6] = {1, 2, 3, 4, 5, 6};
int size = 6;
int *ptr = NULL;
int n = splitData(data, size, 3, &ptr);
printf("%d", n);
for(int i = 0; i < 3; ++i)
{
printf("[%d]", ptr[i]);
}
return 0;
}
int splitData(int data[], int size, int splitPlace, int **firstArray)
{
*firstArray = (int *)malloc(splitPlace * sizeof(int));
for(int i = 0; i < splitPlace; ++i)
{
*firstArray[i] = data[i];
}
return 0;
}
You have the precedence wrong with *firstArray[i]. You need (*firstArray)[i].
Clearer might be to allocate
int *new_array = malloc(...);
*firstArray = new_array.
Then use new_array in your loop body.
I am learning basic C, and I am still trying to understand arrays and pointers. I am trying to write a push function to mimic the behavior of an array in Javascript, but with a workaround, since arrays cannot be returned in C.
When I access the returned pointer with (*p+3), it yields the correct value, but p[3] does not. However, I can still access the correct value within push() with p[3]. Why is this?
#include <stdio.h>
#include <stdlib.h>
void br() {
putchar('\n');
}
int *push(int *arr, size_t size, int val) {
int *arr2 = calloc(size + 1, sizeof(int));
for (int i = 0; i < size; i++) {
arr2[i] = arr[i];
}
arr2[size] = val;
return arr2;
}
int main(int argc, char *argv[]) {
int myNums[] = { 1, 2, 3 };
int *p = push(myNums, sizeof(myNums), 4);
printf("%i", (*p + 3));
br();
printf("%i", p[3]);
br();
return 0;
}
EDIT: I think there is a better solution using structs.
#include <stdio.h>
#include <stdlib.h>
typedef struct{
int*values;
int length;
} intArray;
void printInts(intArray * arr){
for(int i = 0; i < arr->length; i++){
printf("Value %i: %i\n",i,arr->values[i]);
}
}
intArray push(intArray * arr, int value){
arr->length++;
arr->values = realloc(arr->values, sizeof(int)*arr->length);
arr->values[arr->length-1] = value;
return *arr;
}
intArray pop(intArray * arr){
arr->length--;
arr->values = realloc(arr->values, sizeof(int)*arr->length);
return *arr;
}
int main(int argc, char *argv[]) {
intArray myNums;
myNums = push(&myNums,15);
myNums = push(&myNums,30);
myNums = push(&myNums,45);
myNums = push(&myNums,60);
myNums = pop(&myNums);
printInts(&myNums);
/* expected output:
Value 0: 15
Value 1: 30
Value 2: 45
*/
return 0;
}
There are two mistakes in the code:
int *p = push(myNums, sizeof(myNums), 4);
sizeof(myNums) is not the length of the array (ie: the number of elements), but its size in bytes.
You can use sizeof(myNums) / sizeof(myNums[0]) to compute the number of elements at compile time.
printf("%i", (*p + 3));
You first print *p + 3, which is not the same as *(p + 3): you get the expected output only by coincidence because *p, which is equivalent to p[0] happens to have the value 1. Conversely, p[3] accesses the fourth element of the reallocated array, whose value is undefined as it was copied from data beyond the end of the original array passed to push().
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
int *push(int *arr, size_t count, int val) {
int *arr2 = calloc(count + 1, sizeof(int));
for (int i = 0; i < count; i++) {
arr2[i] = arr[i];
}
arr2[count] = val;
return arr2;
}
int main(int argc, char *argv[]) {
int myNums[] = { 1, 2, 3 };
int *p = push(myNums, sizeof(myNums) / sizeof(myNums[0]), 4);
printf("%i\n", *(p + 3));
printf("%i\n", p[3]);
free(p);
return 0;
}
I am doing leetocde. First question is Two Sum: https://leetcode.com/problems/two-sum/description/
I submit solution with c code:
/**
* Note: The returned array must be malloced, assume caller calls free().
*/
int* twoSum(int* nums, int numsSize, int target) {
int *a = (int*)malloc(2*sizeof(int));
for(int i = 0;i<numsSize;i++){
for(int j = i+1;(j<numsSize && j != i);j++){
if(nums[i] + nums[j] == target){
a[0] = i;
a[1] = j;
return a;
}
}
}
return NULL;
}
My soluution be accepted.
The complete c code is:
/* my solution to Two Sum */
#include <stdio.h>
#include <stdlib.h>
#define TARGET 9
int* twoSum(int* nums, int numsSize, int target) {
int *a = (int*)malloc(2*sizeof(int));
for(int i = 0;i<numsSize;i++){
for(int j = i+1;(j<numsSize && j != i);j++){
if(nums[i] + nums[j] == target){
a[0] = i;
a[1] = j;
return a;
}
}
}
return NULL;
}
int main()
{
int n,target = TARGET;
int a[]={2, 7, 11, 15};
// int a[]={2,25,10,7,11,15,21,60}; // test data
int *result = NULL;
n = sizeof(a) / sizeof(a[0]);
result = twoSum(a,n,target);
if(result != NULL)
printf("%d %d\n",result[0],result[1]);
else
printf("No elements that satisfy the condition\n");
return 0;
}
/*
* output:
* 0 1
*/
I run command:
gcc two-sum.c -o two-sum
./two-sum
It outputs : 0 1
But I find my code have a bug that in twoSum function "a" is not be free.
How to solve it?
The complement only makes sense when you specify how long your data type is. If it's 4 bits, then for 0xf it's 0x0. If it's 8 bits, then for 0xf it's 0xf0.
Your representation of -6 is going to be either 0xfa, 0xfffa, 0xfffffffa, or longer, depending on how many bytes long your value is.
I am having a trouble while practicing double pointer
The Error is "EXE_BAD_ACCESS" in Xcode
#include <stdio.h>
/* Program to Get Min and Max Value
in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
**maxPtr=arr[0]; // Error Line
**minPtr=arr[0]; // Error Line
for(i=1; i<5; i++)
{
if(arr[i]>**maxPtr)
**maxPtr=arr[i];
else if(arr[i]<**minPtr)
**minPtr=arr[i];
}
}
int main()
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", *maxptr, *minptr);
}
I've thought that *dptr of **dptr = &ptr is *ptr
and **dptr means variable which *ptr pointing.
so I assume that **dptr = arr[0] means save first num of arr by reference at variable which *ptr pointing!
but I experiencing access error now.. I will thank for your help!
void SaveValue(int **maxPtr, int **minPtr, int arr[]); provides pointers to pointers to int so use them as such.
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
*minPtr=arr + 0; /* same as *maxPtr = &arr[0]; */
for(i = 1; i < 5; i++)
{
if(arr[i] > **maxPtr)
*maxPtr = arr + i; /* same as *maxPtr = &arr[i]; */
else if(arr[i] < **minPtr)
*minPtr = arr + i; /* same as *minPtr = &arr[i]; */
}
}
Also this interface is a bit dangerous and unflexible; so why not pass the size of the array as well:
void SaveValue(int **maxPtr, int **minPtr, int arr[], ssize_t s)
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
Call the fcuntion like this:
SaveValue(&maxptr, &minptr, arr, sizeof arr/sizeof *arr);
As the return value of the function is unused we could utlize it to apply some error inidication to allow the user of the function to write more stable code:
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s)
{
int result = 0;
if ((NULL == arr) || (NULL == maxPtr) || (NULL == minPtr) || (0 > s))
{
result = -1;
errno = EINVAL;
}
else
{
*maxPtr=arr + 0;
*minPtr=arr + 0;
for(--s; s >= 0; --s)
{
if(arr[s] > **maxPtr)
{
*maxPtr = arr + s;
}
else if(arr[i] < **minPtr)
{
*minPtr = arr + s;
}
}
}
return result;
}
Use it like this:
#include <stdio.h>
int SaveValue(int ** maxPtr, int ** minPtr, int arr[], ssize_t s);
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxPtr;
int *minPtr;
int result = SaveValue(&maxPtr, &minPtr, arr, sizeof arr/sizeof *arr);
if (-1 == result)
{
perror("SaveValue() failed")
}
else
{
printf("%d, %d \n", *maxPtr, *minPtr);
}
}
The pointer should be pointing to valid memory location before dereferencing it else it will lead to undefined behavior. Below changes will fix your error.
int max;
int min;
int *maxptr = &max;
int *minptr = &min;
There is no need of double pointer here change your function prototype to
void SaveValue(int *maxPtr, int *minPtr, int arr[])
Have
int max;
int min;
in main() and call this API accordingly
SaveValue(&max,&min,arr);
I'll assume your code is purely for pointer learning purposes and not an attempt to implement this operation in a practical situation. So if you want to have maxptr and minptr in main() pointing to the maximum and minimum values in arr[], I think you should change your double pointer assignments from **maxPtr=arr[0] to *maxPtr=&arr[0], so your code would become:
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr = &arr[0]; // Error Line
*minPtr = &arr[0]; // Error Line
for (i = 1; i < 5; i++) {
if (arr[i] > **maxPtr)
*maxPtr = &arr[i];
else if (arr[i] < **minPtr)
*minPtr = &arr[i];
}
}
In this case, when you make the assignments, you don't want to dereference the double pointers. Instead, you should assign it with the address of the element you want to show when you dereference them in main().
You don't need to use the double asterisk when initialize the maxPtr and minPtr pointers in the function SaveValue, neither in the for loop body. MaxPtr and minPtr both are double pointers, but is still the memory direction of maxptr in main(). So you only need to dereference them with a single asterisk, to acces the memory direction them points to.
The source correct source code is this:
#include <stdio.h>
/* Correct program to Get Min and Max Value in Array */
void SaveValue(int **maxPtr, int **minPtr, int arr[])
{
int i;
*maxPtr=arr[0];
*minPtr=arr[0];
for(i=1; i<5; i++)
{
if(arr[i]>*maxPtr)
*maxPtr=arr[i];
else if(arr[i]<*minPtr)
*minPtr=arr[i];
}
}
int main(void)
{
int arr[5]={4, 5, 7, 2, 6};
int *maxptr;
int *minptr;
SaveValue(&maxptr, &minptr, arr);
printf("%d, %d \n", maxptr, minptr);
return 0;
}
When I compile it with GCC and execute it, i get the next output:
7, 2.
Remember that depending of the environment (Operating System, version, compiler, standards) that you use the program results may vary.
My lsearch function should find the value 11 in my array. It does not, and I don't know where the error is. Why does this code not find the value 11?
#include <stdio.h>
#include <string.h>
#define PF printf
int main() {
int intcmp(void *ip1, void * ip2);
void * lsearch(void *key, void *base, int n, int elemSize,
int(* cmpfun)(void *, void *));
int arr[] = {4, 6, 2, 3, 11, 22, 15};
int n = sizeof(arr) / sizeof(int);
int key = 11;
int *found = lsearch(&key, &arr, n, sizeof(int), intcmp);
PF("found=%p", found);
return 1;
}
int intcmp(void *ip1, void * ip2) {
int *p1 = ip1;
int *p2 = ip2;
return *p1 - *p2 == 0;
}
void * lsearch(void *key, void *base, int n, int elemSize,
int(* cmpfun)(void *, void *)) {
int i;
for(i = 0; i < n; i ++) {
void *elemArr = (char *)base + i * elemSize;
if(cmpfun(key, elemArr) == 0)
return elemArr;
}
return NULL;
}
There's a few oddities in your code (PF and the way the functions is declared in main yet defined globally), however, the problem is that your logic if inverted in a two places.
if(cmpfun(key, elemArr) == 0)
return elemArr;
And:
return *p1 - *p2 == 0;
Mentally run through that when the two elements are equal. The == expression will return 1 when the number does actually equal the other. 1 != 0 thus it's not considered found.
Either through a negation in there or just return *p1 - *p2; directly.
I have annotated the code below:
#include <stdio.h>
#include <string.h>
// This is bad practice. It makes your code less readable.
// I won't use it below.
#define PF printf
// Declare this first so a prototype is not needed.
// You violated a C pattern by using `cmp` in the name.
// Comparison functions in C return <0, 0, >0, not a binary value.
// To wit, later you used the comparison correctly. I've fixed the
// inconsistency.
int intcmp(void *vp1, void *vp2)
{ // Most C styles have the brace on its own line, unlike Java. Roll with it.
int *p1 = vp1, *p2 = vp2;
return *p1 - *p2;
}
// Search n elements of size elemSize in the array at
// base in sequence using cmpfun on key,
// to test for equality (cmpfun == 0). Return a pointer
// to the found element or NULL if none.
void *lsearch(void *key, void *base, int n,
int elemSize, int(* cmpfun)(void *, void *))
{
int i;
for (i = 0; i < n; i++) {
void *elemArr = (char*)base + i * elemSize;
if (cmpfun(key, elemArr) == 0)
return elemArr;
}
return NULL;
}
int main()
{
int arr[] = {4, 6, 2, 3, 11, 22, 15};
int n = sizeof(arr) / sizeof(int);
int key = 11;
int *found = lsearch(&key, &arr, n, sizeof(int), intcmp);
printf("found=%p (%d)", found, *(int*)found);
return 0; // By convention zero corresponds to no error.
}