I had to write a simple database (console application) in C: You could input gender, name and adress of people and the data would be saved in an array of structs called 'Person'. You could then also display all entries or delete entries again. So far so good.
Now I have to add functions to save the data into a .csv file and read from it again. However, the function fopen() always returns a NULL-pointer, so I can't even get to the reading or writing part. Below is my code. I hope you can tell me why not even this first step is working. I'm rapidly losing any confidence I had in my C abilities.
void save(Person persons[]) {
char name[LEN];
printf("File Name: ");
fgets(name, LEN, stdin);
fflush(stdin);
name[strlen(name)] = '\0';
FILE *file = fopen(name, "wx");
if (!file) {
printf("The file couldn't be created.\n\n");
}
}
why not even this first step is working.
fopen(name, "wx") certainly returns NULL as name contains '\n'. Improbable that such a file name exists.
See Removing trailing newline character from fgets() input.
Related
I've ran into a problem trying to open a file from user input. I can open it if the filename is correct the first time it's entered, but can't if it's correct in the while loop.
char file[256], *end;
printf("Enter the name of the file: ");
fgets(file, 256, stdin);
if((end=strchr(file, '\n'))!=NULL)
*end='\0';
FILE *fp=fopen(file, "r");
while(fp==NULL)
{
printf("The given file doesn't exist. Enter a file name: ");
fgets(file, 256, stdin);
if((end=strchr(file, '\n'))!=NULL)
*end='\0';
FILE *fp=fopen(file, "r");
}
I can open it if the filename is correct the first time it's entered, but can't if it's correct in the while loop.
No, you're being fooled. The problem is that the loop condition in while(fp==NULL) tests the value of variable fp declared outside the loop, and inside the loop you never set that variable, so if you enter the loop you will never exit.
But that doesn't mean you fail to open the file on the second attempt or a subsequent one. Inside the loop, you declare another variable fp, "shadowing" the one outside, and assign the result of fopen() to it. When this fopen() succeeds, you effectively ignore the result.
As another, now deleted, answer said, the main thing to do is to fix the loop so that it uses the same fp that is used outside. The smallest change that achieves that would yield this version of the loop:
while(fp==NULL)
{
printf("The given file doesn't exist. Enter a file name: ");
fgets(file, 256, stdin);
if((end=strchr(file, '\n'))!=NULL)
*end='\0';
fp=fopen(file, "r");
}
There are some other issues with the way you input the file name, both there and in the code preceding, as well as some unnecessary code duplication, but as long as the file names entered by the user are simple and short, that will do the trick.
You need to consider about the platform here, to make it your code cross platform file check the approach is different. If the platform is not important then you dont need to worry about Windows, in Linux you can use stat utility.
Simple way to check the existence of file(Checks in read-mode) :
int read_file_exists(const char *filename)
{
FILE *fp = fopen (filename, "r");
if (fp!=NULL) fclose (fp);
return (fp!=NULL);
}
Check this link for more information about C file check.
I'm trying to have the program check, that, if a user inputs nothing the print statement will say it cant find the file name, but the issue I'm having is that the command line will just go to a new line after hitting enter instead of saying the print statement.
This is the code here. I was told that Null is the place holder for if nothing is put in so I thought it would work.
int main()
{
FILE *fin;
FILE *fout;
char fInName[50];
char fOutName[50];
printf("pleas type input file, and output file please type legibly\n ");
scanf("%s %s", &fInName, &fOutName);
fin = fopen(fInName, "r");
fout = fopen(fOutName, "r");
if (fInName == NULL && fOutName == NULL)
{
printf("Error: Cannot open input file %s.", fInName);
}
else if (fInName != NULL && fOutName == NULL)
{
printf("file found");
}
}
What im trying to test is if a first file name is entered and the second isnt then print the statement. If both arent entered then print file does not exist.
there is more to the code to see if the file exists or not, but thst would be a bit much, now Im just trying to understand why it wont read unentered data.
Ive tried looking at examples such as: How to detect empty string from fgets
and tried to alter the code to fit that type of style but it didnt work for me so Im giving you the code it was originally so that anything helpful wouldnt confuse me more.
Edit:
okay so I tried to do a simple code in order to see what may be the cause of this issue:
int main()
{
char firstname[50];
char lastname[50];
char nothing [0];
printf("pleas type input file, and output file please type legibly pwease\n ");
scanf("%s" "%s", firstname, lastname);
if (firstname == lastname )
{
printf("Error: Cannot open input file %s.", firstname);
}
else
{
printf("file found");
}
}
I ran the code using adam and either if I typed adam (space) adam or adam(enter) adam the program thinks that the input is not the same, I feel like that would help identify why it doesnt know why nothing is typed in.
The problem is occurring when you try to check if fInName == NULL.
The problem is that fInName is just a variable that you're using to store the name of the file that you want to open. What you actually want to check is that the user gave you a valid filename, and to do so you will want to understand what the return value of functions are.
For example, when you try to open a file using fopen(), if fopen() is unable to successfully open the file, say because the user didn't input anything or misspelled the filename, then fopen() will return NULL, storing it in whatever variable you assigned it to (in your case, *fin and *fout).
Also, scanf() is not recommended for char arrays because if the user inputs more data than you allocated for the array, which in this case is enough space for 50 characters, then scanf() will try to write data to memory that's not yours, causing a buffer overflow.
A much safer option is to use fgets() because you can choose exactly how much data is written into your char array, with the only downside being that fgets() will write newline characters \n (caused by hitting the enter key) into the array, though the simple solution is to overwrite the newline character with '\0'.
Therefore, I would propose:
int main(void)
{
char fInName[50];
char fOutName[50];
// ensure proper usage
do
{
printf("What file would you like to open? ");
// get infile from user and remove trailing newline '\n' character
fgets(fInName, 50, stdin);
fInName[strcspn(fInName, "\n")] = '\0';
}
// prompt for input until user enters something
while (strlen(fInName) < 1);
do
{
printf("What file would you like to output to? ");
// get outfile from user and remove trailing newline '\n' character
fgets(fOutName, 50, stdin);
fOutName[strcspn(fOutName, "\n")] = '\0';
}
// prompt for input until user enters something
while (strlen(fOutName) < 1);
FILE *fin = fopen(fInName, "r");
if (fin == NULL)
{
printf("Error: Cannot open input file %s.", fInName);
return 1;
}
else
{
printf("file found");
}
}
I'm currently trying to create a database in C, using a .txt document as the place to store all the data. But I can't get fputs() to shift line, so everything that my program writes in this .txt document is only on one line.
int main(void){
char c[1000];
FILE *fptr;
if ((fptr=fopen("data.txt","r"))==NULL){
printf("Did not find file, creating new\n");
fptr = fopen("data.txt", "wb");
fputs("//This text file contain information regarding the program 'monies.c'.\n",fptr);
fputs("//This text file contain information regarding the program 'monies.c'.\n",fptr);
fputs("//Feel free to edit the file as you please.",fptr);
fputs("'\n'",fptr);
fputs("(Y) // Y/N - Yes or No, if you want to use this as a database",fptr);
fputs("sum = 2000 //how much money there is, feel free to edit this number as you please.",fptr);
fclose(fptr);
}
fscanf(fptr,"%[^\n]",c);
printf("Data from file:\n%s",c);
fclose(fptr);
return 0;
}
This is my testing document.
I feel like I've tried everything and then some, but can't get it to change line, help is much appreciated.
Btw. The output looks like this:
There are two issues in your program :
You should specify "w" rather than "wb" so that the file is read and written as text rather than binary. Although in some systems this makes no difference and b is ignored.
The part for file reading should be in an else, otherwise it executes after file creation with fptr not containing a valid value.
This is the code with those corrections. I do get a multiline data.txt with it.
int main(void){
char c[1000];
FILE *fptr;
if ((fptr=fopen("data.txt","r"))==NULL){
printf("Did not find file, creating new\n");
fptr = fopen("data.txt", "w");
fputs("//This text file contain information regarding the program 'mon
fputs("//This text file contain information regarding the program 'mon
fputs("//Feel free to edit the file as you please.",fptr);
fputs("'\n'",fptr);
fputs("(Y) // Y/N - Yes or No, if you want to use this as a database",
fputs("sum = 2000 //how much money there is, feel free to edit this nu
fclose(fptr);
}
else
{
fscanf(fptr,"%[^\n]",c);
printf("Data from file:\n%s",c);
fclose(fptr);
}
return 0;
}
I'm having issues trying to read a white space character in C. What I want to do is read user input when asking for a first and last name.
So for example, I prompt the user to enter their name, they type in something like "Peter Smith". With that info, I want to write it to a file.
When it writes it to a file, the file only reads the last name "Smith". How can I read the whole string?
Here's how I asked:
printf("\nPlease enter your first and last name: \n");
scanf("%[^\n]", name);
fgets(name, sizeof(name), stdin);
I don't think your problem lies in the snippet you posted. Here's an example program I wrote on my Linux system to try and pinpoint the issue:
#include <stdio.h>
int main()
{
char name[128];
int num_scans = 0;
FILE *out = fopen("name.txt", "w");
if(out == NULL)
{
printf("Failed to open file for write.\n");
return 1;
}
printf("\nPlease enter your first and last name: \n");
num_scans = scanf("%127[^\n]", name);
if(num_scans < 1)
{
printf("Error reading name.\n");
return 2;
}
fprintf(out, "%s\n", name);
fclose(out);
return 0;
}
This appeared to work for me:
$cat name.txt
Peter Smith
If you post the code you used to write the name to a file, that might reveal the source of the error.
The code is working correctly. The fgets call replaces the value you read for the first name.
You should stick to one scheme of input. When you switch between input paradigms "strange" things happen. (Technically they are exactly what is supposed to happen, but typical users tend to not be too precise about exactly how each function works, and what state the input stream is left in.)
A friend of mine needs to use MATLAB for one of his classes, so he called me up (a Computer Science Major) and asked if I could teach him C. I am familiar with C++, so I am also familiar with the general syntax, but had to read up on the IO library for C.
I was creating some simple IO programs to show my friend, but my third program is causing me trouble. When I run the program on my machine using Eclipse (with the CDT) Eclipse's console produces a glitchy output where instead of prompting me for the data, it gets the input and then prints it all at once with FAILURE.
The program is supposed to get a filename from user, create the file, and write to it until the user enters a blank line.
When I compile/run it on my machine via console (g++ files2.c) I am prompted for the data properly, but FAILURE shows up, and there is no output file.
I think the error lies with how I am using the char arrays, since using scanf to get the filename will create a functional file (probably since it ignores whitespace), but not enter the while loop.
#include <stdio.h>
#define name_length 20
#define line_size 80
int main() {
FILE * write_file; // pointer to file you will write to
char filename[name_length]; // variable to hold the name of file
char string_buffer[line_size]; // buffer to hold your text
printf("Filename: "); // prompt for filename
fgets(filename, name_length, stdin); // get filename from user
if (filename[name_length-1] == '\n') // if last char in stream is newline,
{filename[name_length-1] = '\0';} // remove it
write_file = fopen(filename, "w"); // create/overwrite file user named
if (!write_file) {printf("FAILURE");} // failed to create FILE *
// inform user how to exit
printf("To exit, enter a blank line (no spaces)\n");
// while getting input, print to file
while (fgets(string_buffer, line_size, stdin) != NULL) {
fputs(string_buffer, write_file);
if (string_buffer[0] == '\n') {break;}
}
fclose(write_file);
return 0;
}
How should I go about fixing the program? I have found next to nothing on user-terminated input being written to file.
Now if you will excuse me, I have a couple of files to delete off of my University's UNIX server, and I cannot specify them by name since they were created with convoluted filenames...
EDIT------
Like I said, I was able to use
scanf("%s", filename);
to get a working filename (without the newline char). But regardless of if I use scanf or fgets for my while loop, if I use them in conjunction with scanf for the filename, I am not able to write anything to file, as it does not enter the while loop.
How should I restructure my writing to file and my while loop?
Your check for the newline is wrong; you're looking at the last character in filename but it may be before that if the user enters a filename that's shorter than the maximum. You're then trying to open a file that has a newline in it's name.
These lines seem to be incorrect:
if (filename[name_length-1] == '\n') // if last char in stream is newline,
{filename[name_length-1] = '\0';} // remove it
You verify the name_length - 1 character,, which is 19 in your case without any regard of the introduced filename's length. So if your file name's length is less then 18 you won't replace the '\n' character at the end of your string. Obviously the file name can't contain '\n' character.
You need to get the size of you file name first with strlen() as an example.
if (filename[strlen(filename) - 1] == '\n')
{
filename[strlen(filename) - 1] = '\0';
}
(Don't forget to include the string.h header)
I hope I was able to help with my weak english.