How to Store dynamic string in a struct ** containing char * pointer












2















Im currently working on a problem to store data from an input file into a struct of the following format:



typedef struct school_{
char *name;
char *state;
}School;


Im reading from an input file of the format :



name1, state1
name2, state2


And I would like to store the data dynamically for each school in a struct via pointers as the length of the name is unknown. k is the number of lines in the file.
So far this is what I have:



void input_schools(FILE *IN, School **Sch, int k) { 
int i, j;
char ch;

for (i=0; i<k; i++)
{ fscanf(IN, "%c", &ch);
Sch[i].name = (char *)malloc(sizeof (char));

j = 0;
Sch[i].name[j] = ch;

while(ch != '-') {
fscanf(IN, "%c", &ch);
j++;
Sch[i].name = (char *) realloc(Sch[i].name, sizeof(char)*(j+1));
Sch[i].name[j] = ch;
}

}
Sch[i].name[j-1] = '';


However I am receiving a seg fault which I'm assuming is from the way I'm trying to store "ch" when writing "Sch[i].name[j]" I have also tried Sch[i]->name[j] and been unsuccessful. I would appreciate any help in knowing the correct way to write the address to store the data?



I call the function using :
input_schools(school_info,TOP100,school_size);
where school info is the input file
School *TOP100[school_size];
is top100
and school_size is the number of lines in the file










share|improve this question




















  • 1





    School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

    – Johnny Mopp
    Nov 13 '18 at 19:40






  • 4





    Also, c-strings need to be terminated with which you neglect to do.

    – Johnny Mopp
    Nov 13 '18 at 19:43






  • 1





    Try and give your variables meaningful names, especially as arguments. What is k?

    – tadman
    Nov 13 '18 at 19:43






  • 2





    Hint: strdup instead of manually copying strings.

    – tadman
    Nov 13 '18 at 19:44











  • yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

    – Aravind Voggu
    Nov 14 '18 at 4:37


















2















Im currently working on a problem to store data from an input file into a struct of the following format:



typedef struct school_{
char *name;
char *state;
}School;


Im reading from an input file of the format :



name1, state1
name2, state2


And I would like to store the data dynamically for each school in a struct via pointers as the length of the name is unknown. k is the number of lines in the file.
So far this is what I have:



void input_schools(FILE *IN, School **Sch, int k) { 
int i, j;
char ch;

for (i=0; i<k; i++)
{ fscanf(IN, "%c", &ch);
Sch[i].name = (char *)malloc(sizeof (char));

j = 0;
Sch[i].name[j] = ch;

while(ch != '-') {
fscanf(IN, "%c", &ch);
j++;
Sch[i].name = (char *) realloc(Sch[i].name, sizeof(char)*(j+1));
Sch[i].name[j] = ch;
}

}
Sch[i].name[j-1] = '';


However I am receiving a seg fault which I'm assuming is from the way I'm trying to store "ch" when writing "Sch[i].name[j]" I have also tried Sch[i]->name[j] and been unsuccessful. I would appreciate any help in knowing the correct way to write the address to store the data?



I call the function using :
input_schools(school_info,TOP100,school_size);
where school info is the input file
School *TOP100[school_size];
is top100
and school_size is the number of lines in the file










share|improve this question




















  • 1





    School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

    – Johnny Mopp
    Nov 13 '18 at 19:40






  • 4





    Also, c-strings need to be terminated with which you neglect to do.

    – Johnny Mopp
    Nov 13 '18 at 19:43






  • 1





    Try and give your variables meaningful names, especially as arguments. What is k?

    – tadman
    Nov 13 '18 at 19:43






  • 2





    Hint: strdup instead of manually copying strings.

    – tadman
    Nov 13 '18 at 19:44











  • yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

    – Aravind Voggu
    Nov 14 '18 at 4:37
















2












2








2








Im currently working on a problem to store data from an input file into a struct of the following format:



typedef struct school_{
char *name;
char *state;
}School;


Im reading from an input file of the format :



name1, state1
name2, state2


And I would like to store the data dynamically for each school in a struct via pointers as the length of the name is unknown. k is the number of lines in the file.
So far this is what I have:



void input_schools(FILE *IN, School **Sch, int k) { 
int i, j;
char ch;

for (i=0; i<k; i++)
{ fscanf(IN, "%c", &ch);
Sch[i].name = (char *)malloc(sizeof (char));

j = 0;
Sch[i].name[j] = ch;

while(ch != '-') {
fscanf(IN, "%c", &ch);
j++;
Sch[i].name = (char *) realloc(Sch[i].name, sizeof(char)*(j+1));
Sch[i].name[j] = ch;
}

}
Sch[i].name[j-1] = '';


However I am receiving a seg fault which I'm assuming is from the way I'm trying to store "ch" when writing "Sch[i].name[j]" I have also tried Sch[i]->name[j] and been unsuccessful. I would appreciate any help in knowing the correct way to write the address to store the data?



I call the function using :
input_schools(school_info,TOP100,school_size);
where school info is the input file
School *TOP100[school_size];
is top100
and school_size is the number of lines in the file










share|improve this question
















Im currently working on a problem to store data from an input file into a struct of the following format:



typedef struct school_{
char *name;
char *state;
}School;


Im reading from an input file of the format :



name1, state1
name2, state2


And I would like to store the data dynamically for each school in a struct via pointers as the length of the name is unknown. k is the number of lines in the file.
So far this is what I have:



void input_schools(FILE *IN, School **Sch, int k) { 
int i, j;
char ch;

for (i=0; i<k; i++)
{ fscanf(IN, "%c", &ch);
Sch[i].name = (char *)malloc(sizeof (char));

j = 0;
Sch[i].name[j] = ch;

while(ch != '-') {
fscanf(IN, "%c", &ch);
j++;
Sch[i].name = (char *) realloc(Sch[i].name, sizeof(char)*(j+1));
Sch[i].name[j] = ch;
}

}
Sch[i].name[j-1] = '';


However I am receiving a seg fault which I'm assuming is from the way I'm trying to store "ch" when writing "Sch[i].name[j]" I have also tried Sch[i]->name[j] and been unsuccessful. I would appreciate any help in knowing the correct way to write the address to store the data?



I call the function using :
input_schools(school_info,TOP100,school_size);
where school info is the input file
School *TOP100[school_size];
is top100
and school_size is the number of lines in the file







c pointers struct






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 13 '18 at 19:49







codingstruggles

















asked Nov 13 '18 at 19:33









codingstrugglescodingstruggles

192




192








  • 1





    School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

    – Johnny Mopp
    Nov 13 '18 at 19:40






  • 4





    Also, c-strings need to be terminated with which you neglect to do.

    – Johnny Mopp
    Nov 13 '18 at 19:43






  • 1





    Try and give your variables meaningful names, especially as arguments. What is k?

    – tadman
    Nov 13 '18 at 19:43






  • 2





    Hint: strdup instead of manually copying strings.

    – tadman
    Nov 13 '18 at 19:44











  • yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

    – Aravind Voggu
    Nov 14 '18 at 4:37
















  • 1





    School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

    – Johnny Mopp
    Nov 13 '18 at 19:40






  • 4





    Also, c-strings need to be terminated with which you neglect to do.

    – Johnny Mopp
    Nov 13 '18 at 19:43






  • 1





    Try and give your variables meaningful names, especially as arguments. What is k?

    – tadman
    Nov 13 '18 at 19:43






  • 2





    Hint: strdup instead of manually copying strings.

    – tadman
    Nov 13 '18 at 19:44











  • yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

    – Aravind Voggu
    Nov 14 '18 at 4:37










1




1





School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

– Johnny Mopp
Nov 13 '18 at 19:40





School **Sch so Sch[i] is a pointer - Sch[i].name should produce a compiler error. Show how you call the function.

– Johnny Mopp
Nov 13 '18 at 19:40




4




4





Also, c-strings need to be terminated with which you neglect to do.

– Johnny Mopp
Nov 13 '18 at 19:43





Also, c-strings need to be terminated with which you neglect to do.

– Johnny Mopp
Nov 13 '18 at 19:43




1




1





Try and give your variables meaningful names, especially as arguments. What is k?

– tadman
Nov 13 '18 at 19:43





Try and give your variables meaningful names, especially as arguments. What is k?

– tadman
Nov 13 '18 at 19:43




2




2





Hint: strdup instead of manually copying strings.

– tadman
Nov 13 '18 at 19:44





Hint: strdup instead of manually copying strings.

– tadman
Nov 13 '18 at 19:44













yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

– Aravind Voggu
Nov 14 '18 at 4:37







yap. try better names, and use a better indentation and formatting. Probably install a linter, it checks for formatting & compilation errors as you type. Also, there are some nice naming conventions out there. for example, instead of k, I would write a_number_of_lines. Thea_ tells me that the variable is a function argument, and the remaining part tells me what the variable has. Also, unless you need, declare the variables in the loop. for(int i = 0; i < a_numer_of_lines; i++)

– Aravind Voggu
Nov 14 '18 at 4:37














2 Answers
2






active

oldest

votes


















1














Your file is very similar in shape to a csv. See if you can use any csv parsing libraries or code.



Instead of checking every char, read a whole line into a buffer and use strtok. strtok is a function used to split a string by a delimiter. a ',' in your case.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}

int main()
{
FILE* stream = fopen("in.md", "r");

char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);

printf("Name is %sn", getfield(tmp1, 1));
printf("State is %sn", getfield(tmp2, 2));
// NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
// Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
free(tmp1);
free(tmp2);
}
}





share|improve this answer
























  • Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

    – codingstruggles
    Nov 13 '18 at 21:13






  • 1





    There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

    – Aravind Voggu
    Nov 14 '18 at 4:31





















1














You could use something like this to read one School entry from the FILE* you supply:



bool School_read(School* s, FILE* in) {

int scan = fscanf(in, " %m[^,n], %m[^n]", &s->name, &s->state);

// the fscanf format string:
// <space> = skip leading whitespaces (like a newline from the line before)
// %m[^,n] = read a string until, but not including, "," or "n" m = allocate space for it
// , = expect a comma and discard it
// %m[^n] = read a string until, but not including, "n" and allocate space for it

// just a debug print
fprintf(stderr, " -- got %d hits, >%s< >%s<n", scan, s->name, s->state);

if(scan<2) {
// not a complete scan, failure
if(scan==1) {
// apparently, we got one match, free it
free(s->name);
s->name = NULL;
}
return false;
}
return true;
}


I don't know how widespread the support for the 'm' modifier that dynamically allocates memory for the strings is though. Recent gcc and clang compilers supports it anyway.



You could also make functions for creating and destroying a School:



School* School_create() {
School* s = malloc(sizeof(School));
if(s!=NULL) {
s->name = NULL;
s->state = NULL;
}
return s;
}

void School_destroy(School** sp) {
if(sp) {
School* s = *sp;
if(s) {
if(s->state) free(s->state);
if(s->name) free(s->name);
free(s);
}
*sp = NULL;
}
}


..and combine them all:



School* School_create_and_read(FILE* in) {
School* s = School_create();
if(s) {
if(School_read(s, in)==false) {
School_destroy(&s);
}
}
return s;
}


So in your function populating the array of schools:



void input_schools(FILE* IN, School** Sch, int k) { 
School* s;
while( (s=School_create_and_read(IN)) ) {
// s is a valid School pointer
// store it in your array
}
}





share|improve this answer





















  • 1





    Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

    – Aravind Voggu
    Nov 14 '18 at 4:34











  • Thank you! I very rarely use scanf myself but has its uses :-)

    – Ted Lyngmo
    Nov 14 '18 at 6:17











