• 0

[C] Loading a structure from a file, modify the structure, then save


Question

I have a local structure with several fields. I want to make this local structure be stored in a file. Everytime I load up the program it can either A: Create the file with the structure if it doesnt exist B: Load everything from the file into each structure's field. Then I work in the program modifying it, deleting it, etc etc. from the local structure then when I exit the program it has to save everything to the same file.

If someone needs code samples, Ill put them but please help me out as Im having problems opening/closing...

23 answers to this question

Recommended Posts

  • 0

I've actually tried this for some uni project, but I could never get it to work =/

If i still have a copy of the cource code somewhere, i'll post it here

---

You could post your code and I could try to get it to work, maybe it was different from mine

  • 0

I have

struct clients

{

int id;

char name[15];

char last[15];/

int number;

}c[num];

And I want to do the following:

I want to (this is seperte but related) control the information with a pointer.

And (this thread) insert id, name, last, number into the struct that at the begin and end of the program will load and save it from a clients.txt

And Im simply not sure how to do the second :) So if someone could help me out thanks.

OT: Is there any good and dedicated community with forums to programming, overall C?

  • 0
I have...

FILE *f=fopen(argv[1], "r");
list *l1; int i;
l1 = makelist(f);
fclose(f);

list *makelist(FILE *stream){
char letter;
int i = 0; int icount =0;
char word[30];
list *l1;
l1= NULL;
/*creates a new list and initialises it. While the character retrieved from//
the stream is not the end of the file,*/
while((letter=fgetc(stream))!=EOF){
/*initialises the character array to put the word on*/
for(icount=0; icount<30; icount++){
word[0] = '\0';
}
/*checks to see that the character is a letter*/
	if(((letter>64&&letter<91)||(letter>96&&letter<123)||letter==32)){
		if ((letter>64&&letter<91)||(letter>96&&letter<123)){
			while(letter!=EOF && (letter!=32) && (letter!='\0') && (letter!='\n')&& (letter!='.') && (letter!=',') && (letter!='\'')&&(letter!='"')&&(letter!=';')&&(letter!=':')&&(letter!=39)&&(letter!='!')&&(letter!='?')&&(letter!=39)&&(letter!=40)&&(letter!=41)&&(letter!=48)&&(letter!=49)&&(letter!=' ')&&(letter!='(')&&(letter!=')')){
				word[i] = letter;
				i++;
				letter=fgetc(stream);
		}
			/*adds an end marker on the end of the string*/
			word[i] = '\0';
			i = 0;
			/*makes the word uppercase*/
			for (i=0; i<strlen(word); i++){
				word[i] =toupper(word[i]);
			}
			i =0;
			/*places the word on the list*/
			l1 = insertlist(word, l1);

		}else{
			i= 0;
		}
	}	
}
/*returns the new list with the item added*/
return l1;
}

That's some code for reading to a list that I ripped from somtehing I did in my first year of uni :s.

As for writing... I did that somewhere too I'll look for a code fragment you could use.

Chris

[edit] Just read the if conditions; lol... what was going on there... I think there was an odd bug in it for a while, you can ignore most of them!!! [/edit]

  • 0

WOW :) You accually kind of help me out on another project!!!

I also have to write/read to graphs, lists, trees, and nodes. Thanks alot.

I understand all of the lines except why you use some of the variables and

while((letter=fgetc(stream))!=EOF){

What is fgetc exactly? (Something about a file and a character but...)

If you could help me out, or If i could add you to my Messenger if you dont mind, thank you very very VERY much :)

  • 0
I understand all of the lines except why you use some of the variables and

while((letter=fgetc(stream))!=EOF){

What is fgetc exactly? (Something about a file and a character but...)

I'm no expert with C but I'm pretty sure all that line does, is to look reading all characters from a stream until it encounters the EOF (End of File). fgetc just gets a character from a stream. More info here :)

  • 0
What exactly is a "stream"? I know its a noob question but...

You can think of a stream as a file. If you close the stream, you close the file. There are three special streams in C - stdin (standard input stream), stdout (standard output stream) and stderr (standard error output stream). Usually those are associated with the first three file handles:

stdin = file handle 0

stdout = file handle 1

stderr = file handle 2

  • 0

Chris's code didnt work :(

Let me explain again what IM trying to do

I have this (pseudocode):

stucture clients

name a string field

lastname a string field

age a integer field

find clients.txt and insert data from clients.txt into the clients stucture with name lastname and age

if clients.txt is not found create clients.txt and set all values as "0" in the clients structure

