Unable to retrieve data from array of character inside structure - c

I am using below code in one file
file 1
//structure is global
struct abc
{
char var;
char *a[5];
}*p;
struct abc q;
int main()
{
char t[] = "sample"
p = &q;
p->a[0] = &t[0];
p->var = 10;
printf("var = %d, string = %s\n", p->var, p->a[0]);
func();
exit(0);
}
But if I try to access the structure member (a[]) in func() that is in another file I don't get the data that is assigned in another file (above).
file2
int fucn()
{
char var1;
var1 = p->var;
printf("var1 = %d\n", var1);
//since i am unable to copy p->a[0] to some other string i am trying to print the contents of p->a[0].
printf("a = %s\n", p->a[0]);
}
program crashes executing the second printf but I can print the content of p->var which is assigned in some other file.

Something like below is what you need.
An include file.
prompt> cat foo.h
struct abc {
char var;
char *a[5];
};
extern struct abc *p;
main function
prompt> cat main.c
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "foo.h"
struct abc q, *p;
extern int func();
int
main()
{
p = &q;
/*
* Using strcpy after allocating memory.
*/
p->a[0] = malloc(strlen("zero") + 1);
strcpy(p->a[0], "zero");
/*
* strdup is equivalent to malloc and strcpy
*/
p->a[1] = strdup("one");
p->a[2] = "two";
p->a[3] = "three";
p->a[4] = "four"
p->var = 10;
printf("main var = %d, string = %s %s %s %s %s\n",
p->var, p->a[0], p->a[1], p->a[2], p->a[3], p->a[4]);
func();
return(0);
}
func function
prompt> cat func.c
#include <stdio.h>
#include "foo.h"
int
func()
{
int r;
r = printf("func var = %d, string = %s %s %s %s %s\n",
p->var, p->a[0], p->a[1], p->a[2], p->a[3], p->a[4]);
return(r);
}
Compile and run
prompt> gcc mainc.c func.c
prompt> a.out
main var = 10, string = zero one two three four
func var = 10, string = zero one two three four

Related

how to use *abs* section symbol

I generate a .o file based on a bin file, but when I use it .o file symbols, “start” and “end” can be output, but the “size” is always changing (start end suze is in the symbol of the. o file)
#include "stdio.h"
#include "stdlib.h"
// #include "ding.h"
extern char _binary_DingPCM_bin_start[];
extern char _binary_DingPCM_bin_end[];
extern char _binary_DingPCM_bin_size[];
int main()
{
char *pDingSound = NULL;
char *pDingSound_end = NULL;
pDingSound = (char*)_binary_DingPCM_bin_start;
pDingSound_end = (char*) _binary_DingPCM_bin_end ;
short int u32DingSoundSize = (long int)_binary_DingPCM_bin_size; //Ding PCM data bytes;
printf ("data_start %p\n", pDingSound);
printf ("data_end %p\n", pDingSound_end);
printf ("size %ld %d\n", pDingSound_end-pDingSound,u32DingSoundSize);
printf ("data_size %x\n", u32DingSoundSize);
printf("0x%hx Ding_sound\n",pDingSound[2]);
pause();
return 0;
}
I want to know why the u32DingSoundSize always changing and I want to use u32DingSoundSize

Cannot output the C struct char array member [duplicate]

