Why my double pointer is null? [duplicate] - c

This question already has an answer here:
Dynamic memory access only works inside function
(1 answer)
Closed 5 years ago.
this is my code:
void n(FILE *f, int *pocet, char **spz) {
int i = 0;
int pocett = 0;
char* r = (char*)malloc(50 * sizeof(char));
if (spz != NULL) {
free(spz);
}
spz = (char**)malloc(sizeof(char*));
if (f == NULL) {
printf_s("File is null");
return;
}
while (fgets(r, 50, f)) {
switch (i % 6) {
case 1: {
if (i == 1) {
spz[0] = (char*)malloc(50 * sizeof(char));
spz[0] = r;
}
else {
spz = (char**) realloc(spz,((i - 1) / 6 + 1) * sizeof(char*));
spz[((i - 1) / 6)] = (char*)malloc(50 * sizeof(char));
strcpy_s(spz[(i-1)/6], 50 ,r);
}
break;
}
case 5: {
pocett++;
break;
}
}
i++;
}
*pocet = ++pocett;
}
and I call my function as this:
int main() {
FILE *f = NULL;
int c;
int pocet = 0;
int* p = &pocet;
char** spz = NULL;
while ((c = getchar()) != 'k') {
getchar();
switch (c) {
case 'v': {
v(&f);
break;
}
case 'o': {
//printf_s("AHOJ\n");
break;
}
case 'n': {
n(f, p, spz);
break;
}
case 's': {
s(spz, *p);
break;
}
case 'p': {
printf_s("AHOJ\n");
break;
}
case 'z': {
printf_s("AHOJ\n");
break;
}
default: {
printf_s("Skus znova\n");
break;
}
}
}
return 0;
}
EDIT: I have edited my code to add main method.
the problem is, when I pass the spz to another method after, it is null, that means I have to use it in method n() as triple pointer, but it is not working when I add asterisk before each spz in method n. Do you have any ideas how to fix this ?

When you call a function you pass a copy of the spz variable from the main() function to an spz variable in the n() function. Then, assignment in n() affects only its local spz.
If you want to get a pointer value back, you need to pass a pointer to the variable and the routine must dereference the pointer to reach the original variable:
void n( char ***spz_ptr) // a pointer to (char **) variable
{
*spz_ptr // dereferenced pointer. i.e. the main's spz
= malloc( ... );
}
void main()
{
char **spz;
n( & spz ); // pass a pointer to spz
if( spz == NULL) { // test the value assigned by n()
.... // handle the error
}
else {
.... // proceed with actual work
}
}

Related

How to assign a character to a string pointed by a struct?

