C - fgets and fputs not editing file data - c

Full code: https://pastebin.com/NpspcJB8
I'm not sure if I'm using fgets() and fputs() correctly, but I need this or something similar in order to edit my file for the program. Within my program, I will have created a file, but when I generate the file contents in my program, I get this:
File output
Space: D44 Customer Name: empty Registration number: empty
Space: D45 Customer Name: empty Registration number: empty
Space: D46 Customer Name: empty Registration number: empty
Space: D47 Customer Name: empty Registration number: empty
Space: D48 Customer Name: empty Registration number: empty
Space: D49 Customer Name: empty Registration number: empty
Space: D50 Customer Name: empty Registration number: empty
empty
empty
empty
empty
empty
empty
empty
This happens when I add parking spaces in the program, and I believe that this merely shifts the array values. I need empty in the file output removed, which I attempted in a code using the functions I first mentioned, within a function I created:
int CheckExtraInput() {
fptr=fopen("parking_spaces.txt", "r+");
if (fptr==NULL) {
printf("Error! File does not exist");
return 1;
}
char extraInput[] = " empty\n";
// http://www.cplusplus.com/reference/cstdio/fgets/
// https://www.tutorialspoint.com/c_standard_library/c_function_strchr.htm
// char *s = strchr(extraInput, '\n');
// if(s) *s = '\0';
// fseek(fptr, 7, SEEK_SET);
while (fgets(extraInput, 8, fptr) != NULL) {
fputs(" aaa ", fptr);
}
}
I used " aaa " to test this code, to which it does not. I believe that I could use more in order to get this to work, but I'm not sure what; I used fseek() earlier on with similar results.
I just need to find out a way for the program to go to the end of the file, and if it starts to detect empty, it needs to remove it to save storage space.

Related

Get specific info between two certain points in a text file using C

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.

search in a file in c

the data on the file.txt are placed as shown.
My Code is this:
int searchBookname()
{
FILE *myFile=fopen("file.txt","r+");
if (myFile!=NULL) // file exists
{
char tmp1[512];
char tmp2[512];
while(fgets(tmp1,512,myFile)!=EOF)
{
puts("Insert the Book Name: ");
scanf("%s",tmp2);
if(strstr(tmp1,tmp2)!=NULL){
printf("the book is found: %s\n\n",tmp1);
}else{
puts("\nSorry there was no Match with this name! Maybe Book is not recorded yet :(\n");
}
}
}else{ // file doesn't exist
puts("\nDatabase is not created yet. Please record a new book to create a simple database\n");
exit(0);
}
fclose(myFile); // closing the file
}
It keeps skipping the if statement 2 times for some reason and on the
3rd time it prints the correct result.
This happen for whatever book I try to search.
See here
How can I make it find the result without skipping the if statement.
You read the file line by line. So in the third loop/line there is a record with 'book1'. Code is working correctly as it is. Maybe you want to ask the user for a book name outside of the while loop and search in every line for the given book name. If there is, you can print you message and break from the loop.
int searchBookname()
{
FILE *myFile=fopen("file.txt","r+");
if (myFile != NULL) // file exists
{
char tmp1[512], tmp2[512];
puts("Insert the Book Name: ");
scanf("%s",tmp2);
// Skip the first two lines of the file
fgets(tmp1,512,myFile);
fgets(tmp1,512,myFile);
while(fgets(tmp1,512,myFile) != EOF)
{
if(strstr(tmp1,tmp2) != NULL)
{
printf("the book is found: %s\n\n",tmp1);
break;
}
else
{
puts("\nSorry there was no Match with this name! Maybe Book is not recorded yet :(\n");
}
}
}
else
{ // file doesn't exist
puts("\nDatabase is not created yet. Please record a new book to create a simple database\n");
exit(0);
}
fclose(myFile); // closing the file
}
It is obvious.
First 2 lines of file are following:
Record_Date ...
-> (empty line)
You are reading file line by line and check book name in each line. So if must fail for first 2 times.
If you want to find a book in your file, your approach is incorrect. There are different approaches for this, but simplest is reading book records into an structure array, and then look for book name in that array.

The last character is not printed to a file

