Put array as argument and read its value - c

I am scanning for values using function .
int **array(int * counter) {
int **vrat;
int max = 5;
int index = 0;
int i;
vrat = malloc(max*sizeof(int*));
for ( i = 0; i < max ; i++) {
vrat[i] = malloc(2 * sizeof(int));
}
int x;
int y;
char c;
while (scanf("%d%c%d", &x, &c, &y) != EOF) {
vrat[index][0] = x;
vrat[index][1] = y;
index++;
}
*counter = index;
return vrat;
}
and calling it in main to return the array, which works .
int main()
{
int counter=0;
int **mej;
int gg;
mej = array(&counter);
int i;
gg = pocet(mej, &counter);
return 0;
}
what is bothering my mnd is "pocet" function , i am passing an array in it and want to print its value . but it always print undefined numbers
Function looks like this
int pocet(int array[][2],int *counter) {
int poc = 0;
int i;
for ( i =0; i < *counter ;i++) {
printf("cislo = %d", array[i][0]);
}
return poc;
}
as you can see , it has static 2nd dimension , how can i make this work?

You are allocating space for 5 pointers, you should multiply by the size of a pointer and not the size of an int, like this
vrat = malloc(max * sizeof(int *));
/* ^ pointer */
Although you can completely avoid the mistake by multiplying by the size of the pointer type like this
vrat = malloc(max * sizeof(*vrat));
and ALWAYS check that malloc() has not returned NULL before actually using the pointer.
Also, don't compare scanf() to EOF since it's very unlikely to get an EOF before an input error because it requires explicit input from the user, instead do this
while(scanf("%d%c%d", &x, &c, &y) == 3)
The return type of your function should match that of the returned object, in this case int **, change the function signature to
int **array(int *content)

vrat = malloc(max*sizeof(int*));
How do you know whether the memory successfully got allocated or not?
Always check the pointer returned by malloc & family functions for equivalence with NULL to avoid possible SegFault.
while (scanf("%d%c%d", &x, &c, &y) != EOF)
What if there's matching failure for c? Then scanf will return 1 and while will still go for iteration even if scanf could not store values in c and y.
So always compare scanf return value with no. of arguments instead of EOF
while (scanf("%d%c%d", &x, &c, &y) != EOF) {
vrat[index][0] = x;
vrat[index][1] = y;
index++;
}
Here what if index >= max?
Since you have allocated memory for only max integer pointers you must not try to access the memory beyond the allocated chunk.
Solution: Change while condition to
while ((scanf("%d%c%d", &x, &c, &y) == 3) && (index < max))
So the correct code snippet would be:
vrat = malloc(max*sizeof(int*));
if(!vrat)
{
printf("vrat: malloc failed!\n");
exit(1);
}
for ( i = 0; i < max ; i++) {
vrat[i] = malloc(2 * sizeof(int));
if(!vrat[i])
{
printf("vrat[%d]: malloc failed!\n", i);
exit(1);
}
}
int x;
int y;
char c;
while ((scanf("%d%c%d", &x, &c, &y) == 3) && (index < max)) {
vrat[index][0] = x;
vrat[index][1] = y;
index++;
}

An int** is not an int[][2]. The first is a pointer to pointers to int while the second (as an argument) is a pointer to int[2]. You cannot convert between the two the way you tried. You should have gotten a compiler warning/error about this.
The easiest way to fix this is to have pocet take an int** as the first argument. Fix the issues others have mentioned as well.

You have defined int **vrat;
When you do malloc, you need to use int ** or int * and not int

Related

Understanding why it does not find duplicates in array