/* program */

/* end of program: */

collect data from strucuture clients and save all data in clients.txt

I hope that clears it up a bit :) All of this in C.

  • 0

Please someone....

I was playing around with fgets but I couldnt somehow get the function to read the file until the end of line (\o), insert into a field in the struct, then jump to the next line and insert into the next field in the struct.

  • 0

Sample C file:

#include <stdio.h>

struct client
{
  char name[15];
  char last[15];
  int age;
};

int main (void)
{
  struct client c; // a single client; make it an array for multiple clients, and remember to change the code accordingly
  FILE* client_file = fopen("clients.txt", "rt");

  /* file not found */
  if (!client_file)
	{
	  fputs("Warning: `clients.txt' was not found. Creating...", stderr);
	  client_file = fopen("clients.txt", "wt");
	  fputs("\t\t0", client_file); //assuming you are using a tab-delimited file for the fields; make sure to check the return value!!
	  fclose(client_file);
	  fputs("`clients.txt' created successfully", stderr);
	  return 1; //exit with a non-zero status (I made it positive because there wasn't an error)
	}

  /* file found */
  {
	char tmp = 0;
	for (unsigned int i = 0; (i < sizeof(c.name) - 1) || ((tmp != '\t') && (tmp != EOF)); ++i)
	  {
		tmp = fgetc(client_file);
		if ((tmp != '\t') && (tmp != EOF))
		  c.name[i] = tmp;
	  }
	c.name[sizeof(c.name) - 1] = 0;

	for (unsigned int i = 0; (i < sizeof(c.last) - 1) || ((tmp != '\t') && (tmp != EOF)); ++i)
	  {
		tmp = fgetc(client_file);
		if ((tmp != '\t') && (tmp != EOF))
		  c.last[i] = tmp;
	  }
	c.last[sizeof(c.last) - 1] = 0;

	while (((tmp = fgetc(client_file)) != '\n') && (tmp != EOF))
	  {
		c.age *= 10;
		c.age += tmp - 48;
	  }
  }

  fclose(client_file);

  return 0;
}

Sample `clients.txt' file:

Bob	Macquerel	82
George	Baeckermann	19
William	Corson		67

The sample C code would read the entry for "Bob Macquerel" and then close the file and exit, if that file existed, of course. It is untested, but it should work. Just remember to add proper error handling, and customize it to your needs.

Edit: Note that if the above sample `clients.txt' file has spaces between fields, they should be replaced by tabs. For example, "William<space><space><space>Corson<space><space>67" would become "William<tab>Corson<tab>67".

  • 0
Sample C file:

#include &lt;stdio.h&gt;

struct client
{
  char name[15];
  char last[15];
  int age;
};

int main (void)
{
  struct client c; // a single client; make it an array for multiple clients, and remember to change the code accordingly
  FILE* client_file = fopen("clients.txt", "rt");

  /* file not found */
  if (!client_file)
	{
	  fputs("Warning: `clients.txt' was not found. Creating...", stderr);
	  client_file = fopen("clients.txt", "wt");
	  fputs("\t\t0", client_file); //assuming you are using a tab-delimited file for the fields; make sure to check the return value!!
	  fclose(client_file);
	  fputs("`clients.txt' created successfully", stderr);
	  return 1; //exit with a non-zero status (I made it positive because there wasn't an error)
	}

  /* file found */
  {
	char tmp = 0;
	for (unsigned int i = 0; (i &lt; sizeof(c.name) - 1) || ((tmp != '\t') &amp;&amp; (tmp != EOF)); ++i)
	  {
		tmp = fgetc(client_file);
		if ((tmp != '\t') &amp;&amp; (tmp != EOF))
		  c.name[i] = tmp;
	  }
	c.name[sizeof(c.name) - 1] = 0;

	for (unsigned int i = 0; (i &lt; sizeof(c.last) - 1) || ((tmp != '\t') &amp;&amp; (tmp != EOF)); ++i)
	  {
		tmp = fgetc(client_file);
		if ((tmp != '\t') &amp;&amp; (tmp != EOF))
		  c.last[i] = tmp;
	  }
	c.last[sizeof(c.last) - 1] = 0;

	while (((tmp = fgetc(client_file)) != '\n') &amp;&amp; (tmp != EOF))
	  {
		c.age *= 10;
		c.age += tmp - 48;
	  }
  }

  fclose(client_file);

  return 0;
}

