I'm having a problem with the .txt as I have to create a customer record and then I can change the data. What happens is the following, when I create the client the data looks like this:
enter image description here
But when I go to edit the name or the country, it's like that, and what I wanted is for you to make the change without creating new lines.
Name:
enter image description here
Country:
enter image description here
I'm probably missing something or it's the way to save the file, but I don't know!!
This is my code:
typedef struct {
char name[80];
char country[10];
int tin;
int customer_code;
} CLIENT, upd, add;
void
edit_customer()
{
CLIENT add, upd;
int choice;
FILE *bd;
bd = fopen("bd.txt", "a");
printf("Enter the customer code: ");
scanf("%d", &add.customer_code);
printf("\nSelect the type of change you want:\n1 - Name\n2 - Country\n\nEnter your choice:");
scanf("%d", &choice);
switch (choice) {
case 1:
fgets(upd.name, 80, stdin);
printf("Type your name: ");
scanf("%[^\n]s", upd.name);
fprintf(bd, "code: %d | name: %s | tin: %d | country: %s \n",
add.customer_code, upd.name, add.tin, add.country);
printf("Changes saved!");
break;
case 2:
printf("Enter the Country:");
scanf("%s", upd.country);
fprintf(bd, "code: %d | name: %s | tin: %i | country: %s \n",
add.customer_code, add.name, add.tin, upd.country);
printf("Changes saved!");
break;
}
}
Updating the data in a file is not easy. First of all you have to decide how you intend to save your data because the way you modify the data will depend on this. There are many ways to do this but to keep it simple there are two basic ways. The first way is to insert records of fixed size. practically you have to decide the size of each field of your record and it will always have to be the same for all the records of your file. So, taking your struct as example
typedef struct {
char name[80];
char country[10];
int tin;
int customer_code;
} CLIENT;
you could write the records by modifying the formatting of the fprintf a little, for example in this way:
"| code: %-10u | name: %-20.20s | tin: %-10u | country: %-25.25s |\n"
this way your file will contain records like this (knowing their position in the record you wouldn't really need the name of the fields):
| code: 1234561 | name: Super Mario | tin: 1286608618 | country: know the name |
| code: 23 | name: John | tin: 123 | country: Donknow |
now if you want to modify one of the records present, you will have to search for it in your file by reading line by line and saving, before each reading, where the line begins in your file using for example the ftell function. Found the record, load its fields and modify those you want to change and at this point move the file pointer back to the beginning of the line (fseek function) and overwrite the old record with the one just modified.
If, on the other hand, you do not want to use fixed-size records, as you are doing now, the work becomes a little more complicated because unfortunately the files are not elasticized, so if you need to modify a record that has a different length than the one in the file you have to make room for it. There are a thousand ways to do this but in essence you should:
save the records that are under the one you want to modify in the file
modify the record
cut the file at the end of the record you edited
append the part you previously saved to the file
In truth for safety you should:
create a temporary file
copy the records preceding the one to be modified into the temporary file
append the new record
append the remainder of the file except the old record
save the temporary file (fclose)
delete the old file
rename the temporary file with the name of the file just deleted
Apart from that, as the comments say, in your program you try to modify a record that you have not read from the file, so the one modified by the user is the only field that has a value while the others have not been initialized. However, it is not enough. You will have to follow what I have written to you if you want to see your program work.
Related
So i have this text file that contains what a person with certain email likes:
email1#gmail.com
Likes:
Animals
Sports
email2#gmail.com
Likes:
Science
Animals
What i really need are those specific words of what certain user email likes (only one email at the time choosen by scanf) and each liked topic of his (all of them are just one word) is going to be used in a function of my code (ex: function(Animals)).
Edit: I just want each word of what a email that i choose likes (Case email1 i want the word "Animals" and the word "Sports" extracted from the text file because i need to use those words). How can i do that with C?
Try the below code
#include<stdio.h>
#include<string.h>
int main()
{
FILE * fptr = NULL;
fptr = fopen("File.txt" , "r");//Let File.txt be the required file
if(fptr==NULL)//Check if file was opened successfully
{
printf("File could not be opened");
return 0;
}
printf("File opened\n");
char buff[1024];//To store line read from file
char email[1024];//To store email id
printf("Enter email id:");
scanf("%s",email);
int found=0;
while(fscanf(fptr,"%[^\n]\n",buff))//Read file line by line and store the line to buff
{
//printf(":%s:",buff);
if(strstr(buff,"#")!=NULL)//Set found=0 if the line in the file is an email id. Here I am checking for the word "#" in the line read since an email id will surely have an # symbol. Replace it with some checking function to verify if it's an email id
{
if(found==1)//If the email was already found break out of the loop
break;
found=0;
}
if(found==1)//If found=1 buff will have your required Likes including the word Likes:
{
if(strcmp("Likes:",buff)!=0)//If required word is not 'Likes:' since only the likes is required not the word 'Likes:'
{
printf("%s\n",buff);//buff contains the required like. It can be used as your functions argument.
}
}
if(strcasecmp(email,buff)==0)//Set found=1 if the required email is found
found=1;
if(feof(fptr))//Break out of the loop if file end is reached
break;
}
}
If email1 is the required email id, then your input should be email1#gmail.com as it is stored in this format in the file.
I wrote a small program in C that creates a list of students in a binary file. I call function fsearch() (below) to search for a specified student and change his data, but the data seems not to be modified.
// the file is opened in mode "wb+"
int fsearch(FILE *f)
{
student s;
float matsearch;
printf("enter the matricule you want to find ");
scanf("%f",&matsearch);
rewind(f); // starting the search from the beginning
while(fread(&s,sizeof(student),1,f)==1 && s.mat!=matsearch);
if(s.mat==matsearch)
{
printf("we found what searched for\n");
printf("name: %s\n",s.fname);
printf("last name: %s\n",s.lname);
printf("matricule: %.f\n",s.mat);
fseek(f,-sizeof(student),SEEK_CUR);
student a;
scanf("%s",&(a.fname));
scanf("%s",&(a.lname));
scanf("%d",&(a.mat));
if(fwrite(&a,sizeof(student),1,f)==1)
{
printf("successfully wrote"); // this message does get printed
}
return(1); // successfully found
}
printf("we didn't find what you searched for\n");
return(0);
}
In addition to the one posted by bluesawdust, I found some other mistakes in the code:
// the file is opened in mode "wb+": this means that your file was destroyed on open (see here). You might want to use "rb+"
since you didn't initialize your student s structure (and no record was ever written in it because of my previous point) s.mat contains a random value
scanf("%d",&(a.mat));: as for printf, you should change the format string to "%f" (but actually you should use a string type, comparing floats with == is not good practice because of the roundings)
sizeof(student) is unsigned, so negating it is not appropriate here. You should cast it to an int before negating.
I'm writing a POS program as a school assignment. I'm using multiple txt files as a database. The program is suppose to allow the user to enter a SKU number (e.g. 123) then it will open a txt file in a database (e.g. database/123.txt). It then pull info from the txt file such as a price and allow the user to add multiple files and end with a total. The user can also add to the database by creating new SKUs. They are also able to view transaction history. The issue I am having is I can't seem to figure out how to record a number from a user and then use that number to open a text file beginning with that number. (e.g. use enters 123 then 123.txt is opened.)
Here is the section of my code that I need help with:
// Function to start a transaction
int transaction(void)
{
// Define Variables
char buf[1000], nDatabase[100];
float nPrice[500], nTotal;
// Instructions
printf("You have started a transaction.\n");
printf("Enter the SKU number below.\n");
printf("Enter 0 to complete the transaction.\n");
// Begin loop here
do
{
FILE *ptr_file;
// record SKU number
/*remove test tools later*/
printf("we r here\n");
scanf("Enter the SKU: %c\n", &nDatabase);
printf("now we r here\n");
// Open database file
/*Change location later*/
ptr_file = fopen("database/123.txt", "r");
// If file is not found return 1
if (!ptr_file)
{
printf("Could not match that SKU number.\n");
return 1;
}
while (fgets(buf, 1000, ptr_file) != NULL)
printf("%s\n", buf);
scanf("%s", &nPrice[0]);
// Close file
fclose(ptr_file);
while (nDatabase == 0);
nTotal = nPrice[0] + nPrice[1];
printf("Your total is: $%.2f\n", &nTotal);
return 0;
}
}
printf( "Enter the SKU: " ) ; // <-- scanf if only for input, the prompt must be output separately
scanf( "%s\n", nDatabase);
// ^ ^
// | |_No & here - nDatabase is an array
// |
// |_Accept a string not a character
Then you might form a complete file name with sprintf, e.g.
char filename[MAX_FNAME] ;
sprintf( filename, "database/%s,txt", nDatabase ) ;
Be aware that no error checking or overrun protection is performed by the above - you may want to consider adding some.
You need to concatenate the user input with you database path, and extension.
Check this post: C string append
I have a few issues with my syntax, it mainly says i have an errror before "struct" on the line "Struct CustomerInfo s; but i dont seem to find the problem.
My program is supposed to ask what the person would like to do first of all, they can store a record for the first option which is then stored in a structure which can be viewed by selecting the 2nd option of the menu, if they select the 3rd then they obviously quit the program.
any help would be appreciated thank you.
#include <stdio.h>
void menu();
int id,first,last;
struct CustomerInfo
{
char FirstName[15]; /* These are the varibles for the customer infomation */
char LastName[20];
int ID;
};
int main()
{ /* program starts */
int selection = 0;
void menu()
{ /* Menu loop function */
do
{ /* menu start */
printf("\n\n - What would you like to do?");
printf("\n1 - Store a customer record");
printf("\n2 - View customer Records");
printf("\n3 - Quit program");
scanf("%i", &selection);
} while (selection > 3);
printf("You have entered an incorrect value"); /* If selection is greater than 3 then end program */
return 0;
}
switch(selection)
{
/* switch statement starts */
case 1:
struct CustomerInfo s;
printf("Please enter the customers details including First name, Lastname and ID.\n\n");
printf("Enter First name: ");
scanf("%s", s.FirstName); /* Option 1: Asks to enter the customers details to store then loops back to program */
printf("Enter Last name: ");
scanf("%s", s.LastName);
printf("Enter Customer ID: ");
scanf("%s", s.ID);
void menu();
break;
case 2:
printf("\nDisplaying Infomation\n");
printf("First name: %s\n",s.Firstname); /* Option 2: Prints the customer details as listed in option 1 */
printf("Last name: %s\n",s.Lastname);
printf("Customer ID: %s\n",s.ID);
void menu();
break;
case 3: /* Option 3: Program ends if option 3 is chosen. */
break;
}
return 0;
Let's start by looking at the structure you created; next we'll try to see if it can be fixed.
I am leaving details out so we can see the big outline:
main {
struct{}
void menu(){
do {
stuff
} while (selection > 3)
printf("you have entered an incorrect value"); // if selection is > 3
}
switch(selection) {
// do something if selection is 1 or 2, exit if 3
}
There is no final closing brace in your code. I am assuming that's a copy-paste error, so I added it. Compiling with -Wall (to get warnings as well as errors reported), I get a number of errors:
sel.c:18: error: nested functions are disabled, use -fnested-functions to re-enable
sel.c: In function ‘menu’:
sel.c:31: warning: ‘return’ with a value, in function returning void
sel.c: In function ‘main’:
sel.c:38: error: expected expression before ‘struct’
sel.c:41: error: ‘s’ undeclared (first use in this function)
sel.c:41: error: (Each undeclared identifier is reported only once
sel.c:41: error: for each function it appears in.)
sel.c:61: warning: control reaches end of non-void function
Let's take those in turn:
sel.c:18: error: nested functions are disabled, use -fnested-functions to re-enable
Putting one function inside another is "nesting". It is rare that you would want to do that - it means that the function is only "visible" when you are inside the other function (a bit like local variables, but for functions). It is not standard C - it is an extension of gcc. It's almost always a bad idea to use non-standard (and thus non-portable) extensions. See http://gcc.gnu.org/onlinedocs/gcc/Nested-Functions.html
sel.c: In function ‘menu’:
sel.c:31: warning: ‘return’ with a value, in function returning void
When we declare a function void, we say that it will not return a value. When you have a statement like return 0; you ARE returning a value. The compiler will ignore that - but it warns that you said one thing, and did another. Just use return; without a parameter, and the warning goes away.
sel.c:38: error: expected expression before ‘struct’
sel.c:41: error: ‘s’ undeclared (first use in this function)
sel.c:41: error: (Each undeclared identifier is reported only once
sel.c:41: error: for each function it appears in.)
This is the trickiest one. You would expect that you were properly declaring a variable s in line 38 - but the compiler complains. The reason for this is explained in the excellent Q&A at
Why can't variables be declared in a switch statement?
As an aside - if you COULD declare a variable like this - what are you doing with it? Your code currently reads in values, and returns. But as soon as you leave the "scope" of the variable (in your case, since you declared s inside the switch, that would be its scope) the variable disappears (the memory that was used for it is marked "free" and will be re-used.)
sel.c:61: warning: control reaches end of non-void function
This says that you have reached the end of a function that expects to return a value, but you don't have a return someValue; type of statement. Again - this only causes a warning, since the default behavior is to return 0 if no value is given, but it's a sign that you said one thing and did another.
So far I've just explained the errors that the compiler gave. Let's look more closely at the code structure. What I think you want to do is something like this:
define customerInfo structure
define menu function
main()
repeat:
call menu, get selection
switch(selection):
case 1: create new record
case 2: display records
case 3: quit program
In order to make this work, we need to make some changes to your program. First - let's move the menu function definition outside of the main function so we have portable code. Second - if we want to be able to create multiple customer records, we need to store them in an array. Really you would want a list so you can extend indefinitely, but let's keep it simple and allow a maximum of 10 records. Then we need to improve the logic of the menu function (if selection is not 1, 2 or 3 you give a message and try again; in your current code the line
printf("You have entered an incorrect value");
doesn't get executed until you have exited the loop that tested for incorrect values… so when you finally get there, the value is valid, not invalid.
Before we actually get to writing the "correct" code, there's another thing worth noting. When you read values using scanf, you do things like:
scanf("%s", s.FirstName);
which is correct, since s.FirstName is a pointer to the start of a string. However, you allocated a finite amount of space to your string (namely, 15 characters including the terminating '\0') so if someone enters a long name, your program will crash. "Good defensive coding" demands that you catch this - use for example
scanf("%14s", s.FirstName);
This says "read no more than 14 characters". There are better tricks but at least this is a start. However, you actually make a mistake when you do
scanf("%s", s.ID);
Since ID was defined as an int, and now you are reading a string into… not just its address, but into some location that is pointed to by the value of s.ID . This is very likely to give you a segmentation error (accessing memory that "isn't yours"). You should be doing:
scanf("%d", &s.ID);
"Read an integer into the location of s.ID"
Also - in some places you use FirstName, while in others you use Firstname. Ditto LastName. Capitalization matters - when you fix other compiler errors, these will start to show up.
Since you seem to want to be able to read in more than one customer record, we need an array of records; as I said above, we have to make sure the array is available in the scope of the switch statement, and "survives" that statement (so you can do something with it). Taking all these things together gets us to something like this:
#include <stdio.h>
// define function prototype:
int menu();
struct CustomerInfo
{
char FirstName[15]; /* These are the variables for the customer infomation */
char LastName[20];
int ID;
};
int menu()
{ /* Menu loop function */
int flag = 0;
int selection;
do
{ /* menu start */
if(flag > 0) printf("You have entered an incorrect value"); /* If selection is greater than 3 then end program */
printf("\n\n - What would you like to do?");
printf("\n1 - Store a customer record");
printf("\n2 - View customer Records");
printf("\n3 - Quit program\n>> ");
scanf("%i", &selection);
flag++;
} while (flag < 10 && (selection < 0 ||selection > 3));
return selection;
}
int main(void)
{ /* program starts */
struct CustomerInfo s[10];
int selection;
int customerCount = 0;
while(1) {
int ii; // loop counter we will need later
selection = menu();
switch(selection)
{
case 1:
printf("Please enter the customers details including First name, Lastname and ID.\n\n");
printf("Enter First name: ");
scanf("%s", s[customerCount].FirstName); /* Option 1: Asks to enter the customers details to store then loops back to program */
printf("Enter Last name: ");
scanf("%s", s[customerCount].LastName);
printf("Enter Customer ID: ");
scanf("%d", &s[customerCount].ID);
customerCount++;
break;
case 2:
printf("\nDisplaying Infomation\n");
for(ii = 0; ii < customerCount; ii++) {
printf("First name: %s\n",s[ii].FirstName); /* Option 2: Prints the customer details as listed in option 1 */
printf("Last name: %s\n",s[ii].LastName);
printf("Customer ID: %d\n---\n",s[ii].ID);
}
break;
case 3: /* Option 3: Program ends if option 3 is chosen. */
return 0; // program returns
break;
}
}
}
Test output:
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> 1
Please enter the customers details including First name, Lastname and ID.
Enter First name: John
Enter Last name: Smith
Enter Customer ID: 123
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> 5
You have entered an incorrect value
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> -1
You have entered an incorrect value
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> 1
Please enter the customers details including First name, Lastname and ID.
Enter First name: Harry
Enter Last name: Jones
Enter Customer ID: 654
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> 2
Displaying Infomation
First name: John
Last name: Smith
Customer ID: 123
---
First name: Harry
Last name: Jones
Customer ID: 654
---
- What would you like to do?
1 - Store a customer record
2 - View customer Records
3 - Quit program
>> 3
How does one read in a txt file containing names and marks of students and inputting them
into an array of structures.
maximum allowable records are 7:
e.g. James 45
Mary 70
Rob 100
First, define the structure. The structure describes what a record is; what data it contains. Here you have a student's name and his or her mark.
Second you need to prepare the array to write the objects of the structure into. You already know from the problem description that no more than 7 students are allowed, so you can define the length of the array to that number.
Next, open the text file.
Lastly write a loop that takes as input from the file a string for the student's name and an integer (or a floating-point point number if you so choose) for their mark. In the loop create a structure for each record and insert the structure into the array.
And of course, don't forget to close the file when you're done.
That's all there is to it. If you have any syntax or logic questions then ask in the comments, and we'll gladly help.
Read the man page for fopen: http://linux.die.net/man/3/fopen
This should give you somewhere to start.
Also, the man page for fread and fgets could be helpful. There are many ways to read from a file and the path you choose will depend on numerous things, such as the structure of the file and the amount of security you want in your application.
found this code that is similar enough that should be able to help you get done what you need.
#include <stdio.h>
#include <string.h>
/* Sample data lines
5 0 Wednesday Sunny
6 2 Thursday Wet
*/
int main() {
/* Define a daydata structure */
typedef struct {
int n_adults; int n_kids;
char day[10]; char weather[10];
} daydata ;
daydata record[30];
FILE * filehandle;
char lyne[121];
char *item;
int reccount = 0;
int k;
/* Here comes the actions! */
/* open file */
filehandle = fopen("newstuff.txt","r");
/* Read file line by line */
while (fgets(lyne,120,filehandle)) {
printf("%s",lyne);
item = strtok(lyne," ");
record[reccount].n_adults = atoi(item);
item = strtok(NULL," ");
record[reccount].n_kids = atoi(item);
item = strtok(NULL," ");
strcpy(record[reccount].day,item);
item = strtok(NULL,"\n");
strcpy(record[reccount].weather,item);
printf("%s\n",record[reccount].day);
reccount++;
}
/* Close file */
fclose(filehandle);
/* Loop through and report on data */
printf("Weather Record\n");
for (k=0; k<reccount; k++) {
printf("It is %s\n",record[k].weather);
}
}
http://www.wellho.net/resources/ex.php4?item=c209/lunches.c
Give a holler with code you tried if you have problems changing it to fit your needs.