I am trying to figure out why using C function strtok is not working properly for me. Here's the problem:
I have a file which contains two types of information: headers and text descriptions. Each line in the file is either a header or part of a text description. A header starts with '>'. The description text follows the header and can span multiple lines. At the end of the text there is an empty line which separates the description from the next header. My aim is to write two separate files: one contains the headers on each line and the other contains the corresponding description on a line by itself. To implement the codes in C, I used fgets to read the file one line at a time into dynamically allocated memory. In order to write the description text on one single line, I used `strtok to get rid of any new line characters exists in the text.
My code is working properly for the header files. However, for the descriptions file, I noticed that the last character of the text is not printed out to the file even though it is printed to the stdout.
FILE *headerFile = fopen("Headers", "w"); //to write headers
FILE *desFile = fopen("Descriptions", "w"); //to write descriptions
FILE *pfile = fopen("Data","r");
if ( pfile != NULL )
{
int numOfHeaders =0;
char **data1 = NULL; //an array to hold a header line
char **data2 = NULL; //an array to hold a description line
char line[700] ; //maximum size for the line
while (fgets(line, sizeof line, pfile ))
{
if(line[0] =='>') //It is a header
{
data1 = realloc(data1,(numOfHeaders +1)* sizeof(*data1));
data1[numOfHeaders]= malloc(strlen(line)+1);
strcpy(data1[numOfHeaders],line);
fprintf(headerFile, "%s",line);//writes the header
if(numOfHeaders >0)
fprintf(desFile, "\n");//writes a new line in the desc file
numOfHeaders++;
}
//it is not a header and not an empty line
if(line[0] != '>' && strlen(line)>2)
{
data2 = realloc(data2,(numOfHeaders +1)* sizeof(*data2));
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
strcpy(data2[numOfHeaders],s);
fprintf(desFile, "%s",data2[numOfHeaders]);
printf(desFile, "%s",data2[numOfHeaders]);
}
} //end-while
fclose(desFile);
fclose(headerFile);
fclose(pfile );
printf("There are %d headers in the file.\n",numOfHeaders);
}
As mentioned in the comments:
fprintf(desFile, "%s",data2[numOfHeaders]); //okay
printf(desFile, "%s",data2[numOfHeaders]); //wrong
Second line should be:
printf("%s",data2[numOfHeaders]); //okay
Or, you could do this:
sprintf(buffer, "%s",data2[numOfHeaders]);
fprintf(desFile, buffer);
printf(buffer);
Other possible issues:
Without an input file it is not possible to know for certain what strtok() is doing, but here is a guess based on what you have described:
In these two lines:
data2[numOfHeaders]= malloc(strlen(line)+1);
char *s = strtok(line, "\n ");
if the string contained in data2 has any embedded spaces, s will only contain the segment occurring before that space. And because you are only calling it once before line gets refreshed:
while (fgets(line, sizeof line, pfile ))
only one token (the very first segment) will be read.
Not always, but Normally, strtok() is called in a loop:
char *s = {0};
s= strtok(stringToParse, "\n ");//make initial call before entering loop
while(s)//ALWAYS test to see if s contains new content, else NULL
{
//do something with s
strcpy(data2[numOfHeaders],s);
//get next token from string
s = strtok(NULL, "\n ");//continue to tokenize string until s is null
}
But, as I said above, you are calling it only once on that string before the content of the string is changed. It is possible then, that the segment not printing has simply not yet been tokenized by strtok().

How to open a file with a user inputted variable in C?

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

Why does my program read an extra structure?

I'm making a small console-based rpg, to brush up on my programming skills.
I am using structures to store character data. Things like their HP, Strength, perhaps Inventory down the road. One of the key things I need to be able to do is load and save characters. Which means reading and saving structures.
Right now I'm just saving and loading a structure with first name and last name, and attempting to read it properly.
Here is my code for creating a character:
void createCharacter()
{
char namebuf[20];
printf("First Name:");
if (NULL != fgets(namebuf, 20, stdin))
{
char *nlptr = strchr(namebuf, '\n');
if (nlptr) *nlptr = '\0';
}
strcpy(party[nMember].fname,namebuf);
printf("Last Name:");
if (NULL != fgets(namebuf, 20, stdin))
{
char *nlptr = strchr(namebuf, '\n');
if (nlptr) *nlptr = '\0';
}
strcpy(party[nMember].lname,namebuf);
/*Character created, now save */
saveCharacter(party[nMember]);
printf("\n\n");
loadCharacter();
}
And here is the saveCharacter function:
void saveCharacter(character party)
{
FILE *fp;
fp = fopen("data","a");
fwrite(&party,sizeof(party),1,fp);
fclose(fp);
}
and the loadCharacter function
void loadCharacter()
{
FILE *fp;
character tempParty[50];
int loop = 0;
int count = 1;
int read = 2;
fp= fopen("data","r");
while(read != 0)
{
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
loop++;
count++;
}
fclose(fp);
}
So the expected result of the program is that I input a name and last name such as 'John Doe', and it gets appended to the data file. Then it is read in, maybe something like
1. Jane Doe
2. John Doe
and the program ends.
However, my output seems to add one more blank structure to the end.
1. Jane Doe
2. John Doe
3.
I'd like to know why this is. Keep in mind I'm reading the file until fread returns a 0 to signify it's hit the EOF.
Thanks :)
Change your loop:
while( fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp) )
{
// other stuff
}
Whenever you write file reading code ask yourself this question - "what happens if I read an empty file?"
You have an algorithmic problem in your loop, change it to:
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
while(read != 0)
{
//read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
loop++;
count++;
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
}
There are ways to ged rid of the double fread but first get it working and make sure you understand the flow.
Here:
read=fread(&tempParty[loop],sizeof(tempParty[loop]),1,fp);
printf("%d. %s %s\n",count,tempParty[loop].fname,tempParty[loop].lname);
You are not checking whether the read was successful (the return value of fread()).
while( 1==fread(&tempParty[loop],sizeof*tempParty,1,fp) )
{
/* do anything */
}
is the correct way.
use fopen("data","rb")
instead of fopen("data","r") which is equivalent to fopen("data","rt")
You've got the answer to your immediate question but it's worth pointing out that blindly writing and reading whole structures is not a good plan.
Structure layouts can and do change depending on the compiler you use, the version of that compiler and even with the exact compiler flags used. Any change here will break your ability to read files saved with a different version.
If you have ambitions of supporting multiple platforms issues like endianness also come into play.
And then there's what happens if you add elements to your structure in later versions ...
For robustness you need to think about defining your file format independently of your code and having your save and load functions handle serialising and de-serialising to and from this format.

Resources