How to initialize char** inside a struct - c

I have a struct
struct cmd{
char **tokenized_cmd;
int num_params;
}
at some point i need to initialize tokenized_cmd and pass values from another array into it
how to do that?

#include <stdio.h>
char *arr[] = {"one", "two"};
struct cmd {
char **tokenized_cmd;
int num_params;
} x = {arr, 2};
int main(void)
{
int i;
for (i = 0; i < x.num_params; i++)
printf("%s\n", x.tokenized_cmd[i]);
return 0;
}
or
#include <stdio.h>
struct cmd {
char **tokenized_cmd;
int num_params;
};
int main(void)
{
char *arr[] = {"one", "two"};
struct cmd x = {arr, 2};
int i;
for (i = 0; i < x.num_params; i++)
printf("%s\n", x.tokenized_cmd[i]);
return 0;
}
or the more flexible:
#include <stdio.h>
#include <stdlib.h>
struct cmd {
char **tokenized_cmd;
int num_params;
};
struct cmd *cmd_init(char **token, int params)
{
struct cmd *x = malloc(sizeof *x);
if (x == NULL) {
perror("malloc");
exit(EXIT_FAILURE);
}
x->tokenized_cmd = token;
x->num_params = params;
return x;
}
int main(void)
{
char *arr[] = {"one", "two"};
struct cmd *x = cmd_init(arr, 2);
int i;
for (i = 0; i < x->num_params; i++)
printf("%s\n", x->tokenized_cmd[i]);
free(x);
return 0;
}

Related

Why when I try to access array of structures it returns random values? (C)