I wrote the following function in C:
int last(long arr[], int length) {
for (int i = 0; i < length-1; i++)
if (*(arr+i) == *(arr + length - 1))
return 1;
return 0;
}
it checks if the last value of the array was used more than once. In the main:
int *arr = malloc(length*sizeof(int));
for (int i = 0; i < length; i++)
scanf("%d", ++arr);
printf(last((long *) arr, length);
For some reason for the array [1,2,2,3] it returns that the last element was used multiple times and I'm not sure why. I think that is because of scanf("%d", ++arr); but I don't know how to fix it.
My goal is that it will return 1 for [1,3,2,3] and 0 for [1,2,2,3]. What could be the problem?
You should use scanf("%d", &arr[i]);. Using ++arr causes the array to be incremented before you pass it to last, and also reads into data beyond arr, which is undefined behavior.
Another one of the issues in this is the cast to long *.
You should use %ld in scanf and long *arr = malloc(length*sizeof(*arr));.
Also make sure to check for NULL. You never know when malloc is going to fail or someone's going to pass bad data.
Full example:
#include <stdio.h>
#include <stdlib.h>
int last(long arr[], int length) {
if(!arr) return -1;
for (int i = 0; i < length-1; i++)
{
if (arr[i] == arr[length-1])
return 1;
}
return 0;
}
int main(void)
{
long *arr = malloc(4*sizeof(*arr));
if(!arr) return 1;
for (int i = 0; i < 4; i++)
scanf("%ld", &arr[i]);
printf("%d\n", last(arr, 4));
}
Several problems in your code:
Look at this statement:
scanf("%d", ++arr);
^^^^^
In the last iteration of loop, the pointer arr will be pointing to one element past end of array arr (due to pre-increment) and it is is passed to scanf(). The scanf() will access the memory location pointed by the pointer which is an invalid memory because your program does not own it. This is undefined behavior. Note that a pointer may point to one element past the end of array, this is as per standard but dereferencing such pointer will lead to undefined behavior.
Once the main() function for loop finishes the arr pointer pointing to location past the end of memory allocated to arr and just after this you are passing arr to last() function. So, you are passing an invalid memory reference to last() function and then accessing that memory in last() function - one more undefined behavior in your program.
Probably you should take another pointer and point it to arr, so that arr keep pointing to allcoated memory reference returned by malloc().
Note that if you want to read the input the way you are doing then use the post-increment operator in scanf(), like this:
int *arr = malloc(length*sizeof(int));
if (arr == NULL)
exit(EXIT_FAILURE);
int *ptr = arr;
for (int i = 0; i < length; i++)
scanf("%d", ptr++);
but the more appropriate and readable way is - scanf("%d", &arr[i]).
Another big problem in your code is accessing the int values as long type.
The last() function parameter arr type is long and you are passing it int pointer typecasted to long *.
Note that the size of long and int may be different based on the platform. You cannot assume them to be of same size on all platforms.
Assume the case where int size is 4 bytes and long size is 8 bytes.
In this case, when accessing an int pointer using long type pointer then every object will be considered as 8 byte long and when you do arr+1 in last(), the pointer will be advance by 8 bytes and you will never get correct result.
Compiler must be throwing warning message on this statement:
printf(last((long *) arr, length);
because the printf() expects first argument as const char * and you are passing it int (return type of last()). You should give the first argument to printf() a string which contains appropriate format specifier('s).
Putting these altogether:
#include <stdio.h>
#include <stdlib.h>
int last(int arr[], int length) {
if (arr == NULL) {
return 1;
}
for (int i = 0; i < length - 1; i++) {
if (arr[i] == arr[length - 1]) {
return 1;
}
}
return 0;
}
int main(void) {
int length = 4;
int *arr = malloc (length * sizeof (*arr));
if (arr == NULL) {
exit(EXIT_FAILURE);
}
printf ("Enter %d numbers:\n", length);
for (int i = 0; i < length; i++) {
scanf ("%d", &arr[i]);
}
printf ("Duplicate found: %s\n", last (arr, length) == 1 ? "Yes" : "No");
return 0;
}

Program keeps crashing

I'm new to C, and pointers for that sake, so some help would be wonderful. My program has crashed multiple times when I try to run this code.
My method punkt_paa_linje returns an integer, instead of a string, because of pointers I assume. I have a very vague understanding of pointers, so an explanation would be very appreciated
char punkt_paa_linje(int linje_1[3], int linje_2[3], int punkt[3])
{
int i;
double t1;
double t2;
double t3;
for(i = 0; i < 3; i = i + 1 ){
double t = (punkt[i]-linje_1[i])/linje_2[i];
if(i == 0){
t1 = t;
} else if (i == 1){
t2 = t;
} else if (i == 2){
t3 = t;
}
}
if(t1 == t2 && t2 == t3){
return "true";
} else {
return "false";
}
}
And when I call the function, it returns 36
int main()
{
int et[] = {1,2,3};
int to[] = {4,5,6};
int tre[] = {7,8,9};
printf("%d\n", punkt_paa_linje(et, to, tre));
return 0;
}
EDIT: The reason I didn't insert an error message is because there is none
You should use char *punkt_paa_linje(int linje_1[3], int linje_2[3], int punkt[3]) instead of char punkt_paa_linje(int linje_1[3], int linje_2[3], int punkt[3]).
And use printf("%s\n", punkt_paa_linje(et, to, tre));. Then your code will run perfectly and give output true.
otherwise try :
#include <stdio.h>
int punkt_paa_linje(int linje_1[3], int linje_2[3], int punkt[3])
{
int i;
double t1;
double t2;
double t3;
for(i = 0; i < 3; i = i + 1 ){
double t = (punkt[i]-linje_1[i])/linje_2[i];
if(i == 0){
t1 = t;
} else if (i == 1){
t2 = t;
} else if (i == 2){
t3 = t;
}
}
if(t1 == t2 && t2 == t3){
return 1;
}
else {
return 0;
}
}
int main()
{
int et[] = {1,2,3};
int to[] = {4,5,6};
int tre[] = {7,8,9};
printf("%d\n", punkt_paa_linje(et, to, tre));
return 0;
}
Output :
1
I will try to explain your mistakes.
You are trying to return string literal. Which has type const char* and its seqention of characters in static storage duration memory, like this
n n+1 n+2 n+3 n+4 <-- Addresses
+---+---+---+---+----+
|'t'|'r'|'u'|'e'|'\0'|
+---+---+---+---+----+
And you are trying to return this string via char, which is one byte in memory, like this
n
+---+
|'t'|
+---+
So you have to return string instead of char, where string is passed by pointer to first character in C.
const char * punkt_paa_linje(int linje_1[3], int linje_2[3], int punkt[3])
...
return "true";
%d specifier expects parameter of type int, while your function now returns string, which has specifier %s.
printf("%s\n", punkt_paa_linje(et, to, tre));
Arrays in C are passed as pointer, so instead of parameters int linje_1[3] use can simply use int * linje_1 or int linje_1[] - its same, and it will accept arrays of all lengths.
Here is live demo. Just click run :-)
You should call your function char *punkt_paa_linje, cause here it just return a char and you need a str, which is a char * type.
So if you really want your function to return a char call it char punkt_paa_linje
There are multiple things when returning string from function in c:-
1.Never return string local variable from function since all local variable of a function will be store in stack and stack will be destroy once function return so local varaible will be invalid now.
2.If you want to retrun string function either you should use:-
1.Heap memory.
2.static variable.
3.String constant literal.
In your example if you want to return string you should use char * as a return type of a function.
char * punkt_paa_linje()
In place of using %d in printf in your code use %s for printing string.
printf("%s\n", punkt_paa_linje(et, to, tre));

C pointer arithmetic palindrome

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;
}

C array of pointers and malloc

I'm trying to get data from std stored into an array, using pointers. The main declares d as int *d; and the function is called using x = getdata(&d); When I step through it with gdb it dies at the first iteration of the for loop, when it tries *d[i]=val;
int getdata(int **d)
{
int count,val,i,j=0;
scanf("%d", &count);
d = malloc(sizeof *d * count);
for( i = 0; i < count-1; i++) {
scanf("%d",val);
*d[i]=val;
}
for ( i = 0; i < count; i++)
printf("Number %d\n",*d[i]);
return count;
}
The memory should be allocated as follows
*d = malloc(count * sizeof **d);
The values should be accessed as follows
(*d)[i] = val;
It is also not clear why you allocate count elements and only initialize count - 1 elements in the input cycle (and later print all count elements in output cycle).
*d = malloc(count * sizeof(int));
then
(*d)[i] = val
What you have is a pointer to an array, not an array of pointers.
1) malloc returns a void* so you need to assign the result to *d instead of d
2) the data size you want is of an int, not an int* (using *d gets you an int* where **d is an int)
*d = malloc(sizeof(**d) * count);
3) Indexing the array requires slightly different syntax
(*d)[i] = val;
printf("%d\n", (*d)[i]);
4) The second scanf needs a pointer, not an int
scanf("%d", &val);

