Getting the size of my array - c

I am trying to get the size of my array but am having no luck...
I've read from various other threads that the way to grab the size of an array is:
theSize = (sizeof(array) / sizeof(array[0]))
But that seems to grab the empty elements of the array too.
How would we grab just the elements that are used up... for example:
char array[200][40];
for (i = 1; i < (sizeof(array) / sizeof(array[0])); i++) {
printf("%s", array[i-1]);
The output for an array that used 3 of its 200 elements would be...
First
Second
Third
(This is where it should stop, however it gives a bunch of question marks,
so I assume I'm grabbing memory i'm not supposed to use.
Note: I want it so that i < 3 for the loop (since the array has 3 elements used up)

There are two ways to do this.
The first way is to keep track of how many elements are used in a separate variable. Note that you must ensure that used is always less than of equal to the size of the array.
char array[200][40];
size_t used = 3;
for (int i = 0; i < used; ++i) {
printf("%s", array[i]);
}
The second way is to flag the first unused element with a special value, such as 0, and output all values until the flagged one. In your case, it would be natural to mark the end of the array with an empty string.
char array[200][40];
size_t size = sizeof(array) / sizeof(array[0]);
for (int i = 0; i < size && array[i][0] != 0; ++i) {
printf("%s", array[i]);
}

Related

why do I have a runtime #2 failure in C when I have enough space and there isn't many data in the array

I'm writing this code in C for some offline games but when I run this code, it says "runtime failure #2" and "stack around the variable has corrupted". I searched the internet and saw some answers but I think there's nothing wrong with this.
#include <stdio.h>
int main(void) {
int a[16];
int player = 32;
for (int i = 0; i < sizeof(a); i++) {
if (player+1 == i) {
a[i] = 254;
}
else {
a[i] = 32;
}
}
printf("%d", a[15]);
return 0;
}
Your loop runs from 0 to sizeof(a), and sizeof(a) is the size in bytes of your array.
Each int is (typically) 4-bytes, and the total size of the array is 64-bytes. So variable i goes from 0 to 63.
But the valid indices of the array are only 0-15, because the array was declared [16].
The standard way to iterate over an array like this is:
#define count_of_array(x) (sizeof(x) / sizeof(*x))
for (int i = 0; i < count_of_array(a); i++) { ... }
The count_of_array macro calculates the number of elements in the array by taking the total size of the array, and dividing by the size of one element.
In your example, it would be (64 / 4) == 16.
sizeof(a) is not the size of a, but rather how many bytes a consumes.
a has 16 ints. The size of int depends on the implementation. A lot of C implementations make int has 4 bytes, but some implementations make int has 2 bytes. So sizeof(a) == 64 or sizeof(a) == 32. Either way, that's not what you want.
You define int a[16];, so the size of a is 16.
So, change your for loop into:
for (int i = 0; i < 16; i++)
You're indexing too far off the size of the array, trying to touch parts of memory that doesn't belong to your program. sizeof(a) returns 64 (depending on C implementation, actually), which is the total amount of bytes your int array is taking up.
There are good reasons for trying not to statically declare the number of iterations in a loop when iterating over an array.
For example, you might realloc memory (if you've declared the array using malloc) in order to grow or shrink the array, thus making it harder to keep track of the size of the array at any given point. Or maybe the size of the array depends on user input. Or something else altogether.
There's no good reason to avoid saying for (int i = 0; i < 16; i++) in this particular case, though. What I would do is declare const int foo = 16; and then use foo instead of any number, both in the array declaration and the for loop, so that if you ever need to change it, you only need to change it in one place. Else, if you really want to use sizeof() (maybe because one of the reasons above) you should divide the return value of sizeof(array) by the return value of sizeof(type of array). For example:
#include <stdio.h>
const int ARRAY_SIZE = 30;
int main(void)
{
int a[ARRAY_SIZE];
for(int i = 0; i < sizeof(a) / sizeof(int); i++)
a[i] = 100;
// I'd use for(int i = 0; i < ARRAY_SIZE; i++) though
}

Why am I geting floating point exception?

This program worked fine when i manually iterated over 5 individual variables but when I substituted them for those arrays and for loop, I started getting floating point exceptions. I have tried debugging but i can't find were the error comes out from.
#include <stdio.h>
int main(void) {
long int secIns;
int multiplicadors[4] = {60, 60, 24, 7};
int variables[5];
int i;
printf("insereix un aquantitat entera de segons: \n");
scanf("%ld", &secIns);
variables[0] = secIns;
for (i = 1; i < sizeof variables; i++) {
variables[i] = variables[i - 1]/multiplicadors[i - 1];
variables[i - 1] -= variables[i]*multiplicadors[i - 1];
}
printf("\n%ld segons són %d setmanes %d dies %d hores %d minuts %d segons\n", secIns, variables[4], variables[3], variables[2], variables[1], variables[0]);
return 0;
}
The problem is you're iterating past the ends of your arrays. The reason is that your sizeof expression isn't what you want. sizeof returns the size in bytes, not the number of elements.
To fix it, change the loop to:
for (i = 1; i < sizeof(variables)/sizeof(*variables); i++) {
On an unrelated note, you might consider changing secIns from long int to int, since it's being assigned to an element of an int array, so the added precision isn't really helping.
Consider this line of code:
for (i = 1; i < sizeof variables; i++) {
sizeof isn't doing what you think it's doing. You've declared an array of 5 ints. In this case, ints are 32-bit, which means they each use 4 bytes of memory. If you print the output of sizeof variables you'll get 20 because 4 * 5 = 20.
You'd need to divide the sizeof variables by the size of its first element.
As mentioned before, sizeOf returns the size of bytes the array holds.
Unlike java's .length that returns the actual length of the array. Takes a little bit more of knowledge with bytes when it comes to C.
https://www.geeksforgeeks.org/data-types-in-c/
This link tells you a bit more about data types and the memory(bytes) they take up.
You could also do sizeOf yourArrayName/sizeOf (int). sizeOf(datatype) returns the size of bytes the data type takes up.
sizeof will give the size (in bytes) of the variables and will yield different results depending on the data type.
Try:
for (i = 1; i < 5; i++) {
...
}

How can I add an element to an array with the index number "array[number of items in array + 1]"

I'm trying to write a program which allows the user to add an element to an array:
#include <stdio.h>
#include <cs50.h>
int main(void)
{
string words[] = {"apple", "bear", "cards"};
string s = get_string("New word:");
s = words[(sizeof(words) / sizeof(words[0])) + 1];
for(int i = 0; i < sizeof(words) / sizeof(words[0]); i++)
{
printf("%s\n", words[i]);
}
}
It was my intention to add the element to the array as index number words[number of items in words + 1], but I receive the error message error: array index 4 is past the end of the array (which contains 3 elements) [-Werror,-Warray-bounds].
Over allocate words array:
#define MAX_WORDS 10
static int LoadPredefinedWords(string words, string preDefined) {...}
const string predefinedWords = {"apple", "bear", "cards", NULL};
string words[MAX_WORDS] = {NULL};
int NumberOfWords = LoadPredefinedWords(words, predefinedWords);
for(int i = NumberOfWords; i < MAX_WORDS; i++) ...
Or learn to use malloc, calloc and realloc, for which you can find documentation included with your compiler or online.
You could just take a shortcut:
#define MAX_WORDS 10
string words[MAX_WORDS] = {"apple", "bear", "cards", NULL};;
int NumberOfWords = 3;
for(int i = NumberOfWords; i < MAX_WORDS; i++) ...
But at some point you need to learn about iterating over NULL terminated arrays of pointers. We tend to mark the ends of things in C with a zero value. A string is just a char *, where the end of character sequence is marked by a \0, aka; null, and not be confused with NULL which is often defined as something like #define NULL void*.
So there's a better version that is less likely to have bugs due to arithmetic errors:
pArrayEnd = words + NumberOfWords;
for (string *pIterator = words; pIterator < pArrayEnd; pIterator++) ...
Bookmark this page for future reference. Read it from top to bottom once (maybe in several sittings), then spend 20 minutes per day studying it. Don't get caught up trying to understand every nuance, just absorb it while you're going off and writing toy programs.
Bookmark these as well:
http://code-reference.com/c
http://c-faq.com/
https://pubs.opengroup.org/onlinepubs/000095399/idx/headers.html
As far as I know, you need to create a dynamic array for such task.
Your array right now has a stable, constant size and cannot be changed. So it's not so simple just to add +1 element to the final structure.
Or in another case - you can create an array of bigger size and create a variable for storing the current amount of elements in your array. But it's a bad solution for cases when you need to do a random amount of "+1" operations.

C: Array not allocating more memory correctly

I'm fairly new to C and I'm working on a project. Given an integer array, I want to move all the zeros in it to the left of the array with the rest of the elements in any order to the right of all the zeros. The basic idea of my algorithm is to count the number of zeros in the array, create a new array with the number of zeros in it from the old array, and then "append" the rest of the non-zero integers onto this array. And then of course I print finished product.
int main(int argc, const char * argv[]) {
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
int n = 10, count = 0;
// counts the number of 0's in the original array
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
++count;
}
}
// creates a new array and makes each element 0
int *array = NULL;
for (int j = 0; j < count; ++j)
{
array = realloc(array, (j + 1) * sizeof(int));
array[j] = 0;
}
// adds the nonzero elements of the array to the new array
for (int l = count; l < n; ++l)
{
array = realloc(array, l * sizeof(int)); // getting an error here
if (a[l] != 0)
{
array[l+count] = a[l];
}
}
// prints the array out in a nice format
printf("%s", "{");
for (int k = 0; k < n-1; ++k)
{
printf("%d%s", array[k], ",");
}
printf("%d", array[n-1]);
printf("%s", "}\n");
free(array);
return 0;
}
I'm getting a "Thread 1: EXC_BAD_ACCESS (code=1, address=0x40)" error when I run this code. I think it's got to do something with invalid pointers to the new array, but I'm not sure how to fix it.
array[l+count] = a[l];
This accesses the memory block that array points at beyond its allocated size. You have to do it differently, using a second index:
// adds the nonzero elements of the array to the new array
int l = count;
for (int j=0; j < n; ++j)
{
if (a[j] != 0)
{
array = realloc(array, (l+1) * sizeof(int));
array[l] = a[j];
++l;
}
}
About your algorithm:
I think u don't need to create a new array, just use a int tmp as swap area, and a int foundZeroCount as index, u swap 2 numbers at a time.
About memory allocation:
If u want to allocate memory for a fixed size array, just use malloc() to allocate array once, later when u need to extend the array, just call realloc() once.
About memory reset:
Just use memset(), and don't need a loop.
Suggestion - about c programming
Try improve your c basic, especially about array / pointer / memory, and try to know more functions from glibc.
Books like <The c programming language 2nd>, GNU c library document, and <The linux programming interface> would be useful, I guess.
The problem is with array[l+count] = a[l]; right when you are done allocating your 'zero-array' it's size is 3 and then you try to access (l + count)'th position which is 6.
And even if you have fixed those issues with memory it still wouldn't work because a[l] and further may still be zeros. (Your initial array is doesn't have zeroes in the beggining, remember?)
And there is a couple of suggestions:
use calloc() to build your initial array of zeros because as man states:
The calloc() function allocates memory for an array of nmemb elements
of size bytes each and returns a pointer to the allocated memory. The
memory is set to zero
First allocate then set because operations with memory are quite taxing for performance. It would be better for you to first allocate some memory and work with it instead of reallocating it each step. It would be much easier to keep track of as well.
Other answers address your immediate issue, that
array[l+count] = a[l];
attempts to access outside the bounds of the allocated space to which array points. I'll focus instead on your approach to the problem, which is flawed.
Dynamic memory allocation is comparatively expensive. You do not want to do any more than necessary, and it is particularly poor form to reallocate many times to increase by small increments each time, as you do.
Since you know at compile time how many elements you will need, dynamic allocation is altogether unnecessary here. You could instead do this:
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
int array[10] = { 0 };
(Note also here that when an array initializer is provided, any array elements it does not explicitly initialize are initialized to 0.)
Even if you did not know at compile time how many elements you would need, it would be far better to perform the whole allocation in one chunk. Moreover, if you did that via calloc() then you would get automatic initialization of the allocated space to all-zeroes.
The count is known before defining the array. You can allocate memory using malloc as shown below.
array = malloc( count * sizeof(int)).
The error indicates you are trying to access address 0x40. This indicates one of the pointer has become NULL and you are trying to dereference ptr+0x40.
Before you start to hack away, take your time to consider the actual problem, which you have described as:
count the number of zeros in the array, create a new array with the number of zeros in it from the old array, and then "append" the rest of the non-zero integers onto this array.
Your comments say what the code should do, yet the code does something entirely different. Your algorithm to solve the problem is wrong - this, and nothing else, is the cause of the bugs.
To begin with, if the new array should contain all zeroes of the old array plus all non-zeroes, then common sense says that the new array will always have the same size as the old array. You don't even need to use dynamic memory allocation.
The code you have creates a new array and discards the old one, in the same memory location, over and over. This doesn't make any sense. On top of that, it is very ineffective to call realloc repeatedly in a loop.
You should do something like this instead:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
int main(int argc, const char * argv[]) {
int a[10] = {3, 0, 1, 4, 0, 0, 7, 20, 1, 5};
const int n = 10;
// counts the number of 0's in the original array
int zeroes = 0;
for (int i = 0; i < n; ++i)
{
if (a[i] == 0)
{
++zeroes;
}
}
// creates a new array and makes each element 0
// there's actually no need to allocate this dynamically at all...
int *array = calloc(1, sizeof(int[n]) );
assert(array != NULL);
// skip zeroes, ie "move the zeroes from the original array"
int* not_zeroes = array + zeroes; // point at first item to contain "not zeroes"
// adds the non-zero elements of the original array to the new array
for (int i = 0; i < n; ++i)
{
if(a[i] != 0)
{
*not_zeroes = a[i];
not_zeroes++;
}
}
// prints the array out in a nice format
printf("%s", "{");
for (int i = 0; i < n; ++i)
{
printf("%d,", array[i]);
}
printf("}\n");
free(array);
return 0;
}

Trying to find numbers repeated in two arrays

I am trying to find all of the numbers that are repeated across two arrays..
For example:
array1[2]: 1,2
array2[2]: 1,5
The number that repeats itself is 1 so we create a new array that will contain 1.
array3[2]: 1
My code is:
int func1(int *str, int *str2)
{
int i,j,temp,c[10];
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
if(*(str+i) == *(str+j))
{
temp = *(str+i);
*(str+i) = temp;
temp = *(c+i);
return c[i];
}
}
}
return 0;
}
What is the problem?(logically)
Thanks.
There are multiple problems:
The conditions in the two for loops are odd and probably wrong. They are equivalent to:
for (i = 0; i < str1[i]; i++)
for (j = 0; j < str2[j]; j++)
You should probably specify the sizes of the input arrays in the function interface.
In C, you must make sure you always know the sizes of the arrays.
You should probably specify the output array in the function interface.
Since you will need to know how many values were found in common, you'll need to return that number from the function.
Your choice of the names str1 and str2 is unusual. Not technically wrong, but probably not a good idea. Such names should be reserved for character strings, not arrays of integers.
Your local array c is barely used, and is not used safely.
Your code returns when it finds the first pair of numbers that match, not all possible matches.
The first two lines of the body of the if statement elaborately copies the value in str[i] back to itself via temp.
The third line of the body of the if statement copies an uninitialized value from array c into the variable temp.
The last line of the body of the if then returns that uninitialized value.
This adds up to changes such as:
int func1(int *arr1, int num1, int *arr2, int num2, int *arr3)
{
int k = 0;
for (int i = 0; i < num1; i++)
{
for (int j = 0; j < num2; j++)
{
if (arr1[i] == arr2[j])
arr3[k++] = arr1[i];
}
}
return k;
}
Note that this code assumes that the size of arr3 (the array, not the pointer itself) is as big as the product of num1 and num2. If both arrays contain a list of the same value, then there will be one row in the output array, arr3, for each pair so it could use num1 * num2 rows. This points out that the code does not deal with suppressing duplicates; if you need that (you likely do), then the body of the if statement needs to search through the current values in arr3 to check that the new value is not present. It would be wise to add another parameter, int siz3, to indicate the size of the third array; if you run out of space for values, you could then return -1 as an error indication.
The coded algorithm is quadratic (or, more accurately, proportional to the product num1 * num2). If you know the arrays are sorted on entry, you can reduce it to a linear algorithm (proportional to num1 + num2). With duplicate elimination, it is a little more expensive - it isn't quite as simple as 'cubic'. If you know the input arrays contain unique values (no duplicates), then duplicate elimination is obviously not necessary.
for(i=0;i<*(str+i);i++){
for(j=0;j<*(str2+j);j++){
Are wrong. You are applying '<' condition on an integer to itself and hence loop condition breaks. So, the loop never runs.
And why are you using these redundant statements?
temp = *(str+i);
*(str+i) = temp;
Also, this is wrong
temp = *(c+i);
return c[i];
Try more to correct those statements.If you can't do again, I will provide you a solution

Resources