Hi I'm trying to read variables from a file into a int array so I can store them in a Struct array. The numbers get stored correctly into the curLinks array but when I try pass the curLinks array into curNodes.nodes, it doesn't work and when i try print it out (to test) it prints rubbish numbers. Any help would be great.
struct nodeInfo* getTopology(FILE *file){
int totLinks=0;
fscanf(file, "%d", &nodeCount);
struct nodeInfo netTopo[nodeCount];
// How many links does node have
for (int id=0; id<nodeCount; id++){
struct nodeInfo curNode;
curNode.n=id;
fscanf(file, "%d", &totLinks);
int curLinks[totLinks];
for(int i=0; i<totLinks; i++){
int digit=0;
fscanf(file, "%d", &digit);
curLinks[i] = digit;
}
curNode.nodes = curLinks;
netTopo[id] = curNode;
}
for (int id=0; id<nodeCount; id++){
for (int j=0; j<3; j++){
printf("%d ", netTopo[id].nodes[j]);
}
}
return netTopo;
}
You define curLinks multiple time in the first for-loop
int curLinks[totLinks];
And after you fill that you try to set that in your nodeinfo however as soon as the next iteration in the for-loop is entered and curLinks is filled again, the memory of your previous curLinks is out of scope and the memory where you think your read in values should reside can be actually filled with anything - Undefined Behaviour
If you tell me the way you define your structs nodeInfo I might be able to show you how to do it properly.
e.g.: Assuming you define
struct nodeinfo {
int *nodes;
};
Then
struct nodeInfo* getTopology(FILE *file)
{
int id, digit=0, totLinks=0;
fscanf(file, "%d", &nodeCount);
struct nodeInfo netTopo[nodeCount];
// How many links does node have
for (id=0; id<nodeCount; id++){
fscanf(file, "%d", &totLinks);
netTopo[id].nodes = malloc(totLinks * sizeof(int));
if (netTopo[id].nodes==NULL)
printf("Error allocating memory\n");
for(i=0; i<totLinks; i++) {
fscanf(file, "%d", &digit);
netTopo[id].nodes[i] = digit;
}
}
// Free the allocate memory
for (id=0; id<nodeCount; id++){
free(netTopo[id].nodes);
}
return netTopo;
}
I think you should use pointers and "malloc" to allocate memory from the heap in this case.
Related
For a class assignment I have an array that I need to define in main() but allocate memory and load the data in a sperate function load(). Right now autos[] doesn't get populated with the data from the file. Any help is appreciated.
The struct has 4 fields: name, floatNum, intNum, color, that the data needs to be written to. size and autos[] are both defined in main and size refers to the number of elements in autos[].
Load function
void load(int size, struct data autos[]) {
autos = malloc(size * sizeof(struct data));
FILE *data;
data = fopen("./hw3.data", "r");
int i;
for (i = 0; i < size; i++) {
fscanf(data, "%s %f %d %s", autos[i].name, &autos[i].floatNum, &autos[i].intNum, autos[i].color);
}
}
I figured it out. Thank you Craig and Johnathan for giving me some pointers. It takes the size of the array needed (from a different function) and creates one and scans through the data file putting data into each element.
struct data* load(int size){
struct data* autos = malloc(size * sizeof(struct data));
FILE* data;
data = fopen("./hw3.data", "r");
int i = 0;
for (i = 0; i < size; i++) {
fscanf(data, "%20s %f %d %20s", autos[i].name, &autos[i].floatNum, &autos[i].intNum, autos[i].color);
}
fclose(data);
return autos;
}
I am writing a search function in C which uses pointers and structs. Search is possible by name using an array called contatcs with ten entries. The array has already been initialized and populated and works as intended.
I have tried to fix the problem by restructuring my code, but it only made matters worse. Maybe there is some flaw in the design logic that I cannot find.
typedef struct
{
char streetname[150];
char city[50];
int zipcode;
}address;
typedef struct
{
char name[50];
int age;
address homeaddress;
}person;
int search (char* name, person *contacts, int size);
[...] // initialization and population of array omitted
int search (char *name, person *contacts, int size)
{
int i;
printf("Input name: ");
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
{
printf("Name: %s;", contacts[i].name);
printf(" Age: %d;", contacts[i].age);
printf(" Adress: %s, ", contacts[i].homeaddress.streetname);
printf("%s, ", contacts[i].homeaddress.city);
printf("%d\n", contacts[i].homeaddress.zipcode);
}
}
return 0;
}
I am just trying to call the function. But every time I try to do so, it just doesn't work. I know this question is rather basic, but I can't seem to find the solution.
char userin = scanf("%s", name);
for(i = 0; i < size; i++)
{
if (strcmp(contacts[i].name, &userin) == 0)
You can not use strcmp with a char, userin must be a NUL terminated array of chars
And as pointed out by #JohnBollinger in comments, it seems you want to compare the name, not the result of scanf
This is just part of a bigger code, but it's full of errors so I try to fix them one by one. When I try to use malloc on my pointer vector the line returns this error
main.c|14|error: expected '{' before '*' token
Any resolutions?
struct students {
int group;
char name[20];
int grade;
};
int main()
{
struct students *ptr[100];
int num, i, max=0;
scanf("%d", &num);
ptr = (struct*) malloc(num * sizeof(struct));
if(ptr == NULL)
{
printf("error");
exit(0);
}
}
Struct is reserved keyword for declaring/defining structures in C, it isn't variable, nor something you cant get size of it. You have declared struct students (according to your code, i think it should be student instead of students), now you have to define a variable and allocate space for 100 structs via a double pointer, the code should be something like this
struct student {
int group;
char name[20];
int grade;
};
int main()
{
struct student ** ptr;
int num, i, max=0;
scanf("%d", &num);
ptr = malloc(num * sizeof(struct student));
if(ptr == NULL)
{
printf("error");
exit(0);
}
}
Now you can access individual students with array subscript
ptr[0]->grade = 20; // putting 20 in grade of first student
Also, there is no need for casting malloc result in C
While using malloc for a 1D array, you should allocate a pointer, not an array of pointers as you have done.
While allocating you are using sizeof(struct). The type here is struct students and you need sizeof(struct students)
Do not cast the result of malloc. See Do I cast the result of malloc?
The final code is
struct students *ptr;
ptr = malloc (num * sizeof(struct students));
You have an array of pointers to structure. You should allocate memory for them separately.
for(int i=0; i<100 && i<num; i++)
{
ptr[i] = malloc(sizeof(struct students));
if(0 == ptr[i])
{
/* Handle this case. */
}
}
/* Your code. */
/* At the end free the memory. */
for(int i=0; i<100; i++)
{
if(0 != ptr[i])
{
free(ptr[i]);
ptr[i] = 0;
}
}
But I think you just wanted to allocate an array of struct students. In that case you just need one pointer.
struct students *ptr = 0;
/* You allocate memory and store it in that pointer. */
ptr = malloc(num * sizeof(struct students));
if(0 == ptr)
{
/* Handle this case. */
}
You can access ith element of the array like ptr[i]. But add necessary checks and make sure i < num.
You need to free the allocated memory whenever you are done using the array.
if(0 != ptr)
{
free(ptr);
ptr = 0;
}
im implementing a program that reads student id and names from stdin or file, and make them ordered by name and ordered by number. The funny thing is i cant understand why but scanf doesnt work. Here is my code while using scanf:
int n=0;
while(n<SIZE){
scanf("%d %s\n",&std_array[n].id, std_array[n].name);
n++;
}
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
and here is my struct:
struct Student {
char *name;
int id;};
when i read from file and print them the out put is:
> 12586546 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null) 0 (null)
> 0 (null) 0 (null) 0 (null)
although file have some numbers and names like 21456764 john 45797654 fred etc. , its doesn't read successfully.
NOTE: i know the way we fix struct like you guys suggested but i must learn the way to do this with char pointer...
When doing this:
struct Student {
char *name; // This does not allocate memory
int id;};
Here, name is a pointer, with no allocated memory, behaving like an uninitialized literal string.
Trying to modify it creates undefined behaviour.
Replace with:
struct Student {
char name[50];
int id;};
or
struct Student {
char name[] = "Initial value gives maximum length. Do not write more!";
int id;};
This allocates memory to the pointer as needed. An intermediate variable is used to hold the string then only enough memory plus 1 for the terminating '\0' is allocated in the struct.
int n=0;
char name[100];//longest possible name
while(n<SIZE && ( scanf("%d%99s",&std_array[n].id, name) == 2)) {// successfully scanned two items
std_array[n].name = malloc ( strlen ( name) + 1));
if ( std_array[n].name == NULL) {
printf ( "malloc failed\n");
// break or return or exit(1) as appropriate
}
strcpy ( std_array[n].name, name);
n++;
}
for(int i = 0; i < n; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
Eventually you will want to free the memory
for ( i = 0; i < n; i++) {
free ( std_array[i].name);
}
Point 1
Allocate memory to name before using it. Otherwise, if used uninitialized, it does not point to any valid memory to read from or write into. You can use malloc() to allocate memory. Also, once done, don't forget to free() it once you're done using the memory.
Point 2
Remove the \n from scanf().
This is the corrected code
struct Student
{
char name[20];
int id;
};
struct Student std_array[SIZE];
int n=0;
while(n<SIZE)
{
scanf("%d %s", &std_array[n].id, std_array[n].name);
n++;
}
n=0;
while(n<SIZE)
{
printf("%d %s\n", std_array[n].id, std_array[n].name);
n++;
}
Hope this helps...,
as user3121023 told to me, it worked. fixed code is following:
struct Student {
char *name;
int id;
};
struct Student std_array[SIZE];
int cmpfunc (const void * a, const void * b);
struct Student *order_by_number(struct Student *array);
int main(int argc, char **argv){
int n=0;
char name[100];
while(n<SIZE){
scanf("%d %s\n",&std_array[n].id, name);
std_array[n].name = malloc(strlen(name)+1);
strcpy(std_array[n].name ,name);
n++;
}
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
order_by_number(std_array);
for(int i=0; i<SIZE; i++)
printf("%d %s\n",std_array[i].id,std_array[i].name);
}
im done, ty guys for helping me. CASE CLOSED :)
I know I need to use free() in here somewhere, but I'm unsure where.
struct info{
char string1[30];
float float1;
int int1;
char string2[30];
};
struct info* build(){
FILE *data;
int i, lines;
lines=0;
data=fopen("hw3.data","r");
struct info info;
struct info *infoArr;
infoArr = (struct info*)calloc(lines,sizeof(struct info));
for(i=0; i<2; i++){ //change not to 2
fscanf(data, "%s %f %d %s", info.string1, &info.float1, &info.int1, info.string2);
strcpy(infoArr[i].string1, info.string1);
infoArr[i].float1 = info.float1;
infoArr[i].int1 = info.int1;
strcpy(infoArr[i].string2, info.string2);
}
fclose(data);
return infoArr;
}
void function1(){
int i; for(i=0; i<2; i++){
printf("%s %f %d %s\n", build()[i].string1, build()[i].float1, build()[i].int1, build()[i].string2);
}
}
I want to use it at the end of function1(), after the print statement, but will the context still be available there? I don't belief I can free(*infoArr) at the end of build() as I need to access that array elsewhere, which is the whole point of build(). build() is intended to be used in multiple functions. If I use free() at the end of function1(), do I use free(infoArr) or free(build()) or something else entirely?
Also, each of your arguments to printf() is working with a different structure, because you're calling build() repeatedly. You should call build() once before the loop, assign this to a variable, and then loop through the variable.
struct info* temp = build();
for (i = 0; i < 2; i++) {
printf("%s %f %d %s\n", temp[i].string1, temp[i].float1, temp[i].int1, temp[i].string2);
}
free(temp);
You have to save the pointer returned by build(), and free it after the loop. It would be better style though to allocate the memory in function 1 before the loop, have build take a pointer and fill in it's data through that.