Passing Array to function using double pointer - c

I was trying to get array updated through a function as in below code and this works fine.
char bookCategory[][MAX_CATEGORY_NAME_LENGTH] = {"Computer", "Electronics", "Electrical", "Civil", "Mechnnical", "Architecture"};
uint8_t getCategoryNumAndName(char* catName, uint8_t choice)
{
choice = choice - 0x30 - 1; /** Category starts from 1 on the screen */
if (choice >= (sizeof (bookCategory) / sizeof (bookCategory[0])))
{
//catName = NULL;
return (0xff);
}
else
{
strcpy(catName,bookCategory[choice]);
//catName = bookCategory[choice];
return(choice);
}
}
void addBooks(void)
{
// Some code here
char categoryName[30];
uint8_t catNumber;
catNumber = getCategoryNumAndName(categoryName, choice);
// Some code here
}
But I thought of making use of double pointer instead of using strcpy(). I tried below code, but I get incompatible pointer type error. How to call getCategoryNumAndName() in below code from addBooks()?
uint8_t getCategoryNumAndName(char** catName, uint8_t choice)
{
choice = choice - 0x30 - 1; /** Category starts from 1 on the screen */
if (choice >= (sizeof (bookCategory) / sizeof (bookCategory[0])))
{
*catName = NULL;
return (0xff);
}
else
{
//strcpy(catName,bookCategory[choice]);
*catName = bookCategory[choice];
return(choice);
}
}
void addBooks(void)
{
// Some code here
char categoryName[30];
uint8_t catNumber;
catNumber = getCategoryNumAndName(&categoryName, choice);
// Some code here
}

You can only pass pointer address to getCategoryNumAndName function not array address.
You can do as below.
char *categoryName = NULL;
catNumber = getCategoryNumAndName(&categoryName, choice);
make sure you assign the memory to categoryName in getCategoryNumAndName before dereferencing it .

To just force the code to work, you need to cast categoryName to a char**. But reading your code, it seems like you just want to move the pointer? You don't need a fixed size array for the category name. Just use a pointer:
char* categoryName;

Related

C language how to call a member of multi-dimensional array in corresponding to a structure

I have a problem with how to call a member of a structure. For example, there is a struct
typedef struct FAVORITE_TBL_S
{
UI32_T apple;
UI32_T banana;
UI16_T puzzle;
UI16_T car;
}FAVORITE_TBL_T;
And in the function, I have created a multi-dimensional array about this struct.
FUNCTION_NO_T
call_myFavoriteTbl(
const UI32_T unit,
const UI32_T value)
{
FUNCTION_NO_T ret = FUNCTION_E_GOOD;
UI8_T num_of_list = 4;
UI32_T i = 0;
FAVORITE_TBL_T *ptr_fav = NULL;
ptr_fav = priviate_alloc(sizeof(FAVORITE_TBL_T ) * num_of_list );
priviate_memset(ptr_fav, 0, sizeof(FAVORITE_TBL_T ) * num_of_list );
/* In this function, if I want to use member in the multi-dim array */
for (i = 0, i < value, i++)
{
if (BRAND_PINKLADY == ptr_fav[i]->apple)
{
printf("I love it!");
}
else
{
printf("I don't want to eat.");
}
if (BRAND_COSTAPICA == ptr_fav[i].banana)
{
printf("I love it!");
}
else
{
printf("I don't want to eat.");
}
}
return ret;
}
So why ptr_fav[i]->apple is wrong and ptr_fav[i].banana is right?
As ptr_fav is an array of FAVORITE_TBL_T values, ptr_fav[i] is a FAVORITE_TBL_T value. It is not a pointer to FAVORITE_TBL_T.
As such, the . notation is correct.
Now, because ptr_fav[i] is equivalent to *(ptr + i), you might write: (ptr_fav + i)->apple, though I'm not sure why you'd want to do that.
The -> operator is used to access a field on a pointer to a structure.
ptr_fav[i] has already dereferenced it and now you have structure value not pointer. If you want to use -> you should try (ptr_fav + i)->apple.

C - How to get original value of when you pass a dereferenced value to a function to later be compare with another string?