This question already has answers here:
How can I correctly assign a new string value?
(4 answers)
Closed 1 year ago.
I'm learning how to use structures in C. But in the following code I couldn't print myArray "HELLO!" which is declared as a char array:
#include <stdio.h>
struct myStruct
{
int myInt;
float myFloat;
char myArray[40];
};
int main()
{
struct myStruct p1;
p1.myInt = 80;
p1.myFloat = 3.14;
printf("Integer: %d\n", p1.myInt);
printf("Float: %f\n", p1.myFloat);
p1.myArray = "HELLO!";
printf("Array: %s\n", p1.myArray);
return 0;
}
What is wrong in the above syntax that I don't get "HELLO!" as an output? Something wrong here:
p1.myArray = "HELLO!";
printf("Array: %s\n", p1.myArray);
Arrays are non-modifiable lvalues. So this attempt to assign a pointer (the string literal is implicitly converted to a pointer to its first element) to an array designator
p1.myArray = "HELLO!";
will not compile.
Either use the standard string function strcpy as for example
#include <string.h>
//...
strcpy( p1.myArray, "HELLO!" );
Or you could initialize the data member initially when the object of the structure type is defined as for example
struct myStruct p1 = { .myInt = 80, .myFloat = 3.14, .myArray = "HELLO!" };
or
struct myStruct p1 = { .myInt = 80, .myFloat = 3.14, .myArray = { "HELLO!" } };
or
struct myStruct p1 = { 80, 3.14, "HELLO!" };
or
struct myStruct p1 = { 80, 3.14, { "HELLO!" } };
Here is a demonstrative program.
#include <stdio.h>
#include <string.h>
struct myStruct
{
int myInt;
float myFloat;
char myArray[40];
};
int main( void )
{
struct myStruct p1 = { .myInt = 80, .myFloat = 3.14, .myArray = { "HELLO!" } };
printf("Integer: %d\n", p1.myInt);
printf("Float: %f\n", p1.myFloat);
printf("Array: %s\n", p1.myArray);
strcpy( p1.myArray, "BYE!" );
printf("\nArray: %s\n", p1.myArray);
return 0;
}
The program output is
Integer: 80
Float: 3.140000
Array: HELLO!
Array: BYE!

Getting string between two given characters

quote
I have input something like !Hello world! - 123 123 - and I need to get it into struct { char *string; int a; int b;} Can you help me?
typedef struct {
int a;
int b;
char *string;
} Smth;
//-----------(size=(already known size of input))
Smth *smth = (*Smth)malloc(sizeof(smth));
smth.string = (char*)malloc(sizeof(char) * size);
sscanf(input, "!%[^!]! - %d %d - ", smth.string, &smth.a, &smth.b); // doesn't work for me
before you edit your question
the call
sscanf("!%[^!]! - %d %d - ",string,&a,&b);
is not the one you want, you missed to give the string to parse as the first argument, so the string to parse is the format you wanted to use and the used format is the perhaps not initialized value of string
You wanted :
#include <stdio.h>
int main()
{
char string[32];
int a,b;
const char * i = "!Hello world! - 123 123 -";
if (sscanf(i, "!%31[^!]! - %d %d - ", string,&a,&b) == 3)
printf("'%s' %d %d\n", string, a, b);
else
put("error");
return 0;
}
does the work :
pi#raspberrypi:/tmp $ gcc -Wall f.c
pi#raspberrypi:/tmp $ ./a.out
'Hello world' 123 123
pi#raspberrypi:/tmp $
Notice I added in your original format a max length for the read string to not take the risk to write out of string and then to have an undefined behavior. If you do not want to manage yourself the array for string you can use the option %m but is not always available.
You are lacking the input string for sscanf. See example below.
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
char *string;
} Smth;
int main(void)
{
Smth smth;
sscanf(
"!Hello world! - 123 123 -",
"!%m[^!]! - %i %i -",
&smth.string,
&smth.a,
&smth.b);
printf("Str: `%s' a:%d b:%d\n", smth.string, smth.a, smth.b);
free(smth.string);
return 0;
}
UPDATE: Given your change in question
#include <stdio.h>
#include <stdlib.h>
typedef struct
{
int a;
int b;
char* string;
} Smth;
int main(void)
{
size_t size = 30u;
char input[] = "!Hello world! - 123 123 -";
Smth* smth = (Smth*) malloc(sizeof(Smth));
smth->string = (char*) malloc(sizeof(char) * size);
sscanf(input, "!%29[^!]! - %d %d - ", smth->string, &smth->a, &smth->b);
printf("Str: %s a:%d b:%d\n", smth->string, smth->a, smth->b);
free(smth->string);
free(smth);
return 0;
}

