I have a structure
struct services {
char *actived[50];
char *disactived[50];
};
and a function :
void servicesInfo(struct services *services_i) {
FILE *fp;
int status;
char *tmp;
const char *actived_cmd ="/usr/sbin/service --status-all | awk '/[+]/{ print $4 }'" ;
fp = popen(actived_cmd, "r");
int i=0;
while (fgets(tmp, 1024, fp)){
printf("service %s\n", tmp);
(services_i->actived)[i]=tmp;
i++;
}
status = pclose(fp);
}
when i call the function
struct services services_i;
servicesInfo(&services_i);
all is fine and all services printed, but if this code
for (i = 0; i < 20; ++i)
{
printf("service i=%d %s\n",i,services_i.actived[i] );
}
print just the last value (uvrandom)
You need to read up on C pointer and memory allocation. There are two misunderstandings here:
tmp is not, as it is written, a string buffer. It is just a string pointer. It can only be assigned to point to strings that are allocated somewhere else, and not contain the string itself.
You are just copying the pointer to actived (which by the way probably should be spelled activated). This means that all actived pointers all point to the same as tmp does, which is always the same, since tmp is never changed (and also has uninitialized value).
I suggest you use tmp = malloc(1024). Don't forget to use free(services_i.actived[i]) when you don't need them anymore.
I also suggest making an array of structs instead of a struct of arrays, to make it more logical.
Here is some example code of how to assign a value to structure:
#include <stdio.h>
struct date { /* global definition of type date */
int month;
int day;
int year;
};
main()
{
struct date today;
today.month = 10;
today.day = 14;
today.year = 1995;
printf("Todays date is %d/%d/%d.\n", \
today.month, today.day, today.year );
}
Related
So i'm writing this code for an assignment for school, and what I have to do is have two functions as they're written, with createMonster returning a dynamically allocated monster with data, and readMonsters returning an array of pointers to the monsters made in createMonster. I've been having trouble understanding how to get the functions and structs to cooperate, and this is what I have so far:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct monster {
int id;
char *name;
char *element;
int population;
} monster;
monster* createMonster(char *name, char *element, int population)
{
monster *amonster = (monster*)malloc(sizeof(monster));
amonster->name = (char*)malloc(sizeof(char)*sizeof(name));
amonster->element = (char*)malloc(sizeof(char)*sizeof(element));
amonster->population = (int)malloc(sizeof(int)*sizeof(population));
amonster->name = name;
amonster->element = element;
amonster->population = population;
return amonster;
}
monster** readMonsters(FILE* infile, int *monsterCount)
{
char n[15], e[15];
int p;
monster **a_array = malloc(*monsterCount * sizeof(struct a*));
for (int i = 0; i < *monsterCount; i++) {
a_array[i] = malloc(sizeof(monster));
fscanf(infile,"%s %s %d",n, e, &p);
printf("%s %s %d\n", n, e, p);
a_array[i] = createMonster(n,e,p);
}
monster ***m = &a_array;
return *m;
}
int main(){
int monsterCount;
char name[15];
FILE *fp = fopen ( "in.txt", "r" );
fscanf(fp,"%d %s",&monsterCount,name);
//printf("test %d\n",monsterCount);
monster **mptr = readMonsters(fp,&monsterCount);
printf("%s %s %d\n", (mptr)[3]->name,(mptr)[3]->element,(mptr)[3]->population);
fclose(fp);
return 0;
}
With the input file being:
8 monsters
StAugustine Grass 12
Zoysia Grass 8
WholeWheat Bread 6
MultiGrain Bread 10
Rye Bread 10
Cinnamon Spice 5
Pepper Spice 10
Pumpkin Spice 30
However, when I run it, I can see it works as far as making them the first time, but when I try and go back to access the data it returns garbage for the strings, with this being my output:
StAugustine Grass 12
Zoysia Grass 8
WholeWheat Bread 6
MultiGrain Bread 10
Rye Bread 10
Cinnamon Spice 5
Pepper Spice 10
Pumpkin Spice 30
`7 w├?]╨# 10
w├?]╨# 10
I've tried rearranging the functions, pointers, etc. and have tried many different versions of these functions trying to follow guides online, but each time it either doesn't work at all or returns garbage. I'm looking for any help in understanding how to get this working or how it could be organized better since I will readily admit my experience with C is moderate at best.
The code you posted has the following issues:
The line
amonster->name = (char*)malloc(sizeof(char)*sizeof(name));
does not make sense. sizeof(name) is the size of the pointer, which is 32-bit or 64-bit, depending on your platform. However, you probably need to allocate more than that. You need to allocate strlen(name) + 1 bytes, because that is the length of the string that is passed to the function (including the null terminating character). The same also applies to the next line:
amonster->element = (char*)malloc(sizeof(char)*sizeof(element));
Also, the line
amonster->population = (int)malloc(sizeof(int)*sizeof(population));
does not make sense, because amonster->population is not a pointer. Why are you trying to store a pointer to dynamically allocated memory in it? You shouldn't need dynamic memory allocation here, because amonster->population is not a string, but a fixed-length variables, for which you have already allocated space, because it is part of the struct. Therefore, you can delete this line. All you need is the line amonster->population = population;, which you already have.
Additionally, the line
amonster->name = name;
does not do what you want. It does not copy the string, it only copies the pointer, i.e. the memory address. That way, you are copying a pointer which will be a dangling pointer by the time you return to the function main. In order to copy the actual string, you must write strcpy( amonster->name, name );. The same applies for the following line:
amonster->element = element;
The line
a_array[i] = malloc(sizeof(monster));
is unnecessary and only creates a memory leak. You have already allocated space for all structs in the function createMonster.
The lines
monster ***m = &a_array;
return *m;
are unnecessarily cumbersome and can be simplified to the following:
return a_array;
After applying all of these fixes, your code should look like this:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct monster {
int id;
char *name;
char *element;
int population;
} monster;
monster* createMonster(char *name, char *element, int population)
{
monster *amonster = (monster*)malloc(sizeof(monster));
amonster->name = (char*)malloc(sizeof(char)*(strlen(name)+1)); //fixed
amonster->element = (char*)malloc(sizeof(char)*(strlen(element)+1)); //fixed
//amonster->population = (int)malloc(sizeof(int)*sizeof(population)); //redundant
strcpy( amonster->name, name ); //fixed
strcpy( amonster->element, element ); //fixed
amonster->population = population;
return amonster;
}
monster** readMonsters(FILE* infile, int *monsterCount)
{
char n[15], e[15];
int p;
monster **a_array = malloc(*monsterCount * sizeof(struct a*)); //what is struct a???
for (int i = 0; i < *monsterCount; i++) {
//a_array[i] = malloc(sizeof(monster)); //redundant
fscanf(infile,"%s %s %d",n, e, &p);
printf("%s %s %d\n", n, e, p);
a_array[i] = createMonster(n,e,p);
}
//monster ***m = &a_array; //removed
//return *m; //removed
return a_array;
}
int main(){
int monsterCount;
char name[15];
FILE *fp = fopen ( "in.txt", "r" );
fscanf(fp,"%d %s",&monsterCount,name);
//printf("test %d\n",monsterCount);
monster **mptr = readMonsters(fp,&monsterCount);
printf("%s %s %d\n", (mptr)[3]->name,(mptr)[3]->element,(mptr)[3]->population);
fclose(fp);
return 0;
}
As demonstrated here, your program now provides the correct output.
I'm working on a function that works as part of a larger program. My C pointer skills are a bit rusty and so I need some help here.
I keep getting segmentation fault errors, and I feel like there is a very trivial solution to my question, and any explanation would help!
Essentially, I have an empty array of structs that I need to pass through to a function as a double pointer. That function will open and read a file saving the contents of the file in the array of structs.
I need to pass it as a double pointer.
This is what I have so far:
struct node{
int first_value;
int second_value;
};
unsigned char readFunction(char *fileName, int *limit, struct node **arrayToFill){ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fopen(fileName, "r");
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
for(i=0; i<(*limit); i++){
fscanf(input, "(%d, %d)", &temp1, &temp2);
(*(arrayToFill+i))->first_value = temp1;
(*(arrayToFill+i))->second_value= temp2;
}
//More code
return 0; //Actually returns another array but that's irrelevant.
}
int main(){
//NOTE: I just created these variables for the sake of showing it on StackOverflow, I still get a Segmentation Fault error when I run the program.
char name[9] = {'t', 'e', 's', 't', '.', 't','x','t', '\0'};
struct node arrayToPass[10];
struct node *pointer = &arrayToPass;
struct node **data = &pointer;
unsigned char returnedVal;
int limit = 10;
returnedVal = readFunction(&name, &limit, data);
return 0;
}
Thanks in advance!
You have several problems. The first is you are using the arrayToPass[10] pointer incorrectly, all you need is:
int main (void) {
struct node arrayToPass[10];
int limit = 10;
printf ("return: %hhu\ncontent:\n", readFunction(NULL, &limit, &arrayToPass));
for (int i = 0; i < limit; i++)
printf ("%5d %5d\n",
arrayToPass[i].first_value, arrayToPass[i].second_value);
}
Do not attempt to cast around your struct node (*arrayToPass)[10] pointer when you pass the address by assigning to different pointers. You begin with type struct node [10] (array of struct node [10]) when you take the address you have struct node (*)[10] (pointer to array of struct node [10]). It is separate and district from struct node ** (pointer to pointer to struct node).
Your function then takes the type struct node (*arrayToFill)[10], e.g.
unsigned char readFunction (char *fileName, int *limit, struct node (*arrayToFill)[10])
{ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fileName ? fopen (fileName, "r") : stdin;
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
while (i < *limit && fscanf(input, " (%d, %d)", &temp1, &temp2) == 2) {
(*arrayToFill)[i].first_value = temp1;
(*arrayToFill)[i].second_value = temp2;
i++;
}
*limit = i;
return 0; //Actually returns another array but that's irrelevant.
}
(note: the use of the ternary operator allowing NULL to be passed as fileName to read from stdin -- that was just for my convenience)
(also note: that since you declare struct node arrayToPass[10]; with automatic storage duration in main(), you don't need to pass the address of the pointer, you only need to pass the address of the pointer if the address can changes in your function -- such as if you call realloc on the pointer. The other answer addresses that point.)
The difference between needing to pass struct node ** or struct node (*)[10] or simply struct node * boils down to how memory is allocated for the original collection. If as you have done, declaring struct node arrayToPass[10]; in main() with automatic storage duration, storage for the array is fixed. On access, the array is converted to a pointer (struct node *) and you can simply pass the array itself as the parameter. (but you are limited to no more than the number of elements originally declared)
If however, you have an allocated storage type for arrayToPass in main (e.g. struct node *arrayToPass = malloc (10 * sizeof *arrayToPass);, then if you need to change the amount of storage, e.g. the number of stuct node that your allocated block of memory can hold in readFunction(), then you must pass the address of the pointer, so if reallocation takes place, and the beginning address for your block of memory changes, that change will be seen back in the caller (main() here). In that case when you pass the address of struct node *, then your type becomes struct node **. (because you have taken the address of a pointer instead of the address of an array)
Since your arrayToPass can't be reallocated, and the storage is fixed before it is passed to readFunction(), you don't need to pass the address and you can eliminate one level of pointer indirection and just pass the array as type struct node *. That simplifies access in your function to simply arrayToFill[i].first_value = temp1;, the [..] acting as a dereference of the pointer, just as -> does.
You also may want to change the return type from unsigned char to size_t and return the number of elements filled in your struct (a meaningful return) -- or you can update the limit pointer as I did -- your choice.
The complete example is:
#include <stdio.h>
struct node {
int first_value;
int second_value;
};
unsigned char readFunction (char *fileName, int *limit, struct node (*arrayToFill)[10])
{ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fileName ? fopen (fileName, "r") : stdin;
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
while (i < *limit && fscanf(input, " (%d, %d)", &temp1, &temp2) == 2) {
(*arrayToFill)[i].first_value = temp1;
(*arrayToFill)[i].second_value = temp2;
i++;
}
*limit = i;
return 0; //Actually returns another array but that's irrelevant.
}
int main (void) {
struct node arrayToPass[10];
int limit = 10;
printf ("return: %hhu\ncontent:\n", readFunction(NULL, &limit, &arrayToPass));
for (int i = 0; i < limit; i++)
printf ("%5d %5d\n",
arrayToPass[i].first_value, arrayToPass[i].second_value);
}
Example Input File
$ cat dat/2x8rand.txt
(17987, 1576)
(12911, 4488)
(30688, 5875)
(25617, 16643)
(8999, 26249)
(29270, 31857)
(8954, 2094)
(21390, 27676)
Note the change in the fscanf format-string including an additional ' ' (space) before the opening parenthesis '(' to consume the '\n' (and any leading whitespace). You cannot use any input function correctly unless you check the return (e.g. fscanf(input, " (%d, %d)", &temp1, &temp2) == 2)
Example Use/Output
$ ./bin/ptrtoarraystruct < dat/2x8rand.txt
return: 0
content:
17987 1576
12911 4488
30688 5875
25617 16643
8999 26249
29270 31857
8954 2094
21390 27676
Look things over and let me know if you have further questions.
I believe you may want something like the following.
#include <stdio.h>
struct node{
int first_value;
int second_value;
};
unsigned char readFunction(char *fileName, int limit, struct node *arrayToFill){ //Many more variables passed, but I removed it for the sake of simplicity
FILE *input;
input = fopen(fileName, "r");
if (input == NULL) {
printf("error: could not read the input file!\n");
}
int i=0;
int temp1, temp2;
for(i=0; i<limit; i++){
fscanf(input, "(%d, %d)", &temp1, &temp2);
arrayToFill[i].first_value = temp1;
arrayToFill[i].second_value = temp2;
}
//More code
return 0; //Actually returns another array but that's irrelevant.
}
int main(){
//NOTE: I just created these variables for the sake of showing it on StackOverflow, I still get a Segmentation Fault error when I run the program.
char name[9] = "test.txt";
struct node arrayToPass[10];
unsigned char returnedVal;
int limit = 10;
returnedVal = readFunction(name, limit, arrayToPass);
return 0;
}
I am creating a program that modifies a dynamic array. It must initialize the array and be able to insert into it. I have been unable print the array after in order to test it, how would I go about this?
Piece of relevant code:
typedef struct {
char first;
char second;
} name;
typedef struct {
int number;
name name;
} data;
/*points to array, number allocated, number used*/
typedef struct {
data *info;
size_t numof;
size_t numused;
} list;
void init(list *l) {
l->data = malloc(sizeof(l) * l->numof);
l->numused = 0;
l->numof = 2;
}
int insert(list *l, const data *dat) {
if (l->numused == l->numof) {
l->numof *= 2;
l->data = (int *)realloc(l->data, l->numof * sizeof(int));
}
l->data[l->numused++] = *dat;
return 0;
}
int main(void) {
int i;
list l;
data list1;
/*example info for testing*/
list.number = 1234;
strcpy(list1.name.first, "abc");
strcpy(list1.name.second, "xyz");
init(&l);
insert(&l, list1);
/*runs through array elements to print*/
for (i=0; i < ((int)sizeof(&l)) /(int)sizeof(&l); i++) {
printf("%s\n", list1);
}
return 0;
}
Edit: I just need to know how to print the array to see if I'm doing it correctly, the code above will have errors as I had been messing around trying to figure it out.
strcpy(list1.name.first, "abc");
strcpy(list1.name.second, "xyz");
These both will invoke undefined behaviour as first and second are declared as char variables , and you copy string literals to them .
You need to declare both of them as character arrays .
And this -
for (i=0; i < ((int)sizeof(&l)) /(int)sizeof(&l); i++) {
printf("%s\n", list1);
}
You try to print struct variable list1 with %s specifier, maybe you tend to print the strings that you wanted to copy. So directly print list1.name.first and list1.name.second in printf with %s specifier.
And the condition -
i < ((int)sizeof(&l)) /(int)sizeof(&l)
The cast is not necessary , and it will yield 1 so, loop will run for 1 time . Change the condition .
In your code, the member of structure name is defined as char. But you are trying to copy a string into it. May be this was a typo. If not you should define them as character array or character pointer. Also in your print statement you are trying to print structure data as string. It should be like -
printf("%s %s\n", list1.name.first, list1.name.second);
Also you assigned value 1234 to list.number. You may have meant list1.number. The parameters in function call of insert is wrong as well. And lastly, you have put l->data in functions init and insert which should be l->info.
I have a program which creates an array or struct and go through it for processing. Initially it initialize the array with the defined nyumber of elements. Then for some number of element in array, the name is assigned.
I pretend the code that is equal to my scenario which is tested in codebloc and get the similar error. The problem is described in comments.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct _car {
char *name;
int year;
} Car;
char *getCarName(char *name, int var);
void processCar();
void printCars(Car car[]);
int INCREMENT = 10;
int main(void)
{
processCar();
return 0;
}
void processCar()
{
// create car array with amount of INCREMENT
Car CAR_ARRAY[INCREMENT];
int a=0;
// This function assign name for Car amount 10 less than INCREMENT
while (a<INCREMENT - 2) {
char *carName;
carName = getCarName(&carName, a);
CAR_ARRAY[a].name = malloc(strlen(carName) + 1);
strcpy(CAR_ARRAY[a].name, carName);
a++;
}
printCars(CAR_ARRAY);
}
void printCars(Car car[])
{
printf("IN Car \n");
int a = 0;
// when try to call name for car amount equals to INCREMENT program terminates.
while(a<INCREMENT) {
if (car[a].name != NULL) // checking if NULL
printf("Car Name : %d -> %s\n", a, car[a].name);
a++;
}
}
char *getCarName(char *name, int var)
{
name = "Toyota";
return name;
}
What is the right way to check the struct value on struct array whether it can be called?
EDIT
I created a hack to do this as follows.
// added these right after creating array
for (a = 0; a < INCREMENT; a++)
CAR_ARRAY[a].name = NULL;
I dont know if it is a standard way or not. pls advice.
You are checking for NULL before printing, which is a good idea, but it doesn't help you here, because your last two cars are uninitialised and likely contain garbage: The name pointer is not NULL, but doesn't point to a valid address either. Segmentation violation ensues.
You should initialise all cars, not only INCREMENT - 2. Alternatively, you could initialise your cars to zero by calling memset before your initialisation:
memset(CAR_ARRAY, 0, sizeof(Car) * INCREMENT);
As an aside, the way you deal with getCarName is rather shaky as well. At the moment, your name is a pointer to a string literal. Your local variable carName does a half-hearted double duty: You try to pass it by reference (but essentially you don't) and you also return it.
Basically, you could do this in one of two ways. The easier one here is to return a pointer. in that case, you don't have to pass any string:
char *getCarName(int var)
{
static char *names[3] = {"Toyota", "Dodge", "Peugeot"};
return names[var % 3];
}
and call it like so:
char *carName = getCarName(&carName, a);
Alternatively, you could pass a char pointer by reference, i.e. as pointer to pointer to char. In that case, you don't have to return anything:
void getCarName(char **name, int var)
{
static char* names[3] = {"Toyota", "Dodge", "Peugeot"};
*name = names[var % 3];
}
Call it like so:
char *carName;
getCarName(&carName, a);
There are other scenarios here, for example if you just pass a char pointer and have getCarName fill it, but I'll leave that for now - it would make everything even more complicated.
I'm trying to split a string every X amount of characters, and then store each line in an array of structs. However, I'm wondering what would be a short and efficient way of doing it. I thought that maybe I could use sscanf, but not very sure how to. Any help will be appreciated. So far I have:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct st {char *str;};
int main ()
{
struct st **mystruct;
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = strlen(tmp)/max + 1;
mystruct = malloc(alloc * sizeof *mystruct);
for (j = 0; j < alloc; j++)
mystruct[j] = malloc(sizeof *mystruct[j]);
const char *ptr = tmp;
char field [ max ];
int n;
while (*ptr != '\0') {
int line = sscanf(ptr, "%s", field, &n); // not sure how to use max in here
mystruct[j]->str = field;
field[0]='\0';
if (line == 1)
ptr += n;
if ( n != max )
break;
++ptr;
++j;
}
return 0;
}
So when I iterate over my struct, I can get something like:
For configuration op
tions (arch/xxx/conf
ig.in, and all the C
onfig.in files),some
what different inden
tation is used.
You could use strncpy.
FYI:
char field [ max ];
while (...) {
mystruct[j]->str = field;
Two problems with this: (1) every struct in your array is going to end up pointing at the same string, which will have the value of the last thing you scanned, (2) they are pointing to a variable on the stack, so when this function returns they will be trashed. That doesn't manifest itself visibly here (e.g. your program doesn't explode) because the function happens to be 'main', but if you moved this to a separate routine and called it to parse a string, you'd get back garbage.
mystruct doesn't need to be pointer to pointer. For a 1D array, just allocate a block N * sizeof *myarray for N elements.
A common C idiom when dealing with structs is to use typedef so you don't have to type struct foo all the time. For instance:
typedef struct {
int x, y;
} point;
Now instead of typing struct point pt you can just say point pt.
If your string is not going to change after you split it up, I'd recommend using a struct like this:
struct st {
char *begin;
char *end;
};
or the alternative:
struct st {
char *s;
size_t len;
};
Then instead of creating all those new strings, just mark where each one begins and ends in your struct. Keep the original string in memory.
One option is to do it character-by-character.
Calculate the number of lines as you are currently doing.
Allocate memory = (strlen(tmp) + number_of_lines) * sizeof(char)
Walk through your input string, copying characters from the input to the newly allocated memory. Every 20th character, insert a null byte to delimit that string. Save a pointer to the beginning of each line in your array of structs.
Its easy enough?
#define SMAX 20
typedef struct {char str[SMAX+1];} ST;
int main()
{
ST st[SMAX]={0};
char *tmp = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
int i=0,j;
for( ; (st[i++]=*(ST*)tmp).str[SMAX]=0 , strlen(tmp)>=SMAX; tmp+=SMAX );
for( j=0;j<i;++j )
puts(st[j].str);
return 0;
}
You may use (non C standard but GNU) function strndup().
#define _GNU_SOURCE
#include <string.h>
struct st {char *str;};
int main ()
{
struct st *mystruct; /* i wonder if there's need for double indirection... */
char tmp[] = "For configuration options (arch/xxx/config.in, and all the Config.in files),somewhat different indentation is used.";
size_t max = 20, j = 0; // max length of string
size_t alloc = (strlen(tmp) + max - 1)/max; /* correct round up */
mystruct = malloc(alloc * sizeof mystruct);
if(!mystruct) return 1; /* never forget testing if allocation failed! */
for(j = 0; j<alloc; j++)
{
mystruct[j].str = strndup(tmp+alloc*max, max);
}
}