How to find the length of a C array [duplicate] - c

This question already has answers here:
How do I determine the size of my array in C?
(24 answers)
Closed 6 years ago.
my professor has assigned a project where we need to make a reverse polish calculator in C (input in postscript syntax). I'm currently working on a method to find the length of the array of values I have scanned in (via .txt file). My current method is
int length(int list[]) {
int c = 0;
while(0 == 0) {
if(list[c] != '\0') {c++;}
else {break;}
}
return c;
}
and the call for it is
int sizeA = length(list);
printf("\n%d\n", sizeA);
It's currently only outputting the length as 0. Does anyone know why that might be and a fix to this method?
Thanks

The notion of "length" is a sort of tricky one in C (and low-level programming in general). If you have an array, the C compiler knows how large it is and provides an interface to the programmer to get that value in bytes: sizeof. The thing is, arrays are passed via pointers in C and determining the size via pointers is impossible without certain meta-information. Common methods to determine the length of an array are
appending an end marker to the array. Determining the length is simply a matter of iterating until the end marker is found and returning the number of iterations. Note that this renders the end marker's value unavailable for use as a value in the array.
just passing the size of the array around. Take the write system call as an example. Besides the file handle, it needs a pointer to the data and its length. Why its length as well? Because the pointer doesn't contain information about the length. So, either use a terminator like a null byte or pass the length explicitly. The former idea can be abandoned because the write system call is supposed to be generic; and to yield genericity, a null byte must be expected to be a possible value in the array, so it cannot be used as a terminator for reasons I uttered above.
Which one you actually end up using totally depends on the particular use case.
Apparently you decided to use the terminator-variant. \0 is the null byte, an ASCII character with code value 0x0. It's commonly used for terminating C-strings. strlen uses it to determine a C-string's length, for example. For int arrays, there is no such predefined terminator, so you need to come up with your own one. If you decide on \0, so be it, but I'd use the literal 0x0 instead because strictly-speaking, \0 is a character literal and that's just unfitting for ints.
To actually implement this, you'd need to append the terminating value to every int array, whose size you want to determine this way. Then write your function to get the length of such an int array just as you do, i.e., by iterating until the terminator is found.

Related

Checking if an array has at least 3 elements