I know homework help are shunned upon, however, I have intense coder's block.
I want help understanding more than anything.
So when I take the address of the variable (&c) I understand that I get an address to its location in memory, but I don't know how to dereference that address in order to access its specific value ('b') to be compared in the function (color(&c, total) it is used in.
The main cannot be changed for any reason due to the requirements of the assignment
typedef struct dragon
{
char *name;
char *color[3];
int numHead;
int numTail;
}dragon;
void color(char* color, dragon *d);
int main()
{
dragon total[4];
dragon_info(total);
char c = 'b';
color(&c, total);
return 0;
}
Eventually, I used this line to see if the colors matched
if(strcmp(color, d[currentDra].color[currentColor]);
Before I used the line below because from my from my first perspective they would char
if(color == d[currentDra].color[currentColor])
But after debugging for a while I realized that color was just an address
Overall, I need to somehow get the value of color using the address somehow.
*color doesn't find the value.
&color doesn't either.
The rest of the function
void color(char *color, dragon *d)
{
char *colorList[5] = {"red","blue","white","green","yellow"};
int colorShow;
int knownColor = 1;
printf("what is color? ==== %p\n", color);
if(*color == 'r')
{
colorShow = 0;
}
else if(*color == 'b')
{
colorShow = 1;
}
else if(*color == 'w')
{
colorShow = 2;
}
else if(*color == 'g')
{
colorShow = 3;
}
else if(*color == 'y')
{
colorShow = 4;
}
else
{
printf("Sorry that is an unknown color, exiting...\n");
knownColor = 0;
}
//if a char then = numbers 0-1
//one loop for the dragons
if(knownColor)
{
printf("***All the %s dragons:***\n", colorList[colorShow]);
int currentDra;
for(currentDra = 0; currentDra < 4; currentDra++)
{
//another loop for the colors of the dragon
int currentColor;
for(currentColor = 0; currentColor < 3; currentColor++)
{
//printf("%c\n\n", (char*)color);
if(strcmp(color, d[currentDra].color[currentColor]))
{
printf("%s is %s\n", d[currentDra].name, colorList[colorShow]);
}
}
}
}
}
Thank you so much this is my first question ever.
if(strcmp(color, d[currentDra].color[currentColor]);
This doesn't work because color, as passed, is not null terminated. Thus this is undefined behavior.
if(color == d[currentDra].color[currentColor])
This doesn't work because you are comparing the pointers and not the values they reference.
If dragon.color is an array that contains single character strings, then you can compare with:
if(color[0] == d[currentDra].color[currentColor][0])

Initializing a struct in C

Im having trouble initialising structures (well doing everything actually, but structures first). The struct is first made in a header as follows
typedef enum cell
{
BLANK, RED, CYAN
} Cell;
#define NAMELEN 20
typedef struct player
{
char name[NAMELEN + NULL_SPACE];
Cell token;
unsigned score;
} Player;
void initFirstPlayer(Player * player);
void initSecondPlayer(Player * player, Cell token);
#endif
=======================================================================
and I tried to initialise it here
void initFirstPlayer(Player * player)
{
int randNo = rand() % 2;
if (randNo == 0) {
token = RED;
}
else() {
token = CYAN;
}
player ; p1 = {
"placeholder",
token,
0,
}
}
void initSecondPlayer(Player * player, Cell token)
{ }
What is the correct way to initialise this player struct?
I suspect this should work for you. Use a generic initPlayer function. Use that to allocate memory for the player and set the initial values. Be sure to also include a freePlayer function where you free() the player when you're done.
#include <stdlib.h>
#include <string.h>
Player* initPlayer()
{
Player* player = malloc(sizeof(Player));
int randNo = rand() % 2;
if (randNo == 0) {
player->token = RED;
}
else {
player->token = CYAN;
}
const char* initName = "placeholder";
strcpy(player->name, initName);
player->score = 0;
return player;
}
void freePlayer(Player* p)
{
free(p);
}
The way you'd use this would be like so:
int main()
{
Player* p1 = initPlayer();
Player* p2 = initPlayer();
play(p1, p2);
freePlayer(p1);
freePlayer(p2);
}
Assuming you have at least C99 support, so that compound literals and designated initializers are available to you, then you can use:
void initFirstPlayer(Player *player)
{
*player = (Player){ .token = rand() % 2 ? CYAN : RED,
.score = 0,
.name = "placeholder"
};
}
This does a structure assignment to the variable whose address is passed to the function. It compresses it all into one statement; you can split it out into several if you wish. This is an occasion where the ternary ? : operator is useful. You might prefer (rand() % 2) with the extra parentheses; I'd probably add them as often as I'd omit them.
The compound literal comes from (typename){ ...initializer for typename... }.
The designated initializers are the .member = value notations.
If you're stuck with C90 support, you have to work harder, perhaps creating a local variable with the correct information and then doing the structure assignment.
void initFirstPlayer(Player *player)
{
Player p1 = { "placeholder", rand() % 2 ? CYAN : RED, 0 };
*player = p1;
}
Now the onus is on you to list the initializers in the correct sequence.
Another way is to receive the player you want to inicialize as parameter:
void initPlayer(Player* player)
{
int randNo = rand() % 2;
if (randNo == 0) {
player->token = RED;
}
else {
player->token = CYAN;
}
const char* initName = "placeholder";
strcpy(player->name, initName);
player->score = 0;
}
int main() {
Player p1;
initPlayer(&p1);
}
You can have an array of players or allocate dinamically with malloc.

Remove the duplicate from a String Using Pointers

#include<stdio.h>
char *removedps(char *x)
{
int Ar[256] = {0};
int ip=0;
int op=0;
char temp;
while(*(x+ip))
{
temp = (*(x+ip));
if (!Ar[temp]) {
Ar[temp] = 1;
*(x+ip) = *(x+op);
op++;
}
ip++;
*(x+op) = '\0';
}
return x;
}
int main()
{
char lo[] = "0001";
printf("%s",removedps(lo));
}
My code is not working
I have tried hard to see the error
All I GET IS the first character .
My idea is simple
make an array of 256 places
insert Zero into them
Then insert 1 for each character inside the string (on that position of the array)
your assignment looks to be the error here.
op is "out postiion", ip is "in position"
so it should be
*(x+op) = *(x+ip);
not the other way.
because *(x+op) = '\0';
is always run every iteration of the loop.
I'd probablly do it more like this ( using your method, which I probablly wouldn't use personally)
char *removedps(char *x)
{
int Ar[256] = {0};
char* start = x;
while(*x)
{
if (Ar[*x])
{ // remove the repeated character
memmove(x, x+1, strlen(x));
}
else
{
Ar[*x] = 1;
x++;
}
}
return start;
}
also, I'd name it remove_duplicate_chars or something, not a fan of cryptic abbreviations.
At the end of the loop, you do *(x+op)='\0';, and then, in the next iteration, you do *(x+ip)=*(x+op);, so from the 2sd iteration, you put there 0.
try do something like:
for (op=ip=0;x[ip];ip++) {
if (!Ar[x[ip]]++) x[op++]=x[ip];
}
x[op]=0;

Changing pointer to a struct, passed by reference

I have this call on a file called 'PlayBoard.c':
MoveSucc = putBoardSquare(theBoard, getX, getY, nextTurn);
Where 'theBoard' is a pointer to struct Board. Inside the function I am changing the board's size by referencing the pointer to ANOTHER Board struct, a bigger one. Will it change 'theBoard' on 'PlayBoard.c', where MoveSucc is invoked?
EDIT: putBoardSquare is defined in another source file
EDIT: I've added the relevant functions
Boolean putBoardSquare(BoardP theBoard, int X, int Y, char val)
{
if (val != 'X' && val != 'O')
{
reportError(BAD_VAL);
return FALSE;
}
if (X<0 || Y<0)
{
reportError(OUT_OF_BOUND);
return FALSE;
}
if (X>theBoard->height || Y>theBoard->width)
{
theBoard = expandBoard(theBoard, X,Y);
}
printf("BOARD SIZE IS %d*%d\n",theBoard->height,theBoard->width);
if (theBoard->board[X][Y] == 'X' || theBoard->board[X][Y] == 'Y' )
{
reportError(SQUARE_FULL);
return FALSE;
}
if (val != turn)
{
reportError(WRONG_TURN);
return FALSE;
}
theBoard->board[X][Y] = val;
printf("PUT %c\n",theBoard->board[X][Y]);
changeTurn(val);
return TRUE;
}
static BoardP expandBoard(ConstBoardP theBoard, int X, int Y)
{
int newWidth = theBoard->width;
int newHeight = theBoard->height;
if (X>theBoard->height)
{
newHeight = (newHeight+1) * 2;
}
if (Y>theBoard->width)
{
newWidth = (newWidth+1) * 2;
}
BoardP newBoard = createNewBoard(newWidth,newHeight);
copyBoard(theBoard,newBoard);
printf("RETUNRNING NEW BOARD OF SIZE %d*%d\n",newHeight,newWidth);
return newBoard;
}
As you can see, when the user tries to place 'X' or 'O' outside the board, it needs to be expanded which happens (I know cause I've printed new board's size in expandBoard() and in putBoardSquare()). But the pointer in 'PlayBoard.c' doesn't seem to change anyway....
My question: how can I change the pointer of a struct passed as an argument to another function? In 'PlayBoard.c' I pass one struct as an argument, and I want putBoardSquare to refrence it to another struct, which will take effect in PlayBoard.c as well.
Am I clear?
EDIT
theBoard = expandBoard(theBoard, X,Y);
This assignment only changes a local variable. You'll have to add one level of indirection, as in:
MoveSucc = putBoardSquare(&theBoard, getX, getY, nextTurn);
Boolean putBoardSquare(BoardP *theBoard, int X, int Y, char val)
{
/* ... */
*theBoard = expandBoard(theBoard, X,Y);
/* ... */
}
Your question is confusing (perhaps you should post the code you have), but the error you have is cause simply by the definition of the struct not being available in PlayBoard.c. For instance, if you only have
struct foo;
void foo(struct foo *foov) { ... }
without a definition of foo available, as in
struct foo { int a; ... }
then you won't be able to access the members of the structure (see "opaque type").
If I understand correctly and you want to change where theBoard points to, you need to define it as a pointer to pointer, not as pointer.
MoveSucc = putBoardSquare(&theBoard, getX, getY, nextTurn);
and change the parameter in putBoardSquare() to ** and when you set the pointer do it like (assuming x is a pointer):
*theBoard = x;

Resources