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 am trying to read in a struct from a file and then display (and sort) and array. I am having trouble though which I think is to do with me not accessing the correct memory. When I print the array it comes up as loads of random numbers.
struct details
{
int numberOfPresents;
int numberOfBuildings;
int buildings[];
};
void print_int_array(const int *array)
{
for(int i=0; i<200; i++)
printf("%d | ", array[i]);
putchar('\n');
}
void sort(int buildings[], int count)
{
int i, j, temp;
do {
j = 0;
for (i = 0;i<count-1;i++)
{
if (buildings[i] < buildings[i+1])
{
j = 1;
temp = buildings[i];
buildings[i] = buildings[i+1];
buildings[i+1] = temp;
}
}
} while (j == 1);
}
int main()
{
FILE *fp;
fp = fopen("buildings.out", "r");
struct details data1;
size_t structSize = sizeof(struct details);
//size_t arraySize = sizeof(int)*sizeof(buildings);
fread(&data1, structSize, 1, fp);
for(int i=0; i<200; i++)
printf("%d | ", data1.buildings[i]);
//sort(data1.buildings );
//print_int_array(data1.buildings, arraySize);
//printf("Number of Houses: %d\n",numberOfHouses(data1.numberOfPresents, data1.buildings));
fclose(fp);
return 0;
}
The sizeof your struct only includes a minimal allocation for the array (one entry, I think). It doesn't actually allocate enough for the 200 entries you want. There are a few possible fixes.
If it will always be 200 entries, then just declare buildings as having size 200. This is the easiest.
If you know the number of entries prior to reading it, then you can do something unpleasant like (s is the number of entries):
struct details *data1 = (struct details *) malloc(sizeof(struct details)+s*sizeof(int));
and free data1 when you are done. This type of code is generally frowned upon but used to be quite common. The read command gets complicated as well.
The final option would be to change buildings to an int* and then malloc that array before reading. Again, the read would have to be done in a loop.
You've got two issues working against you printing the data.
Enough room is not allocated for the records.
Enough data is not read for the records.
The line struct details data1 only allocates enough room on the stack for one copy of the struct. You need enough for 200 of them. I'd immediately suggest an array.
struct details data1[200];
When you perform the read, fread(&data1, structSize, 1, fp), you're only reading in one record of size structSize. Now that you have enough memory allocated to read in 200 records, you can bump up the number of records you're reading to 200 as well.
fread(data1, structSize, 200, fp);
(Notice we dropped the & because we're dealing with an array now. Arrays automatically return their base address if you just reference them by name.)
Now, what if your file doesn't have 200 records in it? You probably need to capture the return value of fread() to determine how many records you actually read.
int intNumberOfRecords = fread(&data1, structSize, 200, fp);
for(int i=0; i<intNumberOfRecords ; i++)
[...]
Now that we have that working, we can look a little closer at the srtuct itself. We've got a challenge with the definition that we can't easily overcome.
struct details{
int numberOfPresents;
int numberOfBuildings;
int buildings[];
};
The last member, buildings[], is not going to read correctly from a file. This is because it's only a 32-bit integer at best in a 32-bit memory model. In other words, what you'll be reading from the disk is just a 32-bit number that points to somewhere in memory. What you won't end up with is an array that contains the buildings. If you try to access it (i.e. in your sort routine) you'll more than likely seg-fault and your program will never work. Trying to post a general solution for this is a little out of the scope of my answer. Suffice it to say, you'll either have to go with a fixed size array or dynamically write variable size arrays to disk (variable length records). The fixed size array would be a lot easier. If we change your definition to the following, we'd load up some data from the disk.
struct details{
int numberOfPresents;
int numberOfBuildings;
int buildings[16];
};
We'd also avoid seg-faulting, which is a nice plus. However, I don't know what your input file looks like so I don't know if this will work given your data.
Related
I have to read a txt with data in it. I can read it and store the data, but I don't know why, some stored data is not good after the read method.
Here is my output:
I write out these data with exactly the same code, except that the first is inside the loop and the second is outside of the loop.
I store these data in their own struct arrays. So as you can see, my problem is that I can't access my data outside that loop. What could be wrong?
Here is the full code: https://pastebin.com/wzEJqcZG
And the test data: https://pastebin.com/L7J133mz
This is inside the file read loop:
printf("%c %i - ", sorok[i].futarkod, sorok[i].datum);
for(j=0;j<sorok[i].rendelesCount;j++) {
printf("%i%c", sorok[i].rendelesek[j].db, sorok[i].rendelesek[j].fajta);
}
printf("\n");
And this is outside of the file read loop:
for(i=0;i<5;i++) {
printf("%c %i - ", sorok[i].futarkod, sorok[i].datum);
for(j=0;j<sorok[i].rendelesCount;j++) {
printf("%i%c ", sorok[i].rendelesek[j].db, sorok[i].rendelesek[j].fajta);
}
printf("\n");
}
In the output the first two columns are good, just the text after the dash is not.
test.c:65:14: warning: 'sor' may not be used as an array element due to flexible array member
[-Wflexible-array-extensions]
sor sorok[32];
^
rendeles rendelesek[]; is a flexible array member meaning since it's at the end of the struct you can, in theory, allocate as much memory for the array as you like. However this means the size of any given sor will vary.
Each element of an array in C must be of a fixed size, going from one element to another is simply start-of-array-memory + (i * sizeof(element)). Since sor can be of different sizes it can't be put into an array.
You could use an array of pointers to sor, or you can change sor to contain a pointer to rendeles **rendelesek;. Or both, getting used to working with pointers is good.
The real problem is sor.rendelesek is never allocated. Whichever you choose, you still have to allocate memory to sor.rendelesek else you're writing into someone else's memory. As a flexible array member, you have to use a pointer array and allocate sufficient memory as part of sor.
typedef struct {
char futarkod;
int datum;
int rendelesCount;
rendeles rendelesek[];
} sor;
sor *sorok[32];
for( size_t i = 0; i < 32; i++) {
sorok[i] = malloc(sizeof(sor) + (sizeof(rendeles) * 32));
}
Or you can use a rendelesek ** instead and allocate that directly. Combining both is probably the best option.
typedef struct {
char futarkod;
int datum;
int rendelesCount;
rendeles *rendelesek;
} sor;
sor *new_sor(const size_t num_rendeles) {
sor *new = malloc(sizeof(sor));
new->rendelesek = malloc(sizeof(rendeles) * num_rendeles);
return new;
}
int main()
{
sor *sorok[32];
for( size_t i = 0; i < 32; i++) {
sorok[i] = new_sor(32);
}
Reading inputs into statically allocated structures like this is risky and wasteful because you have to allocate what you think is the most possible elements. It's very easy to allocate way too much or not enough. Instead they should be dynamically allocated as needed, but that's another thing.
OK, so the problem is basically like the title. Couldn't find a question that got all bits of it, so I figured I'd ask.
Say I want an array of structs shaped like the following
typedef struct s_woo{
char** n;
char* x;
} t_woo;
So I believe I should do
t_woo* woos = malloc(num_woos * sizeof(*woos));
Seems simple enough (and should deter people from yelling at me for my habit of casting malloc).
Then I want to initialize the things in each of those structs.
So intuitively I do:
for(i = 0; i < num_woos; i++){
num_ns = randomint1 / randomint2; //let's say num_ns is big, like 250-ish, average, and changes every round of the loop
woos[i].n = malloc(num_ns * sizeof(char*));
woos[i].x = malloc(num_ns * sizeof(char));
for(j = 0; j < num_ns; j++){
woos[i].n[j] = malloc(16 * sizeof(char)); // I just want 16 characters per char*
}
}
This is the boiled down version of what I have in my code. I want to know what can possibly go wrong with what I've written - like any possible thing. I'm not looking for anything in particular, just general problems with the above, like memory/heap issues, pointer mistakes etc.
Leave out "Virtual Memory Exhausted". My code error checks for that using a wrapper function on malloc, so I'm very sure that's not it.
Even better:
static const size_t woo_n_size = 16;
/* To make sure you use 16 everywhere,
* also easier to change it
*/
struct woo_item {
char n[woo_n_size];
char x;
};
struct s_woo {
struct woo_item *items;
size_t size; / * optinal, to keep track of item count */
}
With the woo_item struct you can make sure there is no x without n[woo_n_size] allocated, and vice versa.
You can remember the count of woo_items by having a designated null element to close each of your lists, or just store a size member in s_woo
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 am working on a project in which I need to read CSV lines from a text file into my program. I was given a code skeleton, and asked to fill in functionality. I have a struct containing a variable for each type of value I am going to receive, but my char array is causing segmentation faults.
Here is an excerpt of my code.
None of the exerpt is part of the given code, this is all mine:
My error is a Segmentation Fault(Core Dumped), due to the code within the get timestamp space.
my test file contained only one line,
5, 10:00:10, 1, 997
/*
* YOUR CODE GOES HERE:
* (1) Read an input csv line from stdin
* (2) Parse csv line into appropriate fields
* (3) Take action based on input type:
* - Check-in or check-out a patient with a given ID
* - Add a new health data type for a given patient
* - Store health data in patient record or print if requested
* (4) Continue (1)-(3) until EOF
*/
/* A new struct to hold all of the values from the csv file */
typedef struct {
int iD;
char *time[MAXTIME + 1];
int value;
int type;
}csv_input;
/* Declare an instance of the struct, and assign pointers for its values */
csv_input aLine;
int *idptr;
char timeval[MAXTIME + 1];
int *valueptr;
int *typeptr;
/*Note: because the time char is already a pointer, I did not make another one for it but instead dereferenced the pointer I was given */
idptr = &aLine.iD;
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
*aLine.time[j] = timeval[j];
}
valueptr = &aLine.value;
typeptr = &aLine.type;
/* Get the Patient ID */
*idptr = getchar();
printf("%c", aLine.iD); /* a test to see if my pointers worked and the correct value was read */
/*Skip the first comma */
int next;
next = getchar();
/* get the timestamp */
int i;
for(i = 0; i < MAXTIME; i++)
{
while ((next = getchar()) != ',')
{
timeval[i] = next;
//printf("%s", aLine.time[i]);
}
}
First:
int j; /* iterator variable */
for(j; j < MAXTIME; j++){
You need to set j to some value, j=0 makes sense. Without this you're accessing an array with an uninitialized value and you're going to get UB with that.
Second:
/*Note: because the time char is already a pointer,
No, time is an array of pointers to characters, there is a difference there.
This line:
*aLine.time[j] = timeval[j];
won't work because, for one thing, of your statement but instead dereference the pointer I was given is making an incorrect assumption. Yes, you were given an array of pointers, but they don't point to anything, they are uninitialized and as such you can't deference them until you initialize them to a valid non-NULL value.
I think you were trying to do something like this:
aLine.time[j] = &timeval; //set the pointer to the local static array
but that's only going to work in the local function scope. It'd be better if you malloc to your array of pointers.
char *time[MAXTIME + 1];
this is an array of pointers (pointer to char array) and not an array of chars
The crash come from this line
*aLine.time[j] = timeval[j];
Because as I said aLine.time[j] is a pointer and you have not allocated memory for this pointer before filling its content
Ok, this is a C programming homework question. But I'm truly stuck.
I ask the user to input words, and then I insert the input into an array, but I can't have any control over the number of words the user types.
I guess what I'm asking is how do you declare a an array in C without declaring its length and without asking the user what the length should be.
I know this has something to do with malloc, but if you could give me some examples of how to do this, I would really appreciate it.
You can malloc a block of memory large enough to hold a certain number of array items.
Then, before you exceed that number, you can use realloc to make the memory block bigger.
Here's a bit of C code that shows this in action, reallocating an integer array whenever it's too small to hold the next integer.
#include <stdio.h>
#include <stdlib.h>
int main (void) {
int *xyzzy = NULL; // Initially NULL so first realloc is a malloc.
int currsz = 0; // Current capacity.
int i;
// Add ten integers.
for (i = 0; i < 10; i++) {
// If this one will exceed capacity.
if (i >= currsz) {
// Increase capacity by four and re-allocate.
currsz += 4;
xyzzy = realloc (xyzzy, sizeof(int) * currsz);
// Should really check for failure here.
}
// Store number.
xyzzy[i] = 100 + i;
}
// Output capacity and values.
printf ("CurrSz = %d, values =", currsz);
for (i = 0; i < 10; i++) {
printf (" %d", xyzzy[i]);
}
printf ("\n");
return 0;
}
You can realloc it every time like:
int size = 0;
char **array = malloc(0);
while(/* something */)
{
char *string = // get input
size++;
array = realloc(array, size * sizeof(char*));
array[size - 1] = string;
}
Or in chunks if you care about speed.
Yes, you want malloc. Checkout this tut.
http://www.cprogramming.com/tutorial/dynamic_memory_allocation.html
This site is good in general for learning.
Here is an example of using realloc, it is basically exactly what you are asking to do.
http://www.cplusplus.com/reference/clibrary/cstdlib/realloc/
0) obviously you will need multiple buffers, so you will need a list like structure: perhaps a record with char array 100 chars and a pointer to next structure
1) You need to capture the words char by char and store them in your buffer
2) once the buffer is full you allocate another record, chain it with the previous one and keep going until you are out of mem or the process is over.
That should be better performance than realloc function. I believe malloc is trying to give contious block of memory. Therefore the list like structure will be faster and work better.
I know it could be done using malloc, but I do not know how to use it yet.
For example, I wanted the user to input several numbers using an infinite loop with a sentinel to put a stop into it (i.e. -1), but since I do not know yet how many he/she will input, I have to declare an array with no initial size, but I'm also aware that it won't work like this int arr[]; at compile time since it has to have a definite number of elements.
Declaring it with an exaggerated size like int arr[1000]; would work but it feels dumb (and waste memory since it would allocate that 1000 integer bytes into the memory) and I would like to know a more elegant way to do this.
This can be done by using a pointer, and allocating memory on the heap using malloc.
Note that there is no way to later ask how big that memory block is. You have to keep track of the array size yourself.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv)
{
/* declare a pointer do an integer */
int *data;
/* we also have to keep track of how big our array is - I use 50 as an example*/
const int datacount = 50;
data = malloc(sizeof(int) * datacount); /* allocate memory for 50 int's */
if (!data) { /* If data == 0 after the call to malloc, allocation failed for some reason */
perror("Error allocating memory");
abort();
}
/* at this point, we know that data points to a valid block of memory.
Remember, however, that this memory is not initialized in any way -- it contains garbage.
Let's start by clearing it. */
memset(data, 0, sizeof(int)*datacount);
/* now our array contains all zeroes. */
data[0] = 1;
data[2] = 15;
data[49] = 66; /* the last element in our array, since we start counting from 0 */
/* Loop through the array, printing out the values (mostly zeroes, but even so) */
for(int i = 0; i < datacount; ++i) {
printf("Element %d: %d\n", i, data[i]);
}
}
That's it. What follows is a more involved explanation of why this works :)
I don't know how well you know C pointers, but array access in C (like array[2]) is actually a shorthand for accessing memory via a pointer. To access the memory pointed to by data, you write *data. This is known as dereferencing the pointer. Since data is of type int *, then *data is of type int. Now to an important piece of information: (data + 2) means "add the byte size of 2 ints to the adress pointed to by data".
An array in C is just a sequence of values in adjacent memory. array[1] is just next to array[0]. So when we allocate a big block of memory and want to use it as an array, we need an easy way of getting the direct adress to every element inside. Luckily, C lets us use the array notation on pointers as well. data[0] means the same thing as *(data+0), namely "access the memory pointed to by data". data[2] means *(data+2), and accesses the third int in the memory block.
The way it's often done is as follows:
allocate an array of some initial (fairly small) size;
read into this array, keeping track of how many elements you've read;
once the array is full, reallocate it, doubling the size and preserving (i.e. copying) the contents;
repeat until done.
I find that this pattern comes up pretty frequently.
What's interesting about this method is that it allows one to insert N elements into an empty array one-by-one in amortized O(N) time without knowing N in advance.
Modern C, aka C99, has variable length arrays, VLA. Unfortunately, not all compilers support this but if yours does this would be an alternative.
Try to implement dynamic data structure such as a linked list
Here's a sample program that reads stdin into a memory buffer that grows as needed. It's simple enough that it should give some insight in how you might handle this kind of thing. One thing that's would probably be done differently in a real program is how must the array grows in each allocation - I kept it small here to help keep things simpler if you wanted to step through in a debugger. A real program would probably use a much larger allocation increment (often, the allocation size is doubled, but if you're going to do that you should probably 'cap' the increment at some reasonable size - it might not make sense to double the allocation when you get into the hundreds of megabytes).
Also, I used indexed access to the buffer here as an example, but in a real program I probably wouldn't do that.
#include <stdlib.h>
#include <stdio.h>
void fatal_error(void);
int main( int argc, char** argv)
{
int buf_size = 0;
int buf_used = 0;
char* buf = NULL;
char* tmp = NULL;
char c;
int i = 0;
while ((c = getchar()) != EOF) {
if (buf_used == buf_size) {
//need more space in the array
buf_size += 20;
tmp = realloc(buf, buf_size); // get a new larger array
if (!tmp) fatal_error();
buf = tmp;
}
buf[buf_used] = c; // pointer can be indexed like an array
++buf_used;
}
puts("\n\n*** Dump of stdin ***\n");
for (i = 0; i < buf_used; ++i) {
putchar(buf[i]);
}
free(buf);
return 0;
}
void fatal_error(void)
{
fputs("fatal error - out of memory\n", stderr);
exit(1);
}
This example combined with examples in other answers should give you an idea of how this kind of thing is handled at a low level.
One way I can imagine is to use a linked list to implement such a scenario, if you need all the numbers entered before the user enters something which indicates the loop termination. (posting as the first option, because have never done this for user input, it just seemed to be interesting. Wasteful but artistic)
Another way is to do buffered input. Allocate a buffer, fill it, re-allocate, if the loop continues (not elegant, but the most rational for the given use-case).
I don't consider the described to be elegant though. Probably, I would change the use-case (the most rational).