I'm not sure how to approach this but put simply, a part of my homework states that I need to check if an array has at least 3 stored integer values and display an error message if it has less. The other part is getting the sum of all values in the array and show the output in the console.
I'm using RARS and the array is already declared in .data along with its values.
Arrays have a notion of length, which can be in bytes, or in element count, but unlike Java and C#, there is no standardized way to represent this notion of length in assembly language or in C code.
Sometimes the length is represented in the program by a constant.
Sometimes the length is represented in the program by a variable, more or less directly as a count of elements (though a program variable could also be an index referring to the last element, in which case that count is that variable + 1).
Sometimes the length is represented in the program by an end pointer — a pointer one element past the last, and also the place to store the next element, if one comes, when growing the array in place is possible.
Sometimes the length is encoded as a special element value, a sentinel or terminator, and to find the length one traverses forwards until that element is found — there must be sufficient storage to hold the real elements and the sentinel as well but it not considered an element of the array.
C-style strings are arrays of character, nul-terminated, so use the special character nul aka `\0' or just 0 as the terminator.
We can also pair a length value with a pointer value to compose a higher level notion of array with length into an object or structure.
This is not necessarily a complete list, since programmers can do as they like.  (Other schemes are possible, such as storing the length at the beginning of the array, or in front of the array, i.e. at position -1 in the array).
A function taking an array as a parameter will often also take another parameter that is the length, but in the case of int main(int argc, char *argv[]) we see the length being passed as the first parameter and the array as the second..
It would be a logic error for a program to have an array whose length is unknown and not computable.
You will need to determine the method for representing the length, and then compare the length with your constant 3 as required.
For example, if the method is an end pointer, then you can subtract: end pointer - beginning pointer (the array base, or address of first element), and then divide that result by the array's element size, which will yield a count of the number of elements.

Alternative to strlen not breaking on 0 [duplicate]

This question already has answers here:
How to find the size of an array (from a pointer pointing to the first element array)?
(17 answers)
Closed 4 years ago.
Is there any better way of getting the right length of array containing digits?
I have an array of digits: 0, 0, 1 and I try to get length of it. It obviously breaks and returns 0. I am new to C but I tried to make custom strlen function:
int custom_strlen(char *str) {
for(int i = 1; ;i++) {
if (str[i] == 0) {
return i;
}
}
return -47;
}
but it is not that efficient and in some cases returns unexpected values as well. The expected out put would be 3 in this case.
Is there any function to use?
An array of integers is not a string. C arrays do not contain length information inherently. The way strlen works is that C strings are null terminated, meaning the last character is NUL (null character), which is 0. Otherwise, there is just no way to know how long an array is.
I think you may be wanting to do an array of '0','0','1'. Can you post the array you are using?
As mentioned, C strings are null terminated.
The only choices are
Using a string terminated with some special character that you watch for (like a null) or
Keeping track of how long the string is when you create it.
FWIW, if it's not null terminated, it's not actually a string in C, it's just memory that contains chars that you happen to be interpreting as a string.

Copying and comparing individual element from 2D array to another array in C

char first_array[5][4] = {"aaa","bbb","ccc","ddd","eee"};
char second_array[1][4];
How would I copy, for example, the third element in first_array ("ccc") and save it to second_array?
The syntax below is clearly wrong, but this is what I'm asking for:
second_array[0] = first_array[2];
Also, after copying, I also want to know how to compare elements in the two arrays. Again, the syntax below might be wrong, I'm just explaining what I'm trying to do:
if(second_array[0] == first_array[2]){ printf("yes"); } //should print yes
You can't assign to arrays in c, you can fill arrays with some library functions like strcpy(), so
second_array[0] = first_array[2];
would be
strcpy(second_array[0], first_array[2]);
you must however ensure that the destination array fits the number of characters you are copying to it.
If you try to compare two strings in c, you can't do it through the == operator, because strings in c are arrays of char which contain a sequence of non-nul characters followed by a nul character, so if you write this
if (second_array[0] == first_array[2])
even when you succeeded at copying the data, the result will be most likely false, because you are not comparing the contents of the arrays, but their addresses, so to compare them correctly there is also a function strcmp() then the correct way of comparing the strings is
if (strcmp(second_array[0], first_array[2]) == 0)
The functions above require you to include the string.h header, and also that the passed strings are strings in the c sense, i.e what I described above.
I was recently trying to do this, as well: it is not possible to do this sort of direct assignment in C.
When you write first_array[0], the compiler will read that as an address which points to the first element (character) of first_array[2], not the entire string. When you run the assignment, if it were to work, it would only set the first character.
The easiest way is to use strncpy or memcpy (or a loop to cycle through the string.

Array fill in C

I have this problem with a lot of arrays in my program, and I can't understand why. I think I miss something on array theory.
"Someone" adds at the end of my arrays some sort of char characters such as ?^)(&%. For example if I have an array of lenght 5 with "hello", so it's full, sometimes it prints hello?()/&%%. I can undesrtand it can occur if it's of 10 elements and i use only 5, so maybe the other 5 elements get some random values, but if it's full, where the hell gets those strange values?
I partially solve it by manaully adding at the end the character '\0'.
For example this problem occurs, sometimes, when I try to fill an array from another array (i read a line form a test file with fgets, then I have to extract single words):
...
for(x=0;fgets(c,500,fileb);x++) { // read old local file
int l=strlen(c);
i=0;
for (k=0;k<(l-34);k++) {
if(c[k+33]!='\n') {
userDatabaseLocalPath[k]=c[k+33];
}
}
Thanks
Strings in C are terminated by a character with the value 0, often referred to as a character literal, i.e. '\0'.
A character array of size 5 can not hold the string hello, since the terminator doesn't fit. Functions expecting a terminator will be confused.
To declare an array holding a string, the best syntax to use is:
char greeting[] = "hello";
This way, you don't need to specify the length (count the characters), since the compiler does that for you. And you also don't need to include the terminator, it's added automatically so the above will create this, in memory:
+-+-+-+-+-+--+
greeting: |h|e|l|l|o|\0|
+-+-+-+-+-+--+
You say that you have problems "filling an array from another longer array", this sounds like an operation most referred to as string copying. Since strings are just arrays with terminators, you can't blindly copy a longer string over a shorter, unless you know that there is extra space.
Given the above, this code would invoke undefined behavior:
strcpy(greeting, "hi there!");
since the string being copied into the greeting array is longer than what the array has space for.
This is typically avoided by using "known to be large enough" buffers, or adding checks that manually keep track of the space used. There is a function called strncpy() which sort of does this, but I would not recommend using it since its exact semantics are fairly odd.
You are facing the issue of boundary limit for the array.. if the array is of size 5 , then its not necessary that the sixth location which will be \0 be safe.. As it is not memory reserved/assigned for your array.. If after sometime some other application accesses this memory and writes to it. you will lose the \0 resulting in the string helloI accessed this space being read. which is what you are getting.

char arrays in c end char

I'm reading from a socket into a char array and I want to know when to stop reading. The terminating char sequence is '\r\n\r\n'. If what I read in is smaller than the array size I don't want to loop around anymore. My question is really if I load into the array say 10 characters and it has length 20, what is the array[20] index set to?
Thanks
edit:
Sorry I did mean array[19], setting the last index to NULL as suggested? seems like an appropriate solution. To give some more detail, I need to know when all the data has been read from the socket. I don't know the size of the data to be sent only that it terminates with '\r\n\r\n'
If it has length 20, then array[20] is outside your array and shouldn't be accessed like that (unless you want to do some sort of wizardy and hacking beyond your explanation).
EDIT: If you meant array[19], then no. You need to set the NUL character at array index = size of string received. ASCII NUL character '\0' is not C NULL constant, which for 32-bits machines would be 4-byte long, and that would potentially overwrite data.
My question is really if I load into the array say 10 characters and it has length 20, what is the array[20] index set to?
It's not set to anything. Feel free to set it to something yourself (for instance, a null terminator).
Generally in the name of efficiency C does not initialize an array to any known value, so you'll get whatever was leftover in memory.
You can explicitly initialize the array to fix this. A common initialization for a sequence of bytes is zero, which won't match your search string and will act as and end-of-string if you try to process the array as a string.
char array[20] = {0}; /* the extra elements are always initialized to 0 as well */
char array2[20];
memset(array2, 0, sizeof(array2));
I'll presume you had a typo and meant array[19] instead of array[20].
In C, when the array is malloced, the array has whatever is leftover in the malloced chunk of memory. If you copy several chars into the array and want the chars to be read as a string, you have to set the next char after the last char to be '\0'.
Since you know when to stop reading, you could set the next char in your array to '\0' to mark the end of the string.
To the best of my knowledge, the ANSI C standard does not describe what value should be allocated to uninitialized arrays. Consider it to be garbage and assume that nothing can be said about it. Although, I have mostly observed them to be 0 (using gcc). This implementation may vary across compilers.
Also, this value could depend on the previous steps which have modified array[19] (as mOskitO pointed out, array[20] is out of bounds).

Resources