Your Answer






StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");

StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});

function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});


}
});














draft saved

draft discarded


















StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53288290%2fhow-to-store-dynamic-string-in-a-struct-containing-char-pointer%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes









1














Your file is very similar in shape to a csv. See if you can use any csv parsing libraries or code.



Instead of checking every char, read a whole line into a buffer and use strtok. strtok is a function used to split a string by a delimiter. a ',' in your case.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}

int main()
{
FILE* stream = fopen("in.md", "r");

char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);

printf("Name is %sn", getfield(tmp1, 1));
printf("State is %sn", getfield(tmp2, 2));
// NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
// Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
free(tmp1);
free(tmp2);
}
}





share|improve this answer
























  • Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

    – codingstruggles
    Nov 13 '18 at 21:13






  • 1





    There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

    – Aravind Voggu
    Nov 14 '18 at 4:31


















1














Your file is very similar in shape to a csv. See if you can use any csv parsing libraries or code.



Instead of checking every char, read a whole line into a buffer and use strtok. strtok is a function used to split a string by a delimiter. a ',' in your case.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}

int main()
{
FILE* stream = fopen("in.md", "r");

char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);

printf("Name is %sn", getfield(tmp1, 1));
printf("State is %sn", getfield(tmp2, 2));
// NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
// Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
free(tmp1);
free(tmp2);
}
}