Sample `clients.txt' file:

Bob	Macquerel	82
George	Baeckermann	19
William	Corson		67

The sample C code would read the entry for "Bob Macquerel" and then close the file and exit, if that file existed, of course. It is untested, but it should work. Just remember to add proper error handling, and customize it to your needs.

Edit: Note that if the above sample `clients.txt' file has spaces between fields, they should be replaced by tabs. For example, "William<space><space><space>Corson<space><space>67" would become "William<tab>Corson<tab>67".

Thank you very much :) Ill test it out and post ASAP.

  • 0

Here is an example of reading a file and storing the contents in an array of structures. Then printing out the array. It should not be too difficult to adapt this to write to a file.

The expected file format is:

FirstName LastName Age
Bob Smith 32
Frank Furter 28

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define MAX_CLIENTS 100

typedef struct client
{
  char nfirst[20];
  char nlast[20];
  int age;
}client;

int main(void)
{
	client c[MAX_CLIENTS];
	char line[BUFSIZ];
	char* filename = "clients.txt";
	int read_cnt = 0, l_cnt = 1;
	int i = 0;

	FILE* fp = fopen(filename, "r");

	if(!fp) {
		printf("Failed to open file: %s\n", filename);
		exit(1);
	}

	/* read the file */
	while(fgets(line, sizeof(line), fp) &amp;&amp; read_cnt &lt; MAX_CLIENTS) {
		/* parse the line and save into client array */
		if(sscanf(line, "%19s %19s %d", c[read_cnt].nfirst, c[read_cnt].nlast, &amp;c[read_cnt].age) != 3) {
			printf("--line(%d) Bad line format--\n", l_cnt);
		}else{
			read_cnt++;
		}
		l_cnt++;
	}

	fclose(fp);

	/* print the list of clients to the screen */
	for(i = 0; i &lt; read_cnt; i++) {
		printf("%s %s %d\n", c[i].nfirst, c[i].nlast, c[i].age);
	}

	return 0;
}

  • 0
Here is an example of reading a file and storing the contents in an array of structures. Then printing out the array. It should not be too difficult to adapt this to write to a file.

The expected file format is:

FirstName LastName Age
Bob Smith 32
Frank Furter 28

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;

#define MAX_CLIENTS 100

typedef struct client
{
  char nfirst[20];
  char nlast[20];
  int age;
}client;

int main(void)
{
	client c[MAX_CLIENTS];
	char line[BUFSIZ];
	char* filename = "clients.txt";
	int read_cnt = 0, l_cnt = 1;
	int i = 0;

	FILE* fp = fopen(filename, "r");

	if(!fp) {
		printf("Failed to open file: %s\n", filename);
		exit(1);
	}

	/* read the file */
	while(fgets(line, sizeof(line), fp) &amp;&amp; read_cnt &lt; MAX_CLIENTS) {
		/* parse the line and save into client array */
		if(sscanf(line, "%19s %19s %d", c[read_cnt].nfirst, c[read_cnt].nlast, &amp;c[read_cnt].age) != 3) {
			printf("--line(%d) Bad line format--\n", l_cnt);
		}else{
			read_cnt++;
		}
		l_cnt++;
	}

	fclose(fp);

	/* print the list of clients to the screen */
	for(i = 0; i &lt; read_cnt; i++) {
		printf("%s %s %d\n", c[i].nfirst, c[i].nlast, c[i].age);
	}

	return 0;
}

Great code; I understand it much better. Thank you very very much :)

My only 3 questions:

What is BUFSIZE (I know buffer size but whats it exactly mean)?

What is sscanf?

What is line?

