This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have spent ages trying to figure out what is the problem with the following program:
typedef struct user {
char host[40];
int order;
} user;
typedef struct data {
user userdat;
} data;
int read_user (char *datname, user *userdat) {
...
fscanf (datin, "%s", &userdat->host);
fscanf (datin, "%d", &userdat->order);
//1
printf ("%d\n", userdat->order);
...
}
void init_data (data *dat) {
init_userdat (&dat->userdat);
}
void init_userdat (user *userdat) {
*userdat->host = "127.0.0.1";
userdat->order = 0;
}
int user_print (int i, data *dat) {
//2
printf ("%d\n", dat->userdat.order);
}
int main(int argc, char *argv[]) {
...
data dat;
init_data (&dat);
read_user (datname, &dat->userdat);
user_print (&dat);
}
The program is very simplified to highlight the relevant sections. What happens is that the first print statement (//1) outputs the value correctly, while the second (//2) does not - it outputs something that looks like a possible memory location.
I have tried numerous combinations of accessing the stored variable, but I just can't crack it. Any help would be appreciated.
Edit1: Fixed up a couple of non essential errors in code (not relating to pointers or structs)
Final Edit: Thank you all for your help. The issue that Arun Saha pointed out was indeed in the original code and is now fixed. However, the problem of printing two different strings persisted. Your assurance that the code should otherwise compile and work led me to discover the true culprit - I was not properly initializing another part of the otherwise complex struct and this resulted in overwriting of the user.order variable.
The following line does not do what it appears to do :-)
*userdat->host = "127.0.0.1";
userdata->host is a pointer to the first character in the host[40] array. The above statement would copy only one character from the source string ("127.0.0.1"). To copy the entire string, use the standard library function stncpy()
strncpy( & userdata->host[ 0 ], "127.0.0.1", 40 );
In your main function, when you invoke read_user (datname, &dat->userdat);, I feel there should be a compilation issue. This should be actually read_user (datname, &dat.userdat); as dat is not a pointer, but an object itself.
With this change and Arun's previous recommendation, I have tried your program and it works.
Related
Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
How do I dynamically create an array of struct in a function in C?
The struct:
typedef struct Track {
char artist[LONGSTR];
char file[LONGSTR];
int id;
int isAlbum;
char name[LONGSTR];
int pos;
char title[LONGSTR];
int time;
} Track;
The function:
int
processplaylist (struct Track** tracks, char* resp)
{
//count the tracks to return
//allocate space for the resulting tracks
*tracks = mem_alloc (count * sizeof (struct Track));
//process each track
return count;
}
And the usage:
char playliststr[] = "file: some-mp3\nTitle: Dire Straits - Romeo And Juliet\nName: TheRadio\nPos: 0\nId: 12\nOK\n"
struct Track* tracks = NULL;
int count = mpd_processplaylist(&tracks, playliststr);
Within the function the tracks are nicely processed and upto the return statement tracks points to the right location to get to the tracks. Most questions I have seen are about arrays to values, not structs.
This answer returns an array of structs, but I would like to return the count (question of style) and return the array through the parameter.
What is going wrong? After the function returns, count has the right value and tracks is still NULL.
As the not so nice people pointed out by down voting the question, the question is too broad and vague. I apologize for that, I was desperate.
As the nice people in the comments confirmed, the code is correct. Even though the debugger showed that just before the return statement everything was OK and after returning to the usage it was not.
By commenting out code lines and logging a lot, there are two things to note.
Within the function, you must refer to the individual tracks as (*tracks + i) or, for example, (*(*tracks + i)).file. Indeed, not shown in the sample code. I had tried *(tracks + i), &tracks[i] and tracks + i, which in the debugger all seemed to work and did not cause immediate errors. I guess the code messed up memory that only came out after the return.
Outside the function, in the usage, you refer to the tracks as an array, as tracks[i] or, for example, tracks[i].file.
I hope that at least my answer helps.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I want to extract the words from a file (and later, from console input), count their appearances and store them in my Word structure:
typedef struct cell{
char *info; /* word itself */
int nr; /* number of appearances of the word *
}*Word;
This structure will be allocated dynamically for as many words are contained in the file. Consider this function:
void Word_Allocation (Word* a) /* The function that allocates space for one structure */
My questions are:
How do I correctly open a file and read it line by line?
How do I correctly store words and number of appearances in my structure?
As for file io, this is the basics.
As for the algorithm, since you are not using C++, so map is not available which is trivial for this problem. A straightforward solution in C might be:
Allocated an array of cell and read in words
sort the array on char *info.
count
Your allocator function should return a Word* and receive a size to allocate for the word itself. Something like this, perhaps:
Word * Word_Allocation (size_t size) {
Word *w = malloc(sizeof(*w));
if (w) w->info = malloc(size);
if (!w->info)
{
free(w);
w = NULL;
}
return w;
}
You can read a word at a time with:
#define STR(x) #x
enum {MAX_BUF = 100};
char buf[MAX_BUF];
fscanf(infile, "%" STR(MAX_BUF) "s", buf);
And then strlen(buf)+1 is the size to pass to Word_Allocation. Or you can pass buf and have Word_Allocation call strlen and copy the data over.
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
[EDIT:]
I have removed a lot of code now. And I have reduced it to a more straight forward question.
Is it OK, to pass this variable...
char Record_Info[file_length + 1];
to another function, like this:
listdir(tempdesc, 0, sockid, Record_Info);
which uses this header:
int listdir(char *dirname, int lvl, int sockid, char Record_Info[])
And the listdir() can call its-self many times?
.
* Orig Question *
I was wondering if another set of eyes can look at this please. It was working, but I added some more code (probably more sprintf, near the bottom) and now a Segmentation fault occurs.
This program creates/sends the web page, correctly, but crashes when it returns from the send_recordings_list() function back to the parsing_request() function. I don't think its necessary to understand how its formatting the data from the file, but I included that bit anyway.
For the most part, I'm using static variables, and when I attempt to free() any thing, it causes another seg fault, or gcc lib fault. Also I am unsure if passing the variables between the functions() might be causing the issue?
Also worth mentioning, a different function (not shown in here) sends out a web page which is about 4MB, I can call this one many times and it does not crash. I have placed a few // ****** at some lines which might be of interest?
Oh yes, I have not done much standard error handling yet... (I'll do it later), so assume its a spherical chicken in a vacuum.
.
So it starts at parsing_request()
goes to send_recordings_list()
goes to listdir() . (this calls its self many times)
back to send_recordings_list()
. (seg fault here)
back to parsing_request()
.
I'm hoping some will go 'ahh i see what you did fool......'
Embedded Linux 2.6.27, GCC 4.2.4, 32MB Ram
void parsing_request(int sockid, char *buff)
{
char *res_line=malloc(MAXLINE), path[MAXLINE], *line;
// Cut code
if (strcmp(line, "/recordings_body.htm") == 0)
{
send_recordings_list (sockid); // ****** IT GOES HERE 1st ******
return;
}
free (res_line);
return;
}
int send_recordings_list(int sockid)
{
int hnd;
int hnd2;
char tempdesc[MAX_PATH_LENGTH];
// Copy all of the data <1 MiB (Slow reading)
int file_length = lseek (hnd2, 0, SEEK_END);
char Record_Info[file_length + 1]; // ******
lseek (hnd2, 0, SEEK_SET);
read (hnd2, Record_Info, file_length);
close (hnd2);
// Cut out code
del_file_cnt = 0;
sprintf (tempdesc, "%s/Recordings", TOPPY_DIR);
listdir(tempdesc, 0, sockid, Record_Info); // ***** Major 2nd call here
return 0;
}
int listdir(char *dirname, int lvl, int sockid, char Record_Info[])
{
int i;
DIR* d_fh;
struct dirent* entry;
char longest_name[4096];
char tempdesc[4096], morespace[128];
int row_col;
char chan_name[128], alt_name[128], desc[500], category[128], rec_time[14], start_time[14], end_time[14];
char trim_file_name[128], trim_file_name2[128], trim_alt_name[128], file_links[1535];
char logo[128];
int length, u_score, dot;
char *looky_pos1, *looky_pos2;
int is_match;
struct tm tm_rec, tm_start, tm_end;
time_t tim_rec, tim_start, tim_end;
// Cut out code
return 0;
}
Sorry, this is a hopeless mess. Learn how to use Linux tools like valgrind and gdb. Check carefully that the memory you request is eventually freed once and after its use is done. Check that you don't pass pointers to local variables out of functions. Check that your strings are long enough to accomodate the data expected (or check as part as your as of now nonexistent error handling).
One debugging strategy that is suprisingly effective is the Teddy Bear Consultant: Get a teddy bear and explain your problem to it step by step. Only if that doesn't help is a real human warranted. [It works because sorting out your understanding to explain it forces you to really think it through.]
After looking quickly at your code, you have two options:
Learn how to handle errors, how to manage resources and how to avoid global variables
Use a programming language which does it for you
Both will take a long time but using the second approach, you will be much more productive.
I suggest to try to implement the above with Python just to get a feeling.
Answering your most recent post, asking if you can pass the character value into the function... I don't understand what you're trying to do. In the function prototype you have the final parameter as a char variable_name[], are you trying to pass a array in? If so, why not use a pointer?
so the prototype would like like:
int listdir(char *dirname, int lvl, int sockid, char* Record_Info);
Passing by reference always tends to give you a little bit more control, whether you want it or not. Are you trying to pass in a specific element of an array?
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I want to create an array of structures:
typedef struct
{
int id;
int department;
}employee;
int main(int argc, char *argv[])
{
int i;
employee job[3]; ////////////////error
for (i=0;i<3;i++)
{
//do something
}
return 0;
}
the issue is that when I want to compile I got the following error:
syntax error before ';' token and points to the line that I marked
Any help?
Thanks
That code, as it stands alone, is fine, as per the following transcript:
pax> cat qq.c
typedef struct {
int id;
int department;
} employee;
int main (int argc, char *argv[]) {
int i;
employee job[3]; ////////////////error
for (i=0;i<3;i++) {
//do something
}
return 0;
}
pax> gcc -o qq qq.c
pax>
. Some things you may want to check are:
Has anything #defined something like employee or job?
Are you sure employee is spelt identically in both places?
Are you sure you have all those semicolons you claim to have?
Are there any "funny" characters in your code (ones that seem invisible but still stuff up your input stream to the compiler)?
A good first start would be to comment out the errant line and see if you get the error on the following line. That should narrow it down to either that line (no error) or a previous line (still have error).
You can see the entire file in hex mode (looking for funny characters) if you do something like:
od -xcb myfile.c
(under Linux - Windows I'm not sure though, if you have gvim, you can convert it to hex with a menu item).
This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I have a few questions about structs and pointers
For this struct:
typedef struct tNode_t {
char *w;
} tNode;
How come if I want to change/know the value of *w I need to use t.w = "asdfsd" instead
of t->w = "asdfasd"?
And I compiled this successfully without having t.w = (char *) malloc(28*sizeof(char));
in my testing code, is there a reason why tt's not needed?
Sample main:
int main()
{
tNode t;
char w[] = "abcd";
//t.word = (char *) malloc(28*sizeof(char));
t.word = w;
printf("%s", t.word);
}
Thanks.
t->w is shorthand for (*t).w i.e. it only makes sense to use the arrow if t is a pointer to a struct.
Also, since the string you assigned is hard-coded (thus, determined at compile time), there's no need to dynamically allocate its memory at runtime.
Take a look at this tutorial: http://pw1.netcom.com/~tjensen/ptr/ch5x.htm
struct tag {
char lname[20]; /* last name */
char fname[20]; /* first name */
int age; /* age */
float rate; /* e.g. 12.75 per hour */
};
kay, so we know that our pointer is going to point to a structure declared using struct tag. We declare such a pointer with the declaration:
struct tag *st_ptr;
and we point it to our example structure with:
st_ptr = &my_struct;
Now, we can access a given member by de-referencing the pointer. But, how do we de-reference the pointer to a structure? Well, consider the fact that we might want to use the pointer to set the age of the employee. We would write:
(*st_ptr).age = 63;
Look at this carefully. It says, replace that within the parenthesis with that which st_ptr points to, which is the structure my_struct. Thus, this breaks down to the same as my_struct.age.
However, this is a fairly often used expression and the designers of C have created an alternate syntax with the same meaning which is:
st_ptr->age = 63;
How come if I want to change/know the value of *w I need to use t.w =
"asdfsd" instead of t->w = "asdfasd"?
If your t is a pointer, you need to use t->w. Else you should use t.w.
in my testing code, is there a reason why tt's not needed?
In your code you have already set your t.word to point to the area storing your char w[] = "abcd";. So you don't need to malloc some memory for your t.word.
Another example where malloc is needed is:
tNode t;
t.word = (char *) malloc(28*sizeof(char));
strcpy(t.word, "Hello World");
printf("%s", t.word);
How come if I want to change/know the value of *w I need to use t.w =
"asdfsd" instead of t->w = "asdfasd"?
t is a tNode, not a pointer to tNode, so . is the appropriate accessor.
And I compiled this successfully without having t.w = (char *)
malloc(28*sizeof(char)); in my testing code, is there a reason why
tt's not needed?
This isn't needed because "abcd" is still in scope so w can just point to it. If you want w to point to persistent memory-managed contents, it will have to allocate its own memory as it would with this line.