share|improve this answer
























  • Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

    – codingstruggles
    Nov 13 '18 at 21:13






  • 1





    There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

    – Aravind Voggu
    Nov 14 '18 at 4:31
















1












1








1







Your file is very similar in shape to a csv. See if you can use any csv parsing libraries or code.



Instead of checking every char, read a whole line into a buffer and use strtok. strtok is a function used to split a string by a delimiter. a ',' in your case.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}

int main()
{
FILE* stream = fopen("in.md", "r");

char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);

printf("Name is %sn", getfield(tmp1, 1));
printf("State is %sn", getfield(tmp2, 2));
// NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
// Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
free(tmp1);
free(tmp2);
}
}





share|improve this answer













Your file is very similar in shape to a csv. See if you can use any csv parsing libraries or code.



Instead of checking every char, read a whole line into a buffer and use strtok. strtok is a function used to split a string by a delimiter. a ',' in your case.



#include <stdio.h>
#include <stdlib.h>
#include <string.h>

const char* getfield(char* line, int num)
{
const char* tok;
for (tok = strtok(line, ",");
tok && *tok;
tok = strtok(NULL, ",n"))
{
if (!--num)
return tok;
}
return NULL;
}

int main()
{
FILE* stream = fopen("in.md", "r");

char line[1024];
while (fgets(line, 1024, stream))
{
char* tmp1 = strdup(line);
char* tmp2 = strdup(line);

printf("Name is %sn", getfield(tmp1, 1));
printf("State is %sn", getfield(tmp2, 2));
// NOTE strtok changes the string. Hence two vars. You can try duplicating in the function instead.
// Note that I'm freeing the data. copying with strdup instead of directly assigning may be wise.
free(tmp1);
free(tmp2);
}
}