sprintf with struct array field - gets segmentation fault

This idea is to format text info messages bellowing to a structure within a module.
It works like a charm when trying to define the message with (cf module.c):
/*this works*/
module_text3.info_text[0] = "toto[0]";
module_text3.info_text[1] = "toto[1]";
But when using sprintf, I got segmentation fault (cf module.c):
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
3 different files: main.c, module.h and module.c
/*main.c*/
/*gcc -o test main.c module.c*/
#include <stdio.h>
#include "module.h"
int main(int argc, char **argv)
{
int i;
struct message3 *ptext3 = moduleFcn3();
for (i= 0; i < ptext3->info_nb; i++)
{
printf("ptext3->info_text[%u]: %s\n", i, ptext3->info_text[i]);
}
printf("ptext3->error_text: %s\n", ptext3->error_text);
printf("ptext3->id: %u\n", ptext3->id);
printf("ptext3->info_nb: %u\n", ptext3->info_nb);
printf("ptext3->info_nb_max: %u\n", ptext3->info_nb_max);
return 0;
}
/*------------------------------------------------------*/
/*module.h*/
#define NB_LINE_MAX 10
struct message3
{
char *info_text[NB_LINE_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
/*------------------------------------------------------*/
/*module.c*/
#include <stdio.h>
#include "module.h"
/*static is in "Stack".*/
static struct message3 module_text3;
struct message3* moduleFcn3(void)
{
int cpt = 0;
struct message3 *ptext;
/*this gives segmentation fault*/
for(cpt=0; cpt < 2; cpt++)
{
sprintf(module_text3.info_text[cpt], "info[%u]", cpt);
}
/*this works*/
// module_text3.info_text[0] = "toto[0]";
// module_text3.info_text[1] = "toto[1]";
// cpt = 2;
module_text3.error_text = "This is error";
module_text3.id = 4;
module_text3.info_nb_max = NB_LINE_MAX;
module_text3.info_nb = cpt;
ptext = &module_text3;
return ptext;
}
I would appreciate any advises on how to format my information messages (with our without using sprintf).
Thank you,
You have not allocated space for the strings in the info_text field. The simplest thing to do would be to change the struct:
/*module.h*/
#define NB_LINE_MAX 10
#define INFO_MAX 25
struct message3
{
char info_text[NB_LINE_MAX][INFO_MAX]; /*a few info lines.*/
char *error_text; /*only one line for error.*/
int id;
int info_nb_max;
int info_nb;
};
extern struct message3* moduleFcn3(void);
You did not allocate any memory for the info_text strings. You either have to use malloc() first, or if your C library supports it (the GNU one does), use asprintf() instead of sprintf() to have it allocate enough memory to hold the whole output string for you:
for(cpt = 0; cpt < 2; cpt++)
asprintf(&module_text3.info[cpt], "info[%u]", cpt);
Don't forget that you also have to free the memory again at some point.
The reason that the following line works:
module_text3.info_text[0] = "toto[0]";
Is that the compiler ensures the string "toto[0]" is stored in memory somewhere, and you just make the pointer module_text3.info_text[0] point to that string.

How to return different types from a single function

I have the following c code :
#include <stdio.h>
#include <stdlib.h>
void *func(int a) {
if (a==3) {
int a_int = 5;
int *ptr_int = &a_int;
return (void *)ptr_int;
}
else if (a==4) {
char a_char = 'b';
char *ptr_char = &a_char;
return (void *)ptr_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
But when I use gcc to test this code, I have the following results :
int value = 98
char value = �
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value = g
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value =
root#coupure:/home/bohao/Desktop/test1375# gcc test.c -o test
root#coupure:/home/bohao/Desktop/test1375# ./test
int value = 98
char value = !
Why do I have the 98 for ptr_int and the random value of ptr_char ?
What I want is to have a general function who can return different types of values instead of using two functions. Is that possible ? If so, how to do it ?
The problem as I see it, you're trying to return the address of a local variable from a function (scope) and trying to access the returned memory from the caller. In the caller, the memory is invalid and any usage will lead to undefined behavior.
Solution: You need to use dynamic memory allocation for the pointer (malloc()/ calloc()) which you want to return from the function. This will overcome the issue here, as the lifetime of the dynamically allocated memory is untill free()-d manually or till program termination, whichever is earlier.
Having said that, this approach is not a good one. If all you want to return one of multiple types, go for a struct containing members for all types and use a flag to mark the type. Fill the corresponding member variable, set the flag and return the structure variable.
For better, you can actually use an union as a member of the structure, as you only need one type at a time. For a working code, please refer to the other answer by #pmg.
You can return (a struct containing) an union
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
union members {
int *intp;
char *charp;
double doublev;
};
struct group {
int lastunionmember;
union members x;
};
struct group f1(void) {
struct group r = {0};
int choice = rand() % 3;
if (choice == 0) {
r.x.intp = malloc(sizeof (int)); // remember to free(intp) at some time
*r.x.intp = 42;
r.lastunionmember = 1;
}
if (choice == 1) {
r.x.charp = malloc(42); // remember to free(charp) at some time
strcpy(r.x.charp, "forty two");
r.lastunionmember = 2;
}
if (choice == 2) {
r.x.doublev = 3.14159;
r.lastunionmember = 3;
}
return r;
}
int main(void) {
struct group x;
srand(time(0));
for (int k = 0; k < 20; k++) {
x = f1();
switch (x.lastunionmember) {
default: printf("invalid value\n"); break;
case 1: printf("int value is %d\n", *x.x.intp); break;
case 2: printf("string is \"%s\"\n", x.x.charp); break;
case 3: printf("double value is %f\n", x.x.doublev); break;
}
}
}
See the code running at ideone.
Your problem is that you are returning the address of a local scoped variable. You have to use dynamic allocation to do what you want to do.
#include <stdio.h>
#include <stdlib.h>
void *func(int a)
{
void *retVal = NULL;
if (a==3)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((int *)(retVal)) = 5;
}
}
else if (a==4)
{
retVal = malloc(sizeof(int));
if (retVal != NULL)
{
*((char *)(retVal)) = 'b';
}
}
else
{
fprintf(stderr, "return value is NULL");
}
return retVal;
}
int main ()
{
int *ptr_int = func(3);
char *ptr_char = func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
free(ptr_int);
free(ptr_char);
return 0;
}
This is because the values that you return the pointers to are of local scope. This means that when the function returns the a_char and a_int variables effectively no longer exist, thus references to them (the pointers) are invalid.
The reason that you see the random output is because the memory that was used by those variables is now being used by something else.
You could either declare these variables at a wider scope (i.e. file scope or program scope) or use dynamic memory allocation.
This example uses file scope variables:
#include <stdio.h>
#include <stdlib.h>
static int a_int = 5;
static char a_char = 'b'
void *func(int a) {
if (a==3) {
return (void *)&a_int;
}
else if (a==4) {
return (void *)&a_char;
}
else {
fprintf(stderr, "return value is NULL");
return NULL;
}
}
int main (int argc, char *argv[]) {
int *ptr_int = (int *)func(3);
char *ptr_char = (char *)func(4);
fprintf(stdout, "int value = %d\n", *ptr_int);
fprintf(stdout, "char value = %c\n", *ptr_char);
return 0;
}
In this specific case you could also just return strings (which would be thread-safe):
#include <stdio.h>
#include <stdlib.h>
char * func(int a) {
if (a == 3) {
return "5";
} else if (a == 4) {
return "b";
} else {
return "Return value is nothing";
}
}
int main (int argc, char *argv[]) {
fprintf(stdout, func(3));
fprintf(stdout, func(4));
fprintf(stdout, func(15));
return 0;
}
If you want a function that return two (or more) values, you have two possibilities:
1- Make the function void and return the values as parameters by reference &
2- Declare a struct (or class) that groups the values and make the function return a value of this struct.

Resources