I have a function that returns pointer to array of structures. However, when I try to access any of the values of returned structure, it prints random symbols.
#include <stdio.h>
struct MY {
int i;
char string[30];
};
struct MY* myFunc() {
struct MY arrayOfStructs[3];
struct MY tempStruct;
struct MY* arrayOfStructsPtr = arrayOfStructs;
tempStruct.i = 1;
tempStruct.string[0] = 'H';
tempStruct.string[1] = 'i';
arrayOfStructs[0] = tempStruct;
tempStruct.i = 2;
tempStruct.string[0] = 'L';
tempStruct.string[1] = 'o';
arrayOfStructs[1] = tempStruct;
tempStruct.i = 3;
tempStruct.string[0] = 'M';
tempStruct.string[1] = 'Y';
arrayOfStructs[2] = tempStruct;
return arrayOfStructsPtr;
}
int main()
{
struct MY* arrayOfStructs = myFunc();
for(int i = 0; i < 3; i++) printf("%d\n", arrayOfStructs[i].i);
return 0;
}
You return a reference to the local array which stops to exist when function returns. It is Undefined Behaviour.
You need:
struct MY* myFunc(void) {
static struct MY arrayOfStructs[3];
or
struct MY* myFunc(void) {
struct MY *arrayOfStructs = malloc(3 * sizeof(*arrayOfStructs));
or pass the buffer allocated by the caller.
struct MY *myFunc(struct MY *arrayOfStructs) {
/* .... */
If you dynamically allocate memory you should free it after use
You return a pointer to a local variable which is out of scope when the function returns. Some alternatives:
The caller main() allocates variable and pass it to myFunc() for initialization.
#include <stdio.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
void myFunc(struct MY arrayOfStructs[N]) {
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < N; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
}
int main() {
struct MY arrayOfStructs[N];
myFunc(arrayOfStructs);
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
}
As used here you don't really need to store i as it's just index of the struct + 1.
myFunc() dynamically allocate the variables with malloc() and return the pointer. Caller is responsible for free'ing the allocated memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define N 3
struct MY {
int i;
char string[30];
};
struct MY *myFunc() {
struct MY *arrayOfStructs = malloc(N * sizeof *arrayOfStructs);
if(!arrayOfStructs) return NULL; // malloc failed
char *strings[N] = { "Hi", "Lo", "MY" };
for(size_t i = 0; i < sizeof strings / sizeof *strings; i++) {
arrayOfStructs[i].i = i + 1;
strcpy(arrayOfStructs[i].string, strings[i]);
}
return arrayOfStructs;
}
int main() {
struct MY *arrayOfStructs = myFunc();
if(!arrayOfStructs) return 1;
for(int i = 0; i < N; i++)
printf("%d\n", arrayOfStructs[i].i);
free(arrayOfStructs);
}
myFunc(): make variables static (not recommended).

Getting jargon before actual data when printing char pointer

I'm writing a program that implements the Alberti Cipher, and when testing, the final print always gives a string of jargon before the actual encryption. Right now its printing \x80\x16G\xbf\xfe\x7fKHOORZRUOG, with KHOOR..... being the actual encryption. Any help appreciated :)
#include <stdio.h>
#include <stdlib.h>
int letterToNumber(char letter){
char str[2] = { letter };
int num = strtol( str, NULL, 36 ) - 10;
return num;
}
int getSize (const char * s) {
const char * t;
int size = 0;
for (t = s; *t != '\0'; t++) {
size++;
}
return size;
}
char numToChar(int numInp){
numInp=numInp+65;
char returnChar=(char)numInp;
return returnChar;
}
void encrypt_alberti(const char *message,const char *inner_ring, int initialShift,int periodicShift,int periodLength,char **result){
//sets initial shift
int numArray[25];
int count=0;
int shiftCount=0;
for(int i = 0; i < 26; ++i) {
numArray[i]=(i+initialShift)%26;
}
//encrypts each character and prints
int messageSize=getSize(message);
char encryptedMessage[messageSize];
for(int i=0; i<messageSize;i++){
count++;
if(periodicShift!=0){
if(count%periodicShift==0){
shiftCount++;
}
}
else{
periodLength=0;
}
char toBeEncrypted=message[i];
int charNumber=letterToNumber(toBeEncrypted);
int encryptedNum=numArray[(charNumber+(shiftCount*periodLength))%26];
char encryptedChar=numToChar(encryptedNum);
strncat(encryptedMessage, &encryptedChar, 1);
}
char* p1=malloc(sizeof(encryptedMessage));
strcpy(p1,encryptedMessage);
*result=p1;
}
void main(void) {
const char *example_message = "HELLOWORLD";
const char *example_inner = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *encrypted_message = NULL;
encrypt_alberti(example_message, example_inner, 3, 0, 1, &encrypted_message);
printf("message is %s\n", encrypted_message);
printf("-----------------");
free(encrypted_message);
}
}

how to print the contents of char**?

I have a structure defined as a char** array containing strings. I dont know how to run printf on its contents.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#ifndef STRUCT_STRING_ARRAY
#define STRUCT_STRING_ARRAY
typedef struct s_string_array
{
int size;
char** array;
} string_array;
#endif
void my_print_words_array(string_array* param_1)
{
int len = param_1->size;
char **d = param_1->array;
for(int i = 0 ; i < len;i++){
printf("%s\n", d[i]);
}
}
int main(){
struct s_string_array *d;
d->size = 2;
char **my_arr = (char *[]){"hello", "world"};//this init is fine
d->array = my_arr;
my_print_words_array(d);
return 0 ;
}
the main function gives me segfault error. What's wrong?
There is no sense to declare a pointer to the structure
struct s_string_array *d;
moreover that is not initialized and has indeterminate value that further is a reason of undefined behavior.
What you are trying to achieve is the following
#include <stdio.h>
typedef struct s_string_array
{
int size;
char** array;
} string_array;
void my_print_words_array( const string_array *param_1 )
{
for ( int i = 0; i < param_1->size; i++ )
{
puts( param_1->array[i] );
}
}
int main( void )
{
string_array d =
{
.size = 2,
.array = (char *[]){"hello", "world"}
};
my_print_words_array( &d );
return 0 ;
}
The program output is
hello
world

C "expected expression before 'struct'" error since using typedef or header

I'm fairly new to C programming (did a little bit of lazarus and java before, but nothing mayor) and I tried to program a little text-rpg to learn the basics.
Now I'm getting a strange error while compiling since I tried to make part of the program a header. At the same time I stopped writing struct everywhere and used typedef, so the error might also originate from there.
Here's my code:
advancedgame.c:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "advancedgameglobals.h"
int main(int argc, char *argv[])
{
initiateglobals();
destroygameglobals();
return 0;
}
advancedgameglobals.c:
#include <stdio.h>
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include "advancedgameglobals.h"
PLAYER *player_create(char *name, int con, int str, int agi, int wis){
PLAYER *who = malloc(sizeof(PLAYER));
assert(who != NULL);
who->name = strdup(name);
who->con = con;
who->str = str;
who->agi = agi;
who->wis = wis;
int def = con / 5;
int maxhp = con * 10;
int hp = maxhp;
int maxmp = wis * 5;
int mp = maxmp;
who->def = def;
who->maxhp = maxhp;
who->hp = hp;
who->maxmp = maxmp;
who->mp = mp;
who->exp = 0;
who->level = 1;
}
char * determine_item_type(int type){
char *typename;
if(type == 1){
typename = "longsword";}
else if(type == 2){
typename = "wooden shield";}
else{
typename = "empty slot";}
return typename;
}
INVENTORY *inventory_create(char *name){
INVENTORY *who = malloc(sizeof(INVENTORY));
assert(who != NULL);
who->name = strdup(name);
int slot0 = 0;
int slot1 = 0;
int slot2 = 0;
int slot3 = 0;
int slot4 = 0;
int slot5 = 0;
int slot6 = 0;
int slot7 = 0;
int slot8 = 0;
int slot9 = 0;
who->slot0 = slot0;
who->slot0name = determine_item_type(slot0);
who->slot1 = slot1;
who->slot1name = determine_item_type(slot1);
who->slot2 = slot2;
who->slot2name = determine_item_type(slot2);
who->slot3 = slot3;
who->slot3name = determine_item_type(slot3);
who->slot4 = slot4;
who->slot4name = determine_item_type(slot4);
who->slot5 = slot5;
who->slot5name = determine_item_type(slot5);
who->slot6 = slot6;
who->slot6name = determine_item_type(slot6);
who->slot7 = slot7;
who->slot7name = determine_item_type(slot7);
who->slot8 = slot8;
who->slot8name = determine_item_type(slot8);
who->slot9 = slot9;
char *test = determine_item_type(slot9);
who->slot9name = test;//determine_item_type(slot9);
}
char * determine_town_type(int type){
char *typename;
if(type == 1){
typename = "shop";}
else if(type == 2){
typename = "Colloseum";}
else{
typename = "empty shack";}
return typename;
}
TOWN *town_create(char *name, int slot0, int slot1, int slot2, int slot3){
TOWN *who = malloc(sizeof(TOWN));
assert(who != NULL);
who->name = strdup(name);
who->slot0 = slot0;
who->slot0name = determine_town_type(slot0);
who->slot1 = slot1;
who->slot1name = determine_town_type(slot1);
who->slot2 = slot2;
who->slot2name = determine_town_type(slot2);
who->slot3 = slot3;
char *test = determine_town_type(slot3);
who->slot3name = test;//determine_town_type(slot3);
}
ENEMY *enemy_create(char *name, int con, int str, int agi, int wis){
ENEMY *who = malloc(sizeof(ENEMY));
assert(who != NULL);
who->name = strdup(name);
who->con = con;
who->str = str;
who->agi = agi;
who->wis = wis;
int def = con / 5;
int maxhp = con * 10;
int hp = maxhp;
int maxmp = wis * 5;
int mp = maxmp;
who->def = def;
who->maxhp = maxhp;
who->hp = hp;
who->maxmp = maxmp;
who->mp = mp;
int exp = con+str+agi+wis;
who->exp = exp;
who->level = exp / 50;
}
void player_destroy(PLAYER *who){
assert(who != NULL);
free(who->name);
free(who);
}
void enemy_destroy(ENEMY *who){
assert(who != NULL);
free(who->name);
free(who);
}
void inventory_destroy(INVENTORY *who){
assert(who != NULL);
free(who->name);
free(who);
}
void town_destroy(TOWN *who){
assert(who != NULL);
free(who->name);
free(who);
}
int initiateglobals(void)
{
PLAYER *PLAYER = player_create(
"Player", 10, 10, 10, 10);
INVENTORY *INVENTORY = inventory_create(
"Inventory");
TOWN *TOWN = town_create(
"Antaria", 2, 1, 0, 0);
return 0;
}
int destroygameglobals(void)
{
player_destroy(PLAYER);
inventory_destroy(INVENTORY);
town_destroy(TOWN);
}
advancedgameglobals.h:
#ifndef ADVANCEDGAMEGLOBALS_H
#define ADVANCEDGAMEGLOBALS_H
typedef struct player{
char *name;
int con;
int def;
int str;
int agi;
int wis;
int maxhp;
int hp;
int maxmp;
int mp;
int exp;
int level;
} PLAYER;
typedef struct enemy{
char *name;
int con;
int def;
int str;
int agi;
int wis;
int maxhp;
int hp;
int maxmp;
int mp;
int exp;
int level;
} ENEMY;
typedef struct inventory{
char *name;
int slot0;
char *slot0name;
int slot1;
char *slot1name;
int slot2;
char *slot2name;
int slot3;
char *slot3name;
int slot4;
char *slot4name;
int slot5;
char *slot5name;
int slot6;
char *slot6name;
int slot7;
char *slot7name;
int slot8;
char *slot8name;
int slot9;
char *slot9name;
} INVENTORY;
typedef struct town{
char *name;
int slot0;
char *slot0name;
int slot1;
char *slot1name;
int slot2;
char *slot2name;
int slot3;
char *slot3name;
} TOWN;
PLAYER *player_create(char *name, int con, int str, int agi, int wis);
char * determine_item_type(int type);
INVENTORY *inventory_create(char *name);
char * determine_town_type(int type);
TOWN *town_create(char *name, int slot0, int slot1, int slot2, int slot3);
ENEMY *enemy_create(char *name, int con, int str, int agi, int wis);
void player_destroy(PLAYER *who);
void enemy_destroy(ENEMY *who);
void inventory_destroy(INVENTORY *who);
void town_destroy(TOWN *who);
int initiateglobals(void);
int destroyglobals(void);
#endif
Now the error I'm getting tells me the following:
error: expected expression before 'PLAYER'
player_destroy(PLAYER);
error: expected expression before 'INVENTORY'
inventory_destroy(INVENTORY);
error: expected expression before 'TOWN'
town_destroy(TOWN);
I'm getting this error whenever I try to make a function using any of my structures. Most likely this is a very dumb error and I'm sorry about that, but I would appreciate any help you could give me.
Problems:
The function initiateglobals() initializes local variables, not global variables. Naming variables to the same name as types is also not good because it is confusing.
The function calls in destroygameglobals() is not good. You have to use names of variables instead of type names to pass as arguments.
To fix:
Declare global variables to be initialized in initiateglobals() and have the function initialize the global variables, not local variables. The names of variables should be differ from the type names to avoid confusion.
Use names of the declared global variables, not type names as arguments in function calls in destroygameglobals().
I think problem is with this function.
int destroygameglobals(void)
{
player_destroy(PLAYER);
inventory_destroy(INVENTORY);
town_destroy(TOWN);
}
Check function calls in this function. Instead of passing some variable as arguments, you are passing data type as arguments. Which is no acceptable.

Function to read in a word into a struct array

I am having an error with the code we are using, was wondering if someone could help debug. Seems like we are getting a malloc error. Thanks.
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
int result = 0;
Word * current_pointer = malloc (sizeof(Word*));//creates a temporary variable for each pointer in the array
for (i=0; i<word_counter; i++) {
current_pointer = *(array+i); //accesses the current pointer
result = strcmp(norm_word, (current_pointer -> word)); //compares the string to each stored string
if (result == 0) {
found = true;
(current_pointer->freq)++;
break;
}
}
if(!found) {
if(pointer_counter == word_counter) {
array = realloc(array, sizeof(array)*2);
pointer_counter*=2;
}
Word * new_pointer = (Word*) malloc (sizeof(Word*));
strcpy(new_pointer -> word, norm_word);
*(array + (pointer_counter - 1)) = new_pointer;
word_counter++;
}
;
}
All pointers have the same size on your system. So a sizeof always returns the same size for any pointer. You want to allocate for the structure, so you need to use sizeof on the name without the star. malloc will return the pointer to that block of memory afterwards.
Here is a short implementation:
#include <iostream>
#include <string>
typedef struct
{
int num;
int numnum;
}numbers;
int main(int argc, char ** argv)
{
numbers* n = (numbers*)malloc(sizeof(numbers));
n->num = 1;
n->numnum = 2;
free(n);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#define MAXSIZE 64
typedef struct word {
char word[MAXSIZE];
int freq;
} Word;
int word_counter = 0;
size_t pointer_counter = 16;//Number of pointers that ensure
void readWords(char norm_word[MAXSIZE], Word ** array) {
int i = 0;
bool found = false;
Word *current_pointer = *array;
for (i=0; i<word_counter; i++) {
if(strcmp(norm_word, current_pointer->word) == 0){
found = true;
current_pointer->freq++;
break;
}
++current_pointer;
}
if(!found) {
if(pointer_counter == word_counter) {
pointer_counter *= 2;
*array = realloc(*array, sizeof(Word)*pointer_counter);
}
Word *new_pointer = *array + word_counter;
new_pointer->freq = 1;
strcpy(new_pointer->word, norm_word);
++word_counter;
}
}
int main(void){
Word *vocabulary = calloc(pointer_counter, sizeof(Word));
char norm_word[MAXSIZE];
while(1==scanf("%s", norm_word)){
readWords(norm_word, &vocabulary);
}
{
int i;
for(i = 0; i < word_counter; ++i){
printf("%s(%d)\n", vocabulary[i].word, vocabulary[i].freq);
}
}
free(vocabulary);
return 0;
}

Resources