share|improve this answer












share|improve this answer



share|improve this answer










answered Nov 13 '18 at 19:58









Aravind VogguAravind Voggu

791413




791413













  • Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

    – codingstruggles
    Nov 13 '18 at 21:13






  • 1





    There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

    – Aravind Voggu
    Nov 14 '18 at 4:31





















  • Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

    – codingstruggles
    Nov 13 '18 at 21:13






  • 1





    There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

    – Aravind Voggu
    Nov 14 '18 at 4:31



















Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

– codingstruggles
Nov 13 '18 at 21:13





Sadly I have to use the format of the struct above. if I used strtok to get each string is there a way to store them in the struct formatted as shown above?

– codingstruggles
Nov 13 '18 at 21:13




1




1





There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

– Aravind Voggu
Nov 14 '18 at 4:31







There are, but I advise you go with the answer by Ted Lyngmo. It's much easier to understand and implement. You can use just the fscanf part, you don't need to use the other part, but it's generally good.

– Aravind Voggu
Nov 14 '18 at 4:31















1














You could use something like this to read one School entry from the FILE* you supply:



bool School_read(School* s, FILE* in) {

int scan = fscanf(in, " %m[^,n], %m[^n]", &s->name, &s->state);

// the fscanf format string:
// <space> = skip leading whitespaces (like a newline from the line before)
// %m[^,n] = read a string until, but not including, "," or "n" m = allocate space for it
// , = expect a comma and discard it
// %m[^n] = read a string until, but not including, "n" and allocate space for it

// just a debug print
fprintf(stderr, " -- got %d hits, >%s< >%s<n", scan, s->name, s->state);

if(scan<2) {
// not a complete scan, failure
if(scan==1) {
// apparently, we got one match, free it
free(s->name);
s->name = NULL;
}
return false;
}
return true;
}


I don't know how widespread the support for the 'm' modifier that dynamically allocates memory for the strings is though. Recent gcc and clang compilers supports it anyway.