C Program: square brackets when printing 2D character array

I am having a confusing issue -- for me at least, this may be very simple and I am missing something. I am trying to initialize a 2D array of variable size, The array is a part of a struct. I am having no issue allocating memory for the array but when I try to assign characters to the array, or print them I receive unexpected results =/
My last attempt has shown that no matter when character I assign to the array, when I print a '[' will be printed... that was the first time I was actually able to print anything. My previous attempts returned seg faults. Here is the code, what am I missing. Thank you.
typedef struct world_map {
char ** map_array;
int X, Y;
} MAP_s;
//
MAP_s * map;
int init_map_array(void) {
int i; // temp
map = malloc(sizeof (MAP_s));
map->X = 20; // Columns
map->Y = 10; // Rows
//
map->map_array = malloc(map->Y * (sizeof (char *)));
//
if (map->map_array == 0) {
printf("ERROR: out of memory!");
return -1;
} else {
for (i = 0; i < map->Y; ++i) {
map->map_array[i] = malloc(map->X * sizeof (char));
if (map->map_array[i] == 0) {
printf("ERROR: out of memory!");
return -1;
}
}
}
int curr_pos_x, curr_pos_y;
int limit_x = map->X;
int limit_y = map->Y;
//
for (curr_pos_y = 0; curr_pos_y < limit_y; ++curr_pos_y) {
for (curr_pos_x = 0; curr_pos_x < limit_x; ++curr_pos_x) {
map->map_array[curr_pos_y][curr_pos_x] = "#";
}
}
return 1;
}
int draw_map(void) {
int curr_pos_x, curr_pos_y;
int limit_x = map->X;
int limit_y = map->Y;
//
for (curr_pos_y = 0; curr_pos_y < limit_y; ++curr_pos_y) {
for (curr_pos_x = 0; curr_pos_x < limit_x; ++curr_pos_x) {
printf("%c", map->map_array[curr_pos_y][curr_pos_x]);
}
printf("\n");
}
}
int main(void) {
init_map_array();
draw_map();
//
printf("STRUCT: %i\n", sizeof (map));
printf("X: %i\n", sizeof (map->X));
printf("Y: %i\n", sizeof (map->Y));
printf("ARRAY: %i\n", sizeof (map->map_array));
return (EXIT_SUCCESS);
}
As a side note, those 4 printf at the end all return "4", I'm fairly certain that if a struct contains 3 elements which are each 4 bytes that it should be larger than 4 bytes itself...
Seems to work fine for me, but there is one error (somehow my GCC was "smart" enough to handle it but it's still an error):
map->map_array[curr_pos_y][curr_pos_x] = "#";
That assigns a char * (pointer to a char in the data segment) instead of a char which will of course result in weird characters. Change "#" to '#' and it should work.
Also, regarding your printfs at the end: they should look like this:
printf("STRUCT*: %lu\n", sizeof (map)); // Prints sizeof(MAP_s *) == sizeof(void *) == 4;
printf("STRUCT: %lu\n", sizeof (*map)); // Prints sizeof(MAP_s) == 16 on my system (iMac w/ Mac OS X),
// alignment and native pointer size might give you different values.
printf("X: %d\n", map->X); // Prints the X dimension. No sizeof.
printf("Y: %d\n", map->Y); // Prints the Y dimension. No sizeof.
You can't print the size of the map->map_array as sizeof works at compile-time and can only return constants for types where the size is known at compile-time. The only way to determine the size of map_array is to save the size argument you gave to malloc in a variable.
Try
map->map_array[curr_pos_y][curr_pos_x] = '#';
instead of
map->map_array[curr_pos_y][curr_pos_x] = "#";
map->map_array[curr_pos_y][curr_pos_x] is of type char and you are assigning a string constant to it.

Resources