How to access and modify arrays of strings in functions? - c

I am fairly new to C and I just fell on pointers, I have been doing exercises on it and I looked all over this site and google but I just can't find what I'm looking for. (maybe from inexperience with terminology)
Context I have to use a specific prototype (that the grading program uses) to pass me an array of strings however since I'm limited to 25 lines per function I have tried to pass that same array of strings to another function to no avail, so this was my workaround:
#include <stdlib.h>
int ft_ultimate_range(int **range, int min, int max)
{
int *arr;
int i;
int j;
j = 0;
i = min;
if (min >= max)
{
*range = NULL;
return (0);
}
arr = malloc(sizeof(int) * ((long long int)max - (long long int)min));
*range = arr;
if(arr == NULL)
return (-1);
while (i < max)
{
*range[j] = i;
i++;
j++;
}
return (j);
}
However I'm getting a EXC_BAD_ACCESS (code=1) on vs code at *range[j] = i;/ seg. fault when execute on the terminal.
I don't understand why this is as I'm trying to assign values to the passed array if I take the star out I get (incompatible int to pointer conversion assigning to 'int *' from 'int').
What is going on?
Also can you also please point me to a thread explaining how to pass arrays of strings (or int's between functions)?
Edit: The question if it helps. (I just want to understand what's wrong)
Create a function ft_ultimate_range which allocates and assigns an array of ints.
This int array should contain all values between min and max. Min included - max excluded.
Here’s how it should be prototyped :
int ft_ultimate_range(int **range, int min, int max);
The size of range should be returned (or -1 on error).
*If the value of min is greater or equal to max’s value, range will point on NULL and it should return 0

As pointed out in the comments, *range[i] can be read as *(range[i]), following the rules of operator precedence. This means you are attempting to step into memory adjacent to the address provided by the caller.
Using (*range)[i], or simply using the arr variable you created earlier, will solve this.
while (i < max) {
arr[j] = i;
i++;
j++;
}
With that said, your code is slightly convoluted. While I don't fully agree with the idea of line limits for functions, if those are the constraints you are going to learn under you'll want to try and break problems down into their simplest components & steps needed.
The only additional variables we need are the computed length of the range, and the index we are inserting values into. There's no need to cast our computed length due to implicit conversions. min already provides our starting value.
size_t range(int **dest, int min, int max) {
if (min >= max)
return *dest = NULL, 0;
size_t length = max - min;
if (!(*dest = malloc(sizeof **dest * length)))
return -1;
for (size_t i = 0; i < length; i++)
(*dest)[i] = min++;
return length;
}
Note in this example I've used size_t as it
[...] can store the maximum size of a theoretically possible object of any type (including array).
and is the most appropriate type for indexing said array. You'll want to change every instance of size_t to an int to match your spec, however.
In C, a string refers to a sequence of nonzero bytes, followed by the NUL terminating byte ('\0').
Examples of strings:
const char *foo = "hello, world";
char bar[] = "Alice";
char baz[] = { 'B', 'o', 'b', '\0' };
There are no strings in your code. An example of passing an array of strings can be found by looking at the main function, and its second argument.

Related

(C) Can't read string array values between functions

I have one char strings pointers array, lets call it "str_array".
I also have 3 strings:
1."Hello"
2."World"
3."Today"
(Every string ends with \0)
And I have this function, that receives our str_array, the size of it, and another pointers arr that is not releveant for my question.
The problem that I encounter, is that function "scanString" receives NULL, or garbage values, instead of the strings inside str_array.
unsigned int RemoveFromStrArray(char*** str_array, unsigned int str_array_size, char** ptr_to_chars_array)
{
int k = 0;
while (k != str_array_size)
{
// This is the part where im trying to scan str_array strings.
scanString(*str_array[k]);
str_array++;
k++;
}
}
int scanString(char* string)
{
int c = 0;
int counter = 0;
while (string[c] != '\0')
{
if (string[c] == 1)
{
moveOneBack(string, c);
c--;
counter++;
}
c++;
}
return c;
}
I've been trying multiple alternative ways to scan str_array string arrays.
But all of my times I just had to deal with garbage values or NULL strings.
How do I reach str_array strings, that would be passed by reference to scanString?
Picture of what I'm talking about:
BIG THANKS IN ADVANCE!
unsigned int RemoveFromStrArray(char*** str_array
You've got at least one too many indirections there. From your drawing, str_array refers to an array, so it's effectively a pointer, and the values in the array are pointers to char. You don't seem to be changing the array itself, e.g. you're not making str_array refer to some other array of strings, so there's no need to pass the address of the array. So char ** is closer to the type you want.
str_array++;
I'm not sure why you're incrementing str_array and using k as an index into the array. Although it's safe to modify parameters locally like that, it's nice to avoid it so that you can refer to them while debugging. Consider this:
unsigned int RemoveFromStrArray(char** str_array,
unsigned int str_array_size)
{
int k = 0;
while (k != str_array_size)
{
char *string = str_array[k];
scanString(string);
k++;
}
}
That is, the values in str_array are of type char *, so str_array[k] has that type. Copying it into a temporary variable string makes it a little easier to see what's going on. (I removed the last parameter, ptr_to_chars_array, to keep things simple and because it's not used. You'll add it back if you have plans for it, I'm sure.)
A for loop would be a little more compact but otherwise equivalent:
unsigned int RemoveFromStrArray(char** str_array,
unsigned int str_array_size)
{
for (int k = 0; k < str_array_size; k++)
{
char *string = str_array[k];
scanString(string);
}
}

Return an array while telling him the length of this array?

I want to filter an strings array passed in, something like this:
char **
filter_vids(char **vids, size_t n) {
int i;
int count = 0;
char ** filted = malloc(n * sizeof(char *));
for(i = 0; i < n; i++){
filted[i] = (char*)malloc(50 * sizeof(char));
}
for(i = 0; i < n; i++) {
if(some_filter(vids[i])) {
strcpy(filted[count++], vids[i]);
printf("in filter:%s\n", vids[i]);
}
}
return filted;
}
But the caller may not known the length of return array, it's extractly the counter variable, so what's the best practice of returning an array while telling him the right length of array?
such as
char **
filter_vids(char **vids, size_t n, int *output_length)
It's the best practice of using output_length?
I edit this function to this, as your suggestions:
char **
filter_vids(char **vids, size_t n) {
int i;
int count = 0;
char ** filted = malloc((n + 1) * sizeof(char *));
for(i = 0; i < n; i++) {
if(vids[i][0] <= 'f') {
filted[count++] = strdup(vids[i]);
}
}
filted[count] = NULL;
return filted;
}
To pass a pointer to an integer length variable whose value is then set in the function is certainly a good way. As Malcolm said, it is also general and can be used for sets of values which do not have an "invalid" member.
In the case of pointers with their invalid null pointer value one can mark the end of valid entries with a null pointer. For example, the array of string pointers which the C run time uses to pass command line arguments to main is thus terminated.
Which method to choose depends a little on how the caller wants to use the resulting array. If it is processed sequentially, a (while *p){ ..; ++p; } feels idiomatic. If, on the other hand, you need random access and must perform the equivalent of a strlen before you can do anything with the array, then it is probably better to return the length via a pointed-to length variable right away.
Two remarks:
First, note the difference between
a valid pointer to an empty string (if somebody called, let's say, myProg par1 "" par2, argv[2] could be a valid pointer to a zero byte);
and a null pointer which is pointing nowhere; in the example, argv[4] would be the null pointer, indicating the end of the argument list.
Second, You malloc more memory than you need which is wasteful in the case of longer strings and/or strict filters. You could instead allocate the string on demand inside the if clause.
These are common options:
Receive the allowed size as parameter by pointer, overwrite it with the actual size, return the array as return value.
Receive the output array as parameter by pointer, update as required, return the actual size as return value.
Append a sentinel value to the output array (here a null pointer), as suggested in the other answer.
Use a more sophisticated data structure as a return value. You could use a struct, which stores the size alongside the array or a linked list.
Example (untested):
typedef char* mystring;
typedef mystring* mystringarray;
typedef struct { mystringarray *arr; size_t size } mysizedstringarray;
/* returns filtered array, size will be updated to reflect the valid size */
mystringarray* myfun1(mystringarray in, size_t* size);
/* out will be allocated and populated, actual size is returned */
size_t myfun2(mystringarray in, size_t size, mystringarray* out);
/* output array contains valid items until sentinel value (NULL) is reached */
mystringarray* myfun3(mystringarray in, size_t size);
/* returns filtered array with actual size */
mysizedstringarray myfun4(mystringarray in, size_t size);

Muti-dimensional Array

I have a trouble regarding to multi-dimensional array in C.
We have to make a multi-dimensional array in which in which the user has to input the size of the array. After that according to the size C has to create a multi-dimensional array. Remember, in the center there always has to be '1'.
At every side of one there should be '2'. on every side of '2' there should be '3', depends upon the size of array. Also shown in image.
can locate the mid point of an array but when i do this: int Array[size/2][size/2] it gives me error. and how i can adjust other 2,3 and and other numbers at the sides?
This is the code I have written for now:
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main(){
const size;
printf("Enter the size: ");
scanf("%d", &size);
int Grid[size][size];
Grid[size/2][size/2] = 1;
printf("%d", Grid[1][1]);
return 0;
}
Firstly, you shall not do such a thing in C :
int grid[size][size];
If you're interested in knowing why, look at C11's Initialization paragraph :
No initializer shall attempt to provide a value for an object not contained within the entity being initialized.
The type of the entity to be initialized shall be an array of unknown size or a complete object type that is not a variable length array type.
Then, I'm not a fan of
const size;
Since the type is not explicit and your variable isn't const here. Even if you're using scanf, you do modify the value of size during the function.
But then, let's hit the problem ;)
I suggest you use a function to allocate your array. It will help clarifying your code :
int** create_array(int size)
{
int i;
int** array;
i = 0;
// You allocate the first dimension of your array
// (the one that will contain other arrays)
array = malloc(size * sizeof(int *));
if (array != NULL)
{
while (i < size)
{
// You allocate each 'sub-array' that will contain... ints !
array[i] = malloc(size * sizeof(int));
i += 1;
}
}
return (array);
}
Now this function returns a well-allocated array of the size you want. Don't forget to check if it's NULL in your calling function, and to free it (if it has been allocated).
To free the array, I'll let you write the function yourself, since it is very similar to the initialization. But still, be careful considering some sub-array might be NULL!
Then the initialization. The most simple way I can think of is iterating on your array and calculating the delta from the center.
int most_far;
////
/// Insert the loop stuff here...
//
if (x == size/2 && y == size/2)
array[x][y] = 1;
else
{
// You could use a ternary here but I don't know if you're familiar with them
// You're getting the position that is the most far from center...
if (abs(x - size/2) > abs(y - size/2))
most_far = abs(x - size/2);
else
most_far = abs(y - size/2);
// With this position, you calculate the 'distance' between the center and your position.
// This distance is your number ! :D
array[x][y] = most_far;
}
//
/// End of the loop, interations, etc...
////
Little tip : I suggest you do the population stuff in some function that returns a boolean. This boolean will be false if one sub-array has been found NULL during the population. And if it's the case, you probably don't want to read/display it !
Pfiouh, what a massive answer I wrote !
Hope it won't scare you (and that you'll find some help in it)
If your targeted element is in position a[2][2] then the condition will be some what like this.
Consider i to be row and j to be column.
if(a[i+1][j]==a[i+1][j+1]==a[i+1][j-1]==a[i][j+1]==a[i][j-1]==a[i-1][j]==a[i-1][j+1]==a[i-1][j-1])
flag=1; \\any process you want
and you can only assign constant to an array while declaring it. You can't assign a value like
int array[size/2][size/2];
There are two ways of doing this you might consider:
Filling entries in a growing square. (i.e., filling all the 1s, then the 2s, then the 3s, ...)
Figuring out a "formula" or procedure for each row.
Looking at the first method:
void fillSquare(int **arr, int n, int size)
{
fillSquareTopSide(arr, n, size);
fillSquareLeftSide(arr, n, size);
fillSquareRightSide(arr, n, size);
fillSquareBottomSide(arr, n, size);
}
where n is the current number (1, 2, or 3) and size is 3. And then a possible implementation of fillSquareTopSide:
void fillSquareTopSide(int **arr, int n, int size)
{
for(int i = size - n; i < size + n; i++)
arr[size - n][i] = n;
}

Find the Array length inside Function

Based on This Question Calculate Length of Array in C by Using Function i really need an explanation.
Let's say we have an Array like this:
int arr[] = {1,2,3};
here arr has the length 3, so passing into a Function will decay to Pointer and we lose track of its Length.
What happens if we Null terminate this array using '\0' like this:
int arr[] = {1,2,3,'\0'};
And pass it to a function like this:
void foo(int *arr){
int length = 0;
while(arr[length] != '\0'){
length++;
}
printf("Length = %d\n",length);
}
Is this ok?
I wrote the following code:
#include<stdio.h>
void foo(int *arr);
int main(void){
int arr1[] = {10,'\0'};
int arr2[] = {12,44,'\0'};
int arr3[] = {87,1,71,'\0'};
int arr4[] = {120,15,31,82,'\0'};
int arr5[] = {28,49,16,33,11,'\0'};
int arr6[] = {19,184,90,52,38,77,'\0'};
int arr7[] = {2,17,23,41,61,78,104,'\0'};
int arr8[] = {16,92,11,35,52,118,79,44,'\0'};
int arr9[] = {20,44,33,75,49,36,9,2,11,'\0'};
int arr10[] = {92,145,24,61,99,145,172,255,300,10,'\0'};
foo(arr1);
foo(arr2);
foo(arr3);
foo(arr4);
foo(arr5);
foo(arr6);
foo(arr7);
foo(arr8);
foo(arr9);
foo(arr10);
return 0;
}
void foo(int *arr){
int length = 0;
while(arr[length] != '\0'){
length++;
}
printf("Length = %d\n",length);
}
And i got the following Output:
Length = 1
Length = 2
Length = 3
Length = 4
Length = 5
Length = 6
Length = 7
Length = 8
Length = 9
Length = 10
Which prints the Length of all 10 arrays.
Now I'm confused here, because as far of my concern, as I read in some books, there is no way to make it work.
Why foo prints the length of all arrays?
It is illegal to use something like int arr[] = {1,2,3,'\0'}; ?
I know that if the Array has a 0 inside like this int arr[] = {1,2,0,3,4}; the length will be 2, but this is not my question.
This is how C-strings mark their end and length. And as they're just char arrays, naturally you can apply the same to other types of arrays as well.
Just remember that calculating the length of such an array through a pointer has a linear time complexity.
It is illegal to use something like int arr[] = {1,2,3,'\0'}; ?
No. It's perfectly legal. '\0' is an int which is same as 0. It's no different to using any number as marker to identify the end of the array. For example, you can use -1 if you array is going to contain only positive number. So your approach is valid.
The reason you wouldn't usually see in practice it's kind of needless to iterate over an array when you can simply pass it as an extra argument, which is easily understandable from maintenance point of view.
int arr[1024];
size_t len = sizeof arr/sizeof a[0];
func(arr, len);
void func(int *a, size_t length) {
}
Compare this with your approach.
Also, the size is calculated at compile-time whereas in your approach you have iterate over the array. Choosing the right sentinel could become difficult ( o or -1 or whatever) if it's also needed to be an element of the array.
Sidenote: '\0' is really 0 here, as your store ints.
You're using a sentinel. C-style strings have been using this method for decades to mark where the string finishes. It has the same benefits, but it also has the same drawbacks.
As long as you maintain the invariant that the sentinel occours only at the last place of the array you'll be able to get the length of the array. In O(N) time, as you have to traverse the sequence.
Note that you can shrink the sequence by terminating it earlier with a sentinel:
1 2 3 4 0 //
1 2 3 0 * // * as in: anything
But as soon as you do this, you cannot known the size of the array anymore. Even though you could technically append an extra element, a function without knowing the context cannot safely do this. In essence, you know the size of the sequence, but you don't known the size of the array anymore.
If you need a method to use to allow you to carry the array length with the array then try using one of these approaches.
Store the length in the start of the array
So (ideally) array[0], the first element would be a length.
The catch is that that only works if your array has a suitable type and the length fit in that type. You can in principle use union to define an element large enough to hold different types of data, including the length, but it's potentially wasteful.
Maintain a structure to store the array length and a pointer to the array data.
This is something like :
struct arrayinfo_s {
int length ;
char *data ;
};
char name[1000] ;
struct arrayinfo a ;
a.length = sizeof(name) ;
a.data = name ;
myfunc( &arrayinfo ) ;
There are many variations on this possible.
The "standard" convention.
As someone already mentioned, it is typical to track the array length and pass it as a separate parameter to the function.
myfunc( array, length ) ;
If array is a fixed size declared like e.g. int nums[100] ; then you can use sizeof(nums) if the variable was declared in the same function as you used sizeof() or globally.
There is also a variation on this for allowing a function to return an array of unknown length. Typically you would do something like returning a point to the array, but pass a parameter that is a pointer to some integer type to store the length of the new array in.
char *newstuff( int *newlength )
{
char *p = NULL ;
p = malloc( 102 ) ;
if( p == NULL )
{
*length = 102 ;
return p ;
}
else
{
*length = 0 ;
return NULL ;
}
}

To know the size of an array in c

I am learning C language. I want to know the size of an array inside a function. This function receive a pointer pointing to the first element to the array. I don't want to send the size value like a function parameter.
My code is:
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
while( *(a + i) != NULL )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
My code doesn't show any number. How can I fix it?
Thanks.
Arrays in C are simply ways to allocate contiguous memory locations and are not "objects" as you might find in other languages. Therefore, when you allocate an array (e.g. int numbers[5];) you're specifying how much physical memory you want to reserve for your array.
However, that doesn't tell you how many valid entries you have in the (conceptual) list for which the physical array is being used at any specific point in time.
Therefore, you're required to keep the actual length of the "list" as a separate variable (e.g. size_t numbers_cnt = 0;).
I don't want to send the size value like a function parameter.
Since you don't want to do this, one alternative is to use a struct and build an array type yourself. For example:
struct int_array_t {
int *data;
size_t length;
};
This way, you could use it in a way similar to:
struct int_array_t array;
array.data = // malloc for array data here...
array.length = 0;
// ...
some_function_call(array); // send the "object", not multiple arguments
Now you don't have to write: some_other_function(data, length);, which is what you originally wanted to avoid.
To work with it, you could simply do something like this:
void display_array(struct int_array_t array)
{
size_t i;
printf("[");
for(i = 0; i < array.length; ++i)
printf("%d, ", array.data[i]);
printf("]\n");
}
I think this is a better and more reliable alternative than another suggestion of trying to fill the array with sentinel values (e.g. -1), which would be more difficult to work with in non-trivial programs (e.g. understand, maintain, debug, etc) and, AFAIK, is not considered good practice either.
For example, your current array is an array of shorts, which would mean that the proposed sentinel value of -1 can no longer be considered a valid entry within this array. You'd also need to zero out everything in the memory block, just in case some of those sentinels were already present in the allocated memory.
Lastly, as you use it, it still wouldn't tell you what the actual length of your array is. If you don't track this in a separate variable, then you'll have to calculate the length at runtime by looping over all the data in your array until you come across a sentinel value (e.g. -1), which is going to impact performance.
In other words, to find the length, you'd have to do something like:
size_t len = 0;
while(arr[len++] != -1); // this is O(N)
printf("Length is %u\n", len);
The strlen function already suffers from this performance problem, having a time-complexity of O(N), because it has to process the entire string until it finds the NULL char to return the length.
Relying on sentinel values is also unsafe and has produced countless bugs and security vulnerabilities in C and C++ programs, to the point where even Microsoft recommends banning their use as a way to help prevent more security holes.
I think there's no need to create this kind of problem. Compare the above, with simply writing:
// this is O(1), does not rely on sentinels, and makes a program safer
printf("Length is %u\n", array.length);
As you add/remove elements into array.data you can simply write array.length++ or array.length-- to keep track of the actual amount of valid entries. All of these are constant-time operations.
You should also keep the maximum size of the array (what you used in malloc) around so that you can make sure that array.length never goes beyond said limit. Otherwise you'd get a segfault.
One way, is to use a terminator that is unique from any value in the array. For example, you want to pass an array of ints. You know that you never use the value -1. So you can use that as your terminator:
#define TERM (-1)
void print(int *arr)
{
for (; *arr != TERM; ++arr)
printf("%d\n", *arr);
}
But this approach is usually not used, because the sentinel could be a valid number. So normally, you will have to pass the length.
You can't use sizeof inside of the function, because as soon as you pass the array, it decays into a pointer to the first element. Thus, sizeof arr will be the size of a pointer on your machine.
#include <stdio.h>
void ShowArray(short* a);
int main (int argc, char* argv[])
{
short vec[] = { 0, 1, 2, 3, 4 };
short* p = &vec[0];
ShowArray(p);
return 0;
}
void ShowArray(short* a)
{
short i = 0;
short j;
j = sizeof(*a) / sizeof(short);
while( i < j )
{
printf("%hd ", *(a + i) );
++i;
}
printf("\n");
}
Not sure if this will work tho give it a try (I don't have a pc at the moment)

Resources