This topic is now closed to further replies.
  • Recently Browsing   0 members

    • No registered users viewing this page.
  • Posts

    • Bose Ultra Open Earbuds are once again selling at their lowest price by Fiza Ali Amazon is once again offering the Bose Ultra Open Earbuds at their lowest price ever with a limited-time 33 percent discount on their original MSRP, ahead of Father's Day. So, you may want to check it out if you are looking for a gift or if you have been wanting to upgrade your device. The earbuds feature an open-ear design and Bose's OpenAudio technology that should deliver high-quality sound while helping keep audio private. The earbuds also support Bose Immersive Audio, which creates a spatialised listening experience designed to place sound around the listener for a more engaging experience. In terms of wireless connectivity, the earbuds features Bluetooth, Bluetooth Low Energy (BLE), A2DP audio streaming, HFP, AAC, and SBC support. Furthermore, they are compatible with Bose SimpleSync technology, allowing pairing with compatible Bose smart soundbars and speakers. They are also compatible with the Bose App for setup, customisation, and software updates. Moreover, they offer an IPX4 water-resistance rating that should provide protection against sweat and light splashes. When it comes to the battery performance, the Bose Ultra Open Earbuds should provide up to seven hours of battery life on a single charge while a full recharge should take approximately one hour. Specifications Detail Fit type Open-ear Noise cancelling No Microphone Built-in Wireless Bluetooth (A2DP, HFP, AAC, SBC, BLE) Multipoint Yes; 2 devices simultaneously Charging interface USB-C Earbud size 0.73"x0.67" x 1.07" (0.014lb) Case size 1.65"x2.56" x 1.04" (0.097 lb) Materials PC-ABS plastic, metal, silicone, gold plating App support Bose app; adjustable EQ, SimpleSync Audio tech OpenAudio, immersive/spatialized sound Bose Ultra Open Earbuds: $199 (Amazon US) - 33% off Good to know This Amazon deal is U.S. specific, and not available in other regions unless specified. We only use first-party seller links (at the time of article publishing); ensure that you purchase from a first-party seller link only. Check out Today's Deals on Amazon | or our recent tech deals. Become a Prime member (for Students or SNAP) via Neowin Get Prime Access - Prime for half price (for qualifying Medicaid, EBT, SNAP) Subscribe to Prime Video, Audible Plus, Music Unlimited or Kindle Unlimited via Neowin As an Amazon Associate, we earn from qualifying purchases.
    • After enabling it in about:config, customize, density, compact; the toolbar/address bar gets smaller vertically. I enabled Nova, I notice the tab bar/title bar is a bit larger vertically now? Everything always becomes a waste of space.
    • Microsoft's Copilot Cowork now generally available with usage-based billing by Pradeep Viswanathan Back in March, Microsoft first revealed Copilot Cowork, a new agentic AI experience in Microsoft 365 Copilot through which users can assign tasks to AI to complete in the background. After testing the service with a limited set of customers in Research Preview for a few weeks, Microsoft announced the general availability of Copilot Cowork to customers in the Frontier program on March 30. Today, Microsoft announced the general availability of Copilot Cowork worldwide for Microsoft 365 Copilot customers. The company also highlighted that Cowork became the fastest-growing feature in the history of its Frontier program. Unlike regular Copilot Chat, Copilot Cowork can run complex, long-running, multi-tool tasks from start to finish in the cloud by using organizational context through Work IQ. When compared to Claude Cowork, Microsoft claims that Copilot Cowork will be 30% to 40% cheaper on average with its Microsoft 365 connector. For now, Copilot Cowork runs on Anthropic models, including Opus 4.8 and Sonnet 4.6. However, Frontier customers can now use GPT-5.5. Microsoft also announced Cowork 1, a secure fine-tuned model coming in the next few weeks, which is designed to handle everyday Copilot tasks at a lower cost. To access Copilot Cowork, a Microsoft 365 Copilot user subscription is required. Usage is billed separately through Copilot Credits, based on model use, context retrieval, tool calls, and runtime. Pay-as-you-go pricing is set at $0.01 per Copilot Credit. To offer IT teams full control over usage costs, Microsoft provides spending limits, usage alerts, user-level controls, reporting, and prepaid usage plans for organizations. Usage-based billing begins today. However, Frontier customers who used Cowork between March 30 and June 16 will not be billed until July 1, 2026. The Microsoft 365 Copilot app now includes a toggle to enter the full Cowork experience. Microsoft is also adding partner plugins, with Enosix, Harvey, LSEG, Miro, monday.com, Moody’s, Morningstar, S&P Global Energy, and TeamsMaestro available now. Adobe, Atlassian, Box, Canva, Databricks, and others are coming soon.
    • With Nova enabled I am not seeing a difference with compactmode.show?
    • HOLY THREAD REVIVAL   But yes, look for browser.nova.enabled and set it to true
  • Recent Achievements

    • One Year In
      Console General earned a badge
      One Year In
    • One Year In
      Twozo Technologies earned a badge
      One Year In
    • One Month Later
      Twozo Technologies earned a badge
      One Month Later
    • Week One Done
      Twozo Technologies earned a badge
      Week One Done
    • Veteran
      branfont went up a rank
      Veteran
  • Popular Contributors

    1. 1
      +primortal
      522
    2. 2
      +Edouard
      196
    3. 3
      PsYcHoKiLLa
      111
    4. 4
      Steven P.
      90
    5. 5
      Nick H.
      71
  • Tell a friend

    Love Neowin? Tell a friend!