You could also make functions for creating and destroying a School:



School* School_create() {
School* s = malloc(sizeof(School));
if(s!=NULL) {
s->name = NULL;
s->state = NULL;
}
return s;
}

void School_destroy(School** sp) {
if(sp) {
School* s = *sp;
if(s) {
if(s->state) free(s->state);
if(s->name) free(s->name);
free(s);
}
*sp = NULL;
}
}


..and combine them all:



School* School_create_and_read(FILE* in) {
School* s = School_create();
if(s) {
if(School_read(s, in)==false) {
School_destroy(&s);
}
}
return s;
}


So in your function populating the array of schools:



void input_schools(FILE* IN, School** Sch, int k) { 
School* s;
while( (s=School_create_and_read(IN)) ) {
// s is a valid School pointer
// store it in your array
}
}





share|improve this answer





















  • 1





    Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

    – Aravind Voggu
    Nov 14 '18 at 4:34











  • Thank you! I very rarely use scanf myself but has its uses :-)

    – Ted Lyngmo
    Nov 14 '18 at 6:17
















1














You could use something like this to read one School entry from the FILE* you supply:



bool School_read(School* s, FILE* in) {

int scan = fscanf(in, " %m[^,n], %m[^n]", &s->name, &s->state);

// the fscanf format string:
// <space> = skip leading whitespaces (like a newline from the line before)
// %m[^,n] = read a string until, but not including, "," or "n" m = allocate space for it
// , = expect a comma and discard it
// %m[^n] = read a string until, but not including, "n" and allocate space for it

// just a debug print
fprintf(stderr, " -- got %d hits, >%s< >%s<n", scan, s->name, s->state);

if(scan<2) {
// not a complete scan, failure
if(scan==1) {
// apparently, we got one match, free it
free(s->name);
s->name = NULL;
}
return false;
}
return true;
}


I don't know how widespread the support for the 'm' modifier that dynamically allocates memory for the strings is though. Recent gcc and clang compilers supports it anyway.



You could also make functions for creating and destroying a School:



School* School_create() {
School* s = malloc(sizeof(School));
if(s!=NULL) {
s->name = NULL;
s->state = NULL;
}
return s;
}

void School_destroy(School** sp) {
if(sp) {
School* s = *sp;
if(s) {
if(s->state) free(s->state);
if(s->name) free(s->name);
free(s);
}
*sp = NULL;
}
}


..and combine them all:



School* School_create_and_read(FILE* in) {
School* s = School_create();
if(s) {
if(School_read(s, in)==false) {
School_destroy(&s);
}
}
return s;
}


So in your function populating the array of schools:



void input_schools(FILE* IN, School** Sch, int k) { 
School* s;
while( (s=School_create_and_read(IN)) ) {
// s is a valid School pointer
// store it in your array
}
}





share|improve this answer





















  • 1





    Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

    – Aravind Voggu
    Nov 14 '18 at 4:34











  • Thank you! I very rarely use scanf myself but has its uses :-)

    – Ted Lyngmo
    Nov 14 '18 at 6:17














1












1








1







You could use something like this to read one School entry from the FILE* you supply:



bool School_read(School* s, FILE* in) {

int scan = fscanf(in, " %m[^,n], %m[^n]", &s->name, &s->state);

// the fscanf format string:
// <space> = skip leading whitespaces (like a newline from the line before)
// %m[^,n] = read a string until, but not including, "," or "n" m = allocate space for it
// , = expect a comma and discard it
// %m[^n] = read a string until, but not including, "n" and allocate space for it

// just a debug print
fprintf(stderr, " -- got %d hits, >%s< >%s<n", scan, s->name, s->state);

if(scan<2) {
// not a complete scan, failure
if(scan==1) {
// apparently, we got one match, free it
free(s->name);
s->name = NULL;
}
return false;
}
return true;
}


I don't know how widespread the support for the 'm' modifier that dynamically allocates memory for the strings is though. Recent gcc and clang compilers supports it anyway.



You could also make functions for creating and destroying a School:



School* School_create() {
School* s = malloc(sizeof(School));
if(s!=NULL) {
s->name = NULL;
s->state = NULL;
}
return s;
}