I have a struct that contains a field named void * user_data.
Here is the library declaration:
typedef struct esp_http_client_event {
esp_http_client_event_id_t event_id;
esp_http_client_handle_t client;
void *data;
int data_len;
void *user_data;
char *header_key;
char *header_value;
} esp_http_client_event_t;
When I declare the struct, I assign a buffer to user_data:
char g_http_response_buffer[MAX_HTTP_OUTPUT_BUFFER] = { 0 };
...
esp_http_client_config_t config = {
.url = WEB_URL,
.event_handler = client_event_handler,
.transport_type = HTTP_TRANSPORT_OVER_SSL,
.crt_bundle_attach = esp_crt_bundle_attach,
.buffer_size_tx = 1024,
.user_data = g_http_response_buffer,
};
After that, I want to manipulate g_http_response_buffer by using the structure, passed to a function (the function is a callback, but I don't think it's relevant).
Inside the function, I use it in the following way:
esp_err_t
client_event_handler (esp_http_client_event_handle_t evt)
{
static int output_len = 0;
esp_err_t ret = ESP_OK;
switch (evt->event_id)
{
case HTTP_EVENT_ERROR:
ESP_LOGI(g_p_tag, "HTTP_EVENT_ERROR");
break;
case HTTP_EVENT_ON_CONNECTED:
ESP_LOGI(g_p_tag, "HTTP_EVENT_ON_CONNECTED");
break;
case HTTP_EVENT_HEADER_SENT:
ESP_LOGI(g_p_tag, "HTTP_EVENT_HEADER_SENT");
break;
case HTTP_EVENT_ON_HEADER:
ESP_LOGI(g_p_tag, "HTTP_EVENT_ON_HEADER, key=%s, value=%s",
evt->header_key, evt->header_value);
break;
case HTTP_EVENT_ON_DATA:
ESP_LOGI(g_p_tag, "HTTP_EVENT_ON_DATA, len=%d", evt->data_len);
if (!esp_http_client_is_chunked_response(evt->client))
{
if (evt->user_data)
{
memcpy(evt->user_data + output_len, evt->data,
evt->data_len);
ESP_LOGI(g_p_tag, "Dati non chunk: %s",
(char *) evt->user_data);
}
if (ESP_OK == ret)
{
output_len += evt->data_len;
}
}
else
{
if (evt->user_data)
{
memcpy(evt->user_data + output_len, evt->data,
evt->data_len);
ESP_LOGI(g_p_tag, "Dati chunk: %s",
(char *) evt->user_data);
}
if (ESP_OK == ret)
{
output_len += evt->data_len;
}
}
break;
case HTTP_EVENT_ON_FINISH:
ESP_LOGI(g_p_tag, "HTTP_EVENT_ON_FINISH");
g_http_response_buffer[output_len] = '\0'; // <- HERE!
ESP_LOGI(g_p_tag, "Dato finale: %s", (char *) evt->user_data);
output_len = 0;
break;
}
return ret;
} /* client_event_handler() */
How can I insert the terminator string by using a pointer to user_data?
I tried (evt + output_len)->user_data = '\0' but it seems wrong.
How can I insert the terminator string by using a pointer to user_data?
You cannot "insert" into arrays strictly speaking. You can assign a char in any index to be a null terminator like this:
char* ptr_to_user_data = config.user_data;
assert(index < MAX_HTTP_OUTPUT_BUFFER);
ptr_to_user_data[index] = '\0';

C error C2660: 'Menu' : function does not take 3 arguments

I am new to programming and do not understand this error.
I have the same arguments in the Menu () function and when I call the same function in the menu_principal () function.
In function menu_principal(), I want execute the switch-case statement by the function Menu() with 'option' variable.
Can you help please?
int main()
{
void menu_principal();
return 0;
}
void menu_principal()
{
bool stop = true;
int option;
const char *title = "MENU PRINCIPAL";
const char *options_menu[] = { "ARTIGOS", "CLIENTES", "ORCAMENTOS", "SAIR" };
int n_options = 4;
do
{
option = Menu(title, options_menu, n_options);
switch (option)
{
case 1:
Menu_Item();
break;
case 2:
Menu_Client();
break;
case 3:
Menu_Billing();
break;
case 4:
stop = false;
break;
}
} while (stop);
}
int Menu(const char *title1, const char *options_menu1[], int n_options1)
{
int OptionSelected= 1;
int key;
bool stop = true;
do
{
system("cls");
gotoxy(5, 3 + OptionSelected); printf(">>");
gotoxy(15, 2); printf("%s", title1);
for (int i = 0; i < n_options1; i++)
{
gotoxy(10, 4 + i);
printf("%s ", options_menu1[i]);
}
do
{
key = _getch();
} while (key != KEY_UP && key != KEY_DOWN && key != KEY_ENTER );
switch (key)
{
case KEY_UP:
OptionSelected--;
if (OptionSelected < 1)
{
OptionSelected = n_options1;
}
break;
case KEY_DOWN:
OptionSelected--;
if (OptionSelected > n_options1)
{
OptionSelected = 1;
}
break;
case KEY_ENTER:
stop = false;
break;
}
} while (stop);
return OptionSelected;
}
The compiler reads your program top to bottom, so it sees:
option = Menu(title, options_menu, n_options);
On this line, you call a previously unknown function, Menu.
Because the function is unknown, the compiler assumes it will be int Menu(void). (takes no parameters, returns an int).
That assumption is obviously different from how Menu eventually gets declared.
To fix this, declare the function properly near the top of your file:
int Menu(const char *title1, const char *options_menu1[], int n_options1);
Then, when the compiler encounters your function-call, it will not assume a declaration, it will use the declaration you already provided (takes 3 parameters, and returns an int)

