I'm trying to assign a number in an array one by one. If the pointer is pointing at the first element of the array, then it means that the array is empty and it will be assigned with a number. But for some reason, it doesn't seem to move the pointer to the next element. How can I fix this?
unsigned char number= '1'; //random number
unsigned char array[8];
int count = 0;
unsigned char *ptr;
int main(){
while(count < 5){
reserve();
count ++;
ptr++; //move to next element
}
}
void reserve(void){
if(ptr = array){ //if pointer is at the first element of the
*ptr = number; //array then it means it's empty
}
else{ //not empty array
*ptr = number;
}
}
EDIT:
if(ptr = array) was a typo. The problem was not assigning the initial value for *ptr. I have a new question, though. Someone who commented below said not to use global variables. I had thought about using static unsigned char *ptr = array in the reserve function, but that would reset to the initial assignment when it is called again. What did that person mean by using explicit dependencies?
Edit: The first paragraph is incorrect. See Oka's comment.
You are initialising a pointer but it doesn't point to anything. This is considered dangerous because when you use it, it just points to a random (not actually random but may as well be) memory address.
You could use (array + count) to step through the array (best not to step array itself as then you run the risk of forgetting and losing the address to the array creating a memory leak).
Also as some comments have pointer out you need to use == for comparison.
int main(){
uint number = 1;
unsigned char array[8];
// a for loop is a good way to have a loop that ends when a condition is met with an incrementing variable
for (int count = 0; count < 4; count++){
reserve(array+count);
}
}
void reserve(char * ptr){
if(ptr == array){ //if pointer is at the first element of the
*ptr = number; //array then it means it's empty
}
else{ //not empty array
//do someting else? Or just set them all equal to number
}
}
Related
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char** AllocateShoppingList(int numFoods);
char* AllocateItem();
int DetermineNumberOfCandy(char** list, int numFoods);
int main()
{
char** stringArray;// pointer to pointers
char* words; //pointer to char array
//1. ask the user how many foods are on their list
int foods;
printf("How many foods on the shopping list?\n");
scanf("%d", &foods);
//2. call the AllocateShoppingList function and store the result
stringArray = AllocateShoppingList(foods);
//3. for X times (user's previous input), call the AllocateItem function
// and store the result in the list of pointers (step 2)
for(int i =0;i < foods; i++){
words = AllocateItem();
stringArray[i] = words;}
//strcpy(stringArray[i],words); why not work?
//4. call the DetermineNumberOfCandy function, and print the result
printf("Candy appeared this many times: %d\n",DetermineNumberOfCandy(stringArray, foods));
//5. free up all of the pointers that are held by the shopping list
//6. free up the shopping pointer itself
free(words);
free(stringArray);
}
int DetermineNumberOfCandy(char** list, int numFoods)
{
//0. setup a counter variable
int counter = 0 ;
//1. for each pointer in the shopping list:
//1a. compare the string at the pointer's address to "candy"
for(int i =0; i< numFoods; i++)
if (strcmp(list[i],"candy")==0)
// why you dont have to dereference it
// this concept works with single pointers
// does it work with double or tripple pointers as long as it orignally points to the string?
counter++;
//1b. if it is candy, then tick up the counter variable
//2. return the counter variable
return counter;
}
char** AllocateShoppingList(int numFoods)
{
return calloc(numFoods, sizeof(char*));
//1. allocate memory that can hold X pointers (X = numFoods)
//2. return the memory address holding this pointer to pointers
}
char* AllocateItem()
{
char* wordPtr;
char word[100];
//1. get a word from the user that is max 100 characters
scanf("%s", word);
//2. determine how large the word actually is
wordPtr = calloc(strlen(word)+1,sizeof(char));
strcpy(wordPtr, word);
//3. allocate memory that is just enough to hold the word
return wordPtr;
//4. copy the user's word into the new memory location
//5. return the memory address holding the word
}
**For this code we had to get a shopping last and see print out how many times candy was in the shopping list and in order to do that we had to allocates enough memory to hold onto as many words (strings) as the user wants to have on their shopping list. Then, for each item, allocate just enough memory to store the word. **
This declaration right here for me doesn't make sense
**char** stringArray; **
From what I understand the double pointer is an array which element in the array contains a pointer to the string address.
Because of this I would think that we would have to declare the double pointer like:
char stringArray[]; **
something like this but that would not work.
So I wanted to know how the code knows it is an Array of pointers if we never put brackets
I tried declaring the double pointer with an array and could not get it to work nor could figure out if it was even possible.
Pointers are pointers, arrays are arrays. However, when an array in C is used in an expression or passed as a parameter to a function, it "decays" into a pointer to the first element of that array. This in turn enables things like a pointer arithmetic and the convenient use of the [] index operator.
This also means that in most contexts, a pointer to the first element can be used in place of an array. If we have an array of pointers char* arr[n]; then a char** can be used to point at the first item, and from there on the rest of the array.
So if you'd write a function like int DetermineNumberOfCandy(int numFoods, char* list[numFoods]); that's fine and valid C, but list "decays" into a pointer to the first element anyway, so it is 100% equivalent to
int DetermineNumberOfCandy(int numFoods, char** list);
Also you have misc bugs in your code.
Since AllocateItem is what allocates a valid memory location, the stringArray[i] in main() must be assigned to this memory location before it can be used. Because until then it is just an uninitialized pointer pointing at garbage. Therefore you can't strcpy(stringArray[i], words). Remember that the function did not just allocate a chunk of memory, but also filled it with valid data. So it is sufficient to set the pointer to point at that data, no need to copy anything.
The word variable doesn't fill any purpose, you could as well write this:
for(int i=0; i < foods; i++){
stringArray[i] = AllocateItem();
}
Similarly free(words) is wrong, this would only free the last allocated memory. Rule of thumb: for each malloc call you must have a corresponding free call! Therefore it should be:
for(int i=0; i < foods; i++){
free(stringArray[i]);
}
free(stringArray);
When you declare a variable like a string like this:
char str[10];
Your computer declares in fact a pointer but allocates enough memory to hold 10 characters automaticely. You will see that if you dereference it, you will get the first character of your string.
About your strcpy not working on line 20, if doesnt work because you created your i variable in a for loop and when you do that, the variable disapeers at the end of the loop so you are not able to use it nowhere into your code.
And about your line 40, you can use pointers in at least 2 deferent ways. First one is passing a variabe as a pointer in a function for you to dont have to return it at the end of a function like so:
int main()
{
int var = 0;
my_funct(&var);
//var = 1 now
}
void myfunct(int *var)
{
*var = 1;
}
Here you need to dereference it but if you allocated memory to your pointer, you can now use it as an array without dereferencing it.
Oh and here, you just free one pointer of the 2 in your stringarray. To free everything, try:
for(int i = 0; i < foods; i++) {
free(StringArray[i]);
}
free(StringArray);
Tell me if i didnt awnser to everything or if i was not clear enough
So I declared an array of strings as
typedef char String[11]; and in my main function I have this condition
`
char word[12];
String hashArray[SIZE];
if (insertword(word, hashArray) == 1)
printf("word %s successfully inserted.\n", word);
This is the function that it calls.
int insertword(char word[], String hashArray[])
{
//get the hash
int hashIndex = hashfunction1(word)% 7 ;
printf("INDEX:%d\n", hashIndex); //delete later
if (hashArray[hashIndex] == NULL) //ERROR IS HERE
{
strcpy(hashArray[hashIndex], word);
printf("INSERTED!! ");
return 1;
}
else
{
printf("NOT INSERTED!! ");
return 0;
}
}
I have tested my program by adding a print and apparently the error happens at the first conditional statement. The else part is always what gets executed. I'm definitely missing something here, any help would be appreciated.
The problem with your code:
char word[12];
String hashArray[SIZE];
word is not initialized, hence it has garbage values.
Then inside insertword function:
int hashIndex = hashfunction1(word)% 7;
The array "decays" into a pointer to the first element:
hashfunction1(word)%7;
Is just as:
hashfunction1(word[0])%7;
When again, word is not initialized, so the value will be put in hashIndex is unknown!
Then you are accessing the array hashArray[hashIndex] in that index which is unknown, might be out of boundary.
Accessing an array outside its bounds has "undefined behavior".
To fix this, you need to put some random values in word array which will be smaller than 32, as stated in your comment, size = 32.
I need to write a function the takes:
an unknown type array, size of the array and size of the elements
and return an array of pointers: first the negative value and then the positive values. this is what Iv done so far:
void *mix(void *A, int nElementsA, int sizeOfAnElement) {
char** res = (char**)malloc(sizeof(char*)*nElementsA*sizeOfAnElement);
char* p = (char *)A;
char* bStart = res[0];
char* bEnd = res[nElementsA*sizeOfAnElement - sizeOfAnElement];
while (p<(char*)A + nElementsA*sizeOfAnElement) {
if (*(int*)p>0) {
bStart = p;
bStart += sizeOfAnElement;
}
else {
bEnd = p;
bEnd -= sizeOfAnElement;
}
p += sizeOfAnElement;
}
return res;
}
and i get array full of rubbish,
what Iv dove wrong?
First of all: What you are trying to do is impossible and makes little sense.
You say that you have: an unknown type array Therefore you can not access any elements of the array. Doing:
(*(int*)p
means that you assume the elements to be of type int (or compatible). This obviously conflict with the type being unknown.
Besides that....
This line
malloc(sizeof(char*)*nElementsA*sizeOfAnElement);
allocates too much memory. It shall only allocate a pointer for each element, i.e.
malloc(sizeof(char*)*nElementsA);
Fixed:
void *mix(void *A, int nElementsA, int sizeOfAnElement,
int (*isPositive)(const void *)) {
// Allocate a `char*` array containing `nElementsA` pointers.
char **res = malloc(nElementsA * sizeof *res);
// &p[i] == &A[i]
char (*p)[sizeOfAnElement] = A;
// bStart points to the first result element.
char **bStart = &res[0];
// bEnd points to the last result element.
char **bEnd = &res[nElementsA - 1];
// Loop through the array,
// adding &A[i] at the start of the result array if positive,
// else at the end of the result array.
for (int i = 0; i < nElementsA; i++) {
if (isPositive(p[i])) {
*bStart = p[i];
bStart++;
}
else {
*bEnd = p[i];
bEnd--;
}
}
return res;
}
Your understanding of what needed to be allocated and how to use your pointers was wrong.
If you want to create an array of pointers, then you need only allocate nElementsA pointers, not nElementsA * sizeOfAnElement pointers (you're storing pointers, not copies of the objects to which they point).
Then you created and used bStart and bEnd incorrectly. If you want to move through an array of int objects, then you need an int* object. In the case of bStart and bEnd, you want to move through an array of char*, so you need a char**.
I added a function pointer parameter, so you can work with types other than int (else what's the point of using void *A and sizeOfAnElement instead of int *A?) If you need help with that, there are plenty of answers here and tutorials for you to find via search engine.
I also took the liberty of changing p to a pointer to an array, so the compiler can perform the pointer arithmetic for you rather than you doing it yourself. You can change it back if you like. If you want to use pointers in the loop (i.e. you can't use i), here's a version of the loop that does that:
// I added the typedef for more easily understood declarations of `p` and `end`.
typedef char array_alias_t[sizeOfAnElement];
// p's type is the same as in the previous code (char (*)[sizeOfAnElement]).
array_alias_t *p = A;
// p + x == &p[x], and &p[nElementsA] is one element past the end of A,
// which is allowed by ISO C, provided you don't dereference the pointer
// (i.e. *end is not allowed).
for (array_alias_t *end = p + nElementsA; p != end; p++) {
if (isPositive(*p)) {
*bStart = *p;
bStart++;
} else {
*bEnd = *p;
bEnd--;
}
}
I am reading from a file (each line wolds 1 word) and putting each line into an array. However I'll get a segmentation fault whenever I try to access any element in the array. Any help on this is greatly appreciated.
*update: added a while loop to grab the character one by one but I still get a segmentation fault
The pointer was made here:
char* ptr;
I passed it through the function as this:
fillDict(ptr,&size);
int fillDict(char* ptr,int *size)
And it reads the file and puts it into the array here:
int i = -1;
int numb;
int wsize;
while (fgets(word,30,file)!=NULL)
{
if (i==-1)
{
if(word[strlen(word)-1]=='\n')
{
word[strlen(word)-1] = 0;
}
numb = atoi(word);
ptr = malloc(sizeof(char));
}
else
{
if(word[strlen(word)-1]=='\n')
{
word[strlen(word)-1] = 0;
}
wsize = wsize+strlen(word);
ptr = realloc(ptr,wsize);
int j = 0; //added from here
while(j<strlen(word)-1)
{
printf("%d\n",j);
ptr[j] = word[j]; //crashes here
j++;
}
ptr[j] = '\0'; //to here
size++;
}
i++;
}
printf("%s",ptr[0]); //but fails here
fclose(file);
As #Jagannath mentioned, you are treating your ptr variable as a 2 dimensional array.
In reality, you allocate it as a simple buffer.
Schematically :
ptr = [][][][][][][][][][][][][][\0];
Then, you have a word which is also a simple buffer as follow :
word = [h][e][l][l][o][\0];
If you want to copy word to ptr, you need to iterate over both buffers and copy character by character as follow :
word = [h][e][l][l][o][\0];
v v v v v
ptr = [h][e][l][l][o][][][][][][][][][\0];
Otherwise, you can create an array of word by creating a 2 dimensional array.
ptr = [|][|][][]...[\0]
v v
[h][w]
[e][o]
[l][r]
[l][l]
[o][d]
[0][0]
Finally, you have flaws in your code. Look at your malloc(1)... And your wsize is never initialized, so when you do wsize = wsize+strlen(word); the behavior is undefined.
This code shows some fundamental misunderstanding about how pointers work. ptr[i] is equivalent to *(ptr+i). This makes no sense in the context of your code. It is therefore supposed to be a char but you are assigning a pointer to a char to it. And the printf that fails, well of course it's going to fail. it expects a pointer to a char but instead it gets whatever data is at the location ptr is pointing to and treats this as a pointer. This is likely to be a forbidden memory location hence the segfault. Even if it isn't, it is unlikely to reach a null terminating byte before it goes out of bound.
I want to use only studio.h library to convert from decimal number to binary number by using an array to store remainder but the result is not correct, maybe i have problem with memory allocation or return value is wrong, please help me to check it.
Thank you so much!
#include <stdio.h>
int n = 0;
int* DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
void main(){
int *d1 = DecimalToBinary(5);
int *d2 = DecimalToBinary(10);
for(int i = n-1 ;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
for(int i = n-1 ;i>=0;i--)
printf(" %d",d2[i]);
}
You return a pointer to a local array. That local array is on the stack, and when the function returns the array goes out of scope and that stack memory will be reused when you call the next function. This means that the pointer will now point to some other data, and not the original array.
There are two solutions to this:
Declare the array in the function calling DecimalToBinary and pass it as an argument.
Create the array dynamically on the heap (e.g. with malloc) and return that pointer.
The problem with method 2 is that it might create a memory leak if you don't free the returned pointer.
As noted by Craig there is a third solution, to make the array static inside the function. However in this case it brings other and bigger problems than the two solutions I originally listed, and that's why I didn't list it.
There is also another serious problem with the code, as noted by Uchia Itachi, and that is that the array is indexed by a global variable. If the DecimalToBinary function is called with a too big number, or to many times, this global index variable will be to big for the array and will be out of bounds for the array.
Both the problem with dereferencing a pointer to an out-of-scope array and the indexing out of bounds leads to undefined behavior. Undefined behavior will, if you're lucky, just lead to the wrong result being printed. If you're unlucky it will cause the program to crash.
You are returning a pointer to a locally allocated array. It is allocated on the stack, and goes away when the function returns, leaving your pointer pointing to garbage.
You have a few options. You could pass an array in to fill:
void DecimalToBinary(int result[10],int number){
while(number!=0){
result[n++] = number%2;
number/=2;
}
return result;
}
// usage example:
int b[10];
DecimalToBinary(b, 42);
Or you could allocate an array on the heap:
int* DecimalToBinary(int number){
int *a = (int *)malloc(sizeof(int) * 10);
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
// usage example
int *b = DecimalToBinary(42);
free(b); // when finished with it
Or you could wrap the array in a struct:
typedef struct {
int b[10];
} result;
result DecimalToBinary(int number){
result r;
while(number!=0){
r.b[n++] = number%2;
number/=2;
}
return r;
}
// usage example
result r = DecimalToBinary(42);
If you do the malloc() option, do not forget to free() the returned data when you're done with it, otherwise it will hang around. This is called a memory leak. In more complex programs, it can lead to serious issues.
Note: By the way, if your number is larger than 1023 (10 binary digits), you'll overrun the array. You may also wish to explicitly stop once you've stored 10 digits, or pass the size of the array in, or compute the required size first and allocate that much space. Also, you will get some odd results if your number is negative, you might want to use number&1 instead of number%2.
Note 2: As noted elsewhere, you should make n local, or at the very least reinitalize it to 0 each time the function is called, otherwise it will just accumulate and eventually you'll go past the end of the array.
int[10] is not the same as int *; not only is the former created on the stack, it is a different type alltogether. You need to create an actual int * like so:
int *a = malloc (10 * sizeof (int));
Of course, don't forget to free() it after use!
What you can also do and what is commonly done in C is creating the array where it is called and provide a pointer to that array to the function, this way when the array is on the stack of the function that calls it and not in the function self. We also have to specify the size of the array on to that function, since the function cannot know to how many elements the pointer points to
void DecimalToBinary( int number, int* output, unsigned size ) {
/*adapt this to your liking*/
int i;
for ( i = 0; i < size && number != 0; i++) {
output[i] = number%2;
number/2;
}
}
and in you main function you would call it like this:
int array[10];
DecimalToBinary( 5, array, sizeof(array)/sizeof(array[0]));
now array has the same result as a would have had in your example.
The problem in your code lies here..
int * DecimalToBinary(int number){
int a[10];
while(number!=0){
a[n++] = number%2;
number/=2;
}
return a;
}
The array a scope is only till this function. Once this function terminates, the memory allocated for this array will be released, either u need to use dynamic memory allocation or make array a global.
This is the correct program:
#include <stdio.h>
int n = 0;
int a[10] = {0};
int* DecimalToBinary(int number){
n = 0;
while(number!=0){
a[n++] = number%2;
number = number/2;
}
return a;
}
int main(){
int *d1;
int *d2;
int i;
d1 = DecimalToBinary(5);
for(i = n-1;i>=0;i--)
printf(" %d",d1[i]);
printf("\n");
d2 = DecimalToBinary(10);
for(i = n-1;i>=0;i--)
printf(" %d",d2[i]);
printf("\n");
}