void School_destroy(School** sp) {
if(sp) {
School* s = *sp;
if(s) {
if(s->state) free(s->state);
if(s->name) free(s->name);
free(s);
}
*sp = NULL;
}
}


..and combine them all:



School* School_create_and_read(FILE* in) {
School* s = School_create();
if(s) {
if(School_read(s, in)==false) {
School_destroy(&s);
}
}
return s;
}


So in your function populating the array of schools:



void input_schools(FILE* IN, School** Sch, int k) { 
School* s;
while( (s=School_create_and_read(IN)) ) {
// s is a valid School pointer
// store it in your array
}
}





share|improve this answer















You could use something like this to read one School entry from the FILE* you supply:



bool School_read(School* s, FILE* in) {

int scan = fscanf(in, " %m[^,n], %m[^n]", &s->name, &s->state);

// the fscanf format string:
// <space> = skip leading whitespaces (like a newline from the line before)
// %m[^,n] = read a string until, but not including, "," or "n" m = allocate space for it
// , = expect a comma and discard it
// %m[^n] = read a string until, but not including, "n" and allocate space for it

// just a debug print
fprintf(stderr, " -- got %d hits, >%s< >%s<n", scan, s->name, s->state);

if(scan<2) {
// not a complete scan, failure
if(scan==1) {
// apparently, we got one match, free it
free(s->name);
s->name = NULL;
}
return false;
}
return true;
}


I don't know how widespread the support for the 'm' modifier that dynamically allocates memory for the strings is though. Recent gcc and clang compilers supports it anyway.



You could also make functions for creating and destroying a School:



School* School_create() {
School* s = malloc(sizeof(School));
if(s!=NULL) {
s->name = NULL;
s->state = NULL;
}
return s;
}

void School_destroy(School** sp) {
if(sp) {
School* s = *sp;
if(s) {
if(s->state) free(s->state);
if(s->name) free(s->name);
free(s);
}
*sp = NULL;
}
}


..and combine them all:



School* School_create_and_read(FILE* in) {
School* s = School_create();
if(s) {
if(School_read(s, in)==false) {
School_destroy(&s);
}
}
return s;
}


So in your function populating the array of schools:



void input_schools(FILE* IN, School** Sch, int k) { 
School* s;
while( (s=School_create_and_read(IN)) ) {
// s is a valid School pointer
// store it in your array
}
}






share|improve this answer














share|improve this answer



share|improve this answer








edited Nov 13 '18 at 23:30

























answered Nov 13 '18 at 23:10









Ted LyngmoTed Lyngmo

2,5211317




2,5211317








  • 1





    Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

    – Aravind Voggu
    Nov 14 '18 at 4:34











  • Thank you! I very rarely use scanf myself but has its uses :-)

    – Ted Lyngmo
    Nov 14 '18 at 6:17














  • 1





    Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

    – Aravind Voggu
    Nov 14 '18 at 4:34











  • Thank you! I very rarely use scanf myself but has its uses :-)

    – Ted Lyngmo
    Nov 14 '18 at 6:17








1




1





Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

– Aravind Voggu
Nov 14 '18 at 4:34





Ah, this is much nice. Thanks showing us! I'm gonna use this better way the next time.

– Aravind Voggu
Nov 14 '18 at 4:34













Thank you! I very rarely use scanf myself but has its uses :-)

– Ted Lyngmo
Nov 14 '18 at 6:17





Thank you! I very rarely use scanf myself but has its uses :-)

– Ted Lyngmo
Nov 14 '18 at 6:17


















draft saved

draft discarded




















































Thanks for contributing an answer to Stack Overflow!


  • Please be sure to answer the question. Provide details and share your research!

But avoid



  • Asking for help, clarification, or responding to other answers.

  • Making statements based on opinion; back them up with references or personal experience.


To learn more, see our tips on writing great answers.




draft saved


draft discarded














StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53288290%2fhow-to-store-dynamic-string-in-a-struct-containing-char-pointer%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown





















































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown

































Required, but never shown














Required, but never shown












Required, but never shown







Required, but never shown







Popular posts from this blog

Florida Star v. B. J. F.

Danny Elfman

Retrieve a Users Dashboard in Tumblr with R and TumblR. Oauth Issues