How to store a buffer of single characters and print them out as a string?

I posted a few questions about my project already and its all been helpful but I'm still unsure of one part of it.
I'm creating a translator that converts ASCII to ASH and ASH to ASCII. I have now successfully converted ASCII to ASH but can't convert from ASH to ASCII. I've created a function called 'ASCIIstring2ASHstring' which works fine, but I now have to create another function called 'ASHstring2ASCIIstring'. However, I've been told that for this function I need to save each character the user enters into a temporary buffer until a '/' appears, at which point I need to print out all the characters in the temporary buffer as a full string by calling the 'ASHstring2ASCIIstring' function (which I'm asking for help creating now) . However, I have no idea how I'd do this and I hoped someone here could lend me a hand :)
Thanks!
UPDATE: I have now created the function with some help, but for some reason its not printing out ASH to ASCII translations as expected, I have posted the updated code below.
char ASH_a[] = "*";
char ASH_b[] = "!!*";
char ASH_c[] = "!!#";
char ASH_d[] = "*!";
char ASH_e[] = "!";
char ASH_f[] = "!*!";
char ASH_g[] = "**";
char ASH_h[] = "!**";
char ASH_i[] = "!!";
char ASH_j[] = "*!!";
char ASH_k[] = "*#";
char ASH_l[] = "!*#";
char ASH_m[] = "!*";
char ASH_n[] = "!#";
char ASH_o[] = "#*";
char ASH_p[] = "!#!";
char ASH_q[] = "*!#";
char ASH_r[] = "!#*";
char ASH_s[] = "#!";
char ASH_t[] = "#";
char ASH_u[] = "##";
char ASH_v[] = "**!";
char ASH_w[] = "***";
char ASH_x[] = "*#!";
char ASH_y[] = "!##";
char ASH_z[] = "**#";
//char ASH_1[] = "#!!*";
//char ASH_2[] = "#!!#";
//char ASH_3[] = "#!*!";
//char ASH_4[] = "#!**";
//char ASH_5[] = "#!*#";
//char ASH_6[] = "#!#!";
//char ASH_7[] = "#!#*";
//char ASH_8[] = "#!##";
//char ASH_9[] = "#*!!";
//char ASH_0[] = "#!!!";
//char ASH_.[] = "#!!";
//char ASH_,[] = "#!*";
//char ASH_?[] = "#**";
//char ASH_![] = "#*#";
//char ASH_+[] = "##!";
//char ASH_-[] = "##*";
//char ASH_*[] = "###";
//char ASH_/[] = "#!#";
char t[] = "ash code";
char buffer1[100];
const int oblen = 100;
char ob [oblen];
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
// Serial.println(ASH2ASCII("!**")); //These are the ASH characters I want to convert to ASCII using the ASH2ASCII function
//Serial.println(ASH2ASCII("!"));
//Serial.println(ASH2ASCII("!*#"));
//Serial.println(ASH2ASCII("!*#"));
//Serial.println(ASH2ASCII("#*"));
//ASCIIstring2ASHstring (t, ob, oblen);
//Serial.println(ob);
usinput(buffer1);
Serial.print(buffer1);
chardecide(buffer1);
}
void chardecide(char * buffer1) { //char decide which acts upon the result of isASH using the true and false returns
if (isASH (buffer1)) {
Serial.println(" has been recognized as ASH - ");
ASHstring2ASCIIstring(buffer1, ob); //passes function with buffer1 and ob included
Serial.println(ob);
} else {
Serial.println(" has been recognized as ASCII - ");
ASCIIstring2ASHstring (buffer1, ob, oblen);
Serial.println(ob);
}
}
void usinput(char * ib ) {
char inChar;
int i = 0;
do {
while (!Serial.available()) {};
inChar = Serial.read();
if (inChar == '\n') {
break;
} else {
ib[i] = inChar;
i++;
}
ib[i] = '\0';
} while (true);
}
bool isASH(char * buffer1)
{
if (buffer1[0] != '*' && buffer1[0] != '!' && buffer1[0] != '#') return false;
return true;
}
int ASHstring2ASCIIstring(char *buffer, char *ob) //converts ash to ascii
{
char str[10];
int j = 0;
int l = 0;
while (*buffer) {
if (*buffer == '/') { //hit slash
str[j] = '\0'; //empty buffer
ob[l++] = ASH2ASCII(str);
j = 0;
} else {
if (j + 1 < sizeof(str)) {
str[j++] = *buffer;
}
}
buffer++;
}
ob[l] = '\0';
return l;
}
void ASCIIstring2ASHstring (char * ip, char * op, int oplen) { //converts ascii to ash
op[0] = '\0';
int bp = 0;
int n;
char m[9];
int l = strlen(ip);
for (int i = 0; i < l; i++) {
m[0] = '\0';
strcpy(m, ASCII2ASH(ip[i]));
n = strlen(m);
if ((bp + n + l) < oplen) {
strcat(op , m);
bp = bp + n;
}
if (ip[i] != ' ' && ip[i + l] != ' ') {
op[bp] = '/';
bp++;
}
op[bp] = '\0';
}
}
char ASH2ASCII(char * m) { //Using the char variables impmented globally, ASH2ASCII searches through specific variables until it finds a match for the conversion, at which point it will capture and reuturn the ASCII string
if (strcmp(ASH_a, m) == 0) { //if string captured return a
return 'a';
}
else if (strcmp(ASH_b, m) == 0) { //else if b string is captured return
return 'b';
}
else if (strcmp(ASH_c, m) == 0) {
return 'c';
}
else if (strcmp(ASH_d, m) == 0) {
return 'd';
}
else if (strcmp(ASH_e, m) == 0) {
return 'e';
}
else if (strcmp(ASH_f, m) == 0) {
return 'f';
}
else if (strcmp(ASH_g, m) == 0) {
return 'g';
}
else if (strcmp(ASH_h, m) == 0) {
return 'h';
}
else if (strcmp(ASH_i, m) == 0) {
return 'i';
}
else if (strcmp(ASH_j, m) == 0) {
return 'j';
}
else if (strcmp(ASH_k, m) == 0) {
return 'k';
}
else if (strcmp(ASH_l, m) == 0) {
return 'l';
}
else if (strcmp(ASH_m, m) == 0) {
return 'm';
}
else if (strcmp(ASH_n, m) == 0) {
return 'n';
}
else if (strcmp(ASH_o, m) == 0) {
return 'o';
}
else if (strcmp(ASH_p, m) == 0) {
return 'p';
}
else if (strcmp(ASH_q, m) == 0) {
return 'q';
}
else if (strcmp(ASH_r, m) == 0) {
return 'r';
}
else if (strcmp(ASH_s, m) == 0) {
return 's';
}
else if (strcmp(ASH_t, m) == 0) {
return 't';
}
else if (strcmp(ASH_u, m) == 0) {
return 'u';
}
else if (strcmp(ASH_v, m) == 0) {
return 'v';
}
else if (strcmp(ASH_w, m) == 0) {
return 'w';
}
else if (strcmp(ASH_x, m) == 0) {
return 'x';
}
else if (strcmp(ASH_y, m) == 0) {
return 'y';
}
else if (strcmp(ASH_z, m) == 0) {
return 'z';
}
}
void ASCIIstring2ASH (char * buf) {
Serial.println(ASCII2ASH(*t));
}
char * ASCII2ASH (char c) { //This is the opposire of ASH2ASCII, it uses the globally defined variables to search through ASCII characters, and returns the ASH version of that character
switch (c) {
case 'a':
return ASH_a;//returns ASH version of a if matched
case 'b':
return ASH_b;
case 'c':
return ASH_c;
case 'd':
return ASH_d;
case 'e':
return ASH_e;
case 'f':
return ASH_f;
case 'g':
return ASH_g;
case 'h':
return ASH_h;
case 'i':
return ASH_i;
case 'j':
return ASH_j;
case 'k':
return ASH_k;
case 'l':
return ASH_l;
case 'm':
return ASH_m;
case 'n':
return ASH_n;
case 'o':
return ASH_o;
case 'p':
return ASH_p;
case 'q':
return ASH_q;
case 'r':
return ASH_r;
case 's':
return ASH_s;
case 't':
return ASH_t;
case 'u':
return ASH_u;
case 'v':
return ASH_v;
case 'w':
return ASH_w;
case 'x':
return ASH_x;
case 'y':
return ASH_y;
case 'z':
return ASH_z;
case ' ':
return " ";
default:
Serial.println("switching went wrong!");
break;
}
}
void loop() {
}
In <string.h>, there is a function strtok that splits a string on a range of given characters. You could use it like this:
int ASHstring2ASCIIstring(char *buffer, char *ob)
{
char *token;
int l = 0;
token = strtok(buffer, "/");
while (token) {
println(token);
ob[l++] = ASH2ASCII(token); // Note: No overflow check!
token = strtok(NULL, "/");
}
ob[l] = '\0';
return l;
}
On the first call, you supply the string to split, on subsequent calls you pass NULL to tell strtok to keep working on the same string. This code destroys the original string in the process, because it places end markers at the end of the tokens.
You can also code that behaviour yourself by filling an auxiliary buffer. When you hit a slash, process the buffer and empty it:
int ASHstring2ASCIIstring(char *buffer, char *ob)
{
char str[10];
int j = 0;
int l = 0;
while (*buffer) {
if (*buffer == '/') {
str[j] = '\0';
ob[l++] = ASH2ASCII(str);
j = 0;
} else {
if (j + 1 < sizeof(str)) {
str[j++] = *buffer;
}
}
buffer++;
}
ob[l] = '\0';
return l;
}
This code leaves the string intact. It also requires that there is a slash after the last token. That may not be what you want, but it might be a good starting point.

Evaluate postfix notation

I was doing my exercise but i stucked at the last step.
I have to evaluate postfix notation using stacks in C.
Code:
#include<stdio.h>
#include<stdlib.h>
#define MAX 100
typedef struct
{
int info;
}tipElement;
typedef struct
{
tipElement magacin [MAX];
int vrv;
}tipMagacin;
tipMagacin postfixStack;
void Inicijalizacija(tipMagacin *Mag)
{
(*Mag).vrv = -1; //warehouse is empty
}
int Prazen(tipMagacin Mag)
{
return(Mag.vrv == -1); //returns true if the warehouse is empty
}
int Poln(tipMagacin Mag)
{
return(Mag.vrv == MAX-1); //returns true if the warehouse is full
}
void Push(tipMagacin *Mag, tipElement Element)
{
if (Poln(*Mag)) printf("Warehouse is full\n"); //if it is full report an error
else
{
(*Mag).vrv++; //next position in the warehouse
(*Mag).magacin[(*Mag).vrv].info = Element.info; //put an element
}
}
void Pop(tipMagacin *Mag, tipElement *Element)
{
if (Prazen(*Mag)) printf("Warehouse is empty\n"); //if it is empty report an error
else
{
(*Element).info = (*Mag).magacin[(*Mag).vrv].info; //read the last element
(*Mag).vrv--; // delete it
}
}
int evaluate(int op1, int op2, char operate) {
switch (operate) {
case '*': return op2 * op1;
case '/': return op2 / op1;
case '+': return op2 + op1;
case '-': return op2 - op1;
default : return 0;
}
}
int evaluatePostfix (char *izraz, int n)
{
tipMagacin *Mag;
tipElement element;
tipElement go,z;
int i=0;
int op2;
char ch;
int value;
while (i < n) {
element.info = izraz[i];
if(isdigit(element.info))
{
Push(&postfixStack, element);
}
else
{
z=Pop(&postfixStack, &go);
op2=1;
value = evaluate(z,op2,ch);
Push(Mag,value);
}
i++;
}
return value;
}
my code works fine until here:
else
{
op1=Pop(&postfixStack, &go);
op2=Pop(&postfixStack, &go);
value = evaluate(op1,op2,element.info);
Push(&postfixStack, value);
}
i++;
}
return value;
}
the problem is: error: void value not ignored as it ought to be
my Push and Pop functions are void and i need to put the value that I remove from my stack to some int variable then i calculate them. put it doesnt put it for some reason i dont know.
Anyone help ?

Stack of strings

Hi i have program here that accept int as value. i wanted to translate it to accept strings in array then. i have read about using struct but i couldnt get into it. i hope someone can help me getting into that without using struct i dont know where to start i want to keep this lines of code.
#include <stdio.h>
#include <ctype.h>
#include <conio.h>
#include <string.h>
#include <stdlib.h>
int top = 0;
int *stack = NULL;
int size = 0;
main()
{
int opt, num;
char cont[] = { 'y' };
clrscr();
/* <start Declaring Stack Size { */
printf("Stacking Program");
printf("\n\nData Size: ");
scanf("%d", &size);
printf("\n");
/* } end> */
/* <start Allocates size of stack { */
if(size > 0)
{
stack = malloc(size * sizeof(int));
if(stack == NULL)
{
printf("ERROR: malloc() failed\n");
exit(2);
}
}
else
{
printf("ERROR: size should be positive integer\n");
exit(1);
}
/* } end> */
while((cont[0] == 'y') || (cont[0] == 'Y'))
{
clrscr();
/* <start Main Menu { */
printf("Stacking Program");
printf("\n\nData Size: %d\n\n", size);
printf("MAIN MENU\n1. Pop\n2. Push\n3. Pick\n4. View\nChoose: ");
scanf("%d", &opt);
printf("\n");
switch(opt) {
case 1:
pop();
break;
case 2:
if(top==size)
{
printf("You can't push more data");
}
else
{
printf("Enter data for Stack[%d]: ", top+1);
scanf("%d", &num);
push(num);
}
break;
case 3:
pick();
break;
case 4:
view();
break;
default:
printf("Your choice is not on the list.");
break;
}
/* } end> */
printf("\n\nDo you want continue\(Y\/N\)?");
scanf("%s", &cont[0]);
}
free(stack);
}
pop()
{
int a;
loading();
if(top <= 0)
{
printf("Stack empty.");
return 0;
}
else
{
top--;
a=stack[top];
printf("\(Stack[%d] = %d\) removed.", top+1, a);
}
}
push(int a)
{
stack[top]=a;
top++;
loading();
}
pick()
{
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
printf("\(Stack[%d] = %d\) is the last data.", top, stack[top-1]);
}
}
view()
{
int i;
loading();
if(top <= 0)
{
printf("Nothing to display.");
return 0;
}
else
{
for(i=0;i<top;i++)
{
printf("Stack[%d] = %d\n", i+1, stack[i]);
}
}
}
loading()
{
float i, x;
float load;
int loadarea[] = { 5000, 10000, 15000, 20000, 25000, 30000 };
int percentLoad;
x=0;
load=0;
percentLoad = loadarea[random(5)];
gotoxy(26,11);
printf("[");
for(i=0;i<25;i++)
{
x = i+27;
gotoxy(x, 11);
printf("=");
delay(percentLoad);
gotoxy(51,11);
printf("]");
gotoxy(53,11);
load=(i/25)*104.5;
if(load>100)
load = 100.00;
printf("%.2f\%",load);
}
delay(60000);
for(i=0;i<60;i++) {
printf("\b \b");
}
printf("\n");
}
Easiest way is to convert your stack to store char* instead of int.
char **stack;
stack = malloc( size * sizeof(char*) );
Now, your push operation will accept a char* from some buffer that is storing the string that was just input, duplicate it with strdup, and store that new pointer in the stack.
typedef enum {
STACK_MEM_ERROR = -1,
STACK_FULL = 0,
STACK_OK = 1
} StackStatus;
StackStatus push(const char *str)
{
char *newstr;
if( top >= size ) return STACK_FULL;
newstr = strdup(str);
if( newstr == NULL ) return STACK_MEM_ERROR;
stack[top++] = newstr;
return STACK_OK;
}
When you pop a string, you just get a pointer.
char *pop()
{
if( top == 0 ) return NULL;
return stack[--top];
}
You are responsible for freeing that memory when you are finished with the pointer (by calling free).
char * val;
while( NULL != (val = pop()) )
{
printf( "I popped: %s\n", val );
free(val);
}

Resources