fopen with string variable fails - c

I'm trying to make a small program that saves some information on a file, taking input from the user for the content and name of the file. For some reason, I am unable to save file_name into FILE *open.
This works when input a string as the file name; open = fopen("filename.txt","w"); but not when I try to input string as a variable. I have looked all over and cannot find an answer anywhere.
I have included stdio.h and string.h
int main (){
FILE *open;
char first_name[16],last_name[21];
char save_name[30],ext[10];
char file_name[40];
int a,b;
printf("This program will take your name and save it in a file.\n");
printf("Insert your first name:");
scanf("%s",&first_name);
printf("Insert your last name:");
scanf("%s",&last_name);
do{
printf("Insert file name with extension:");
scanf("%[^.].%s", &save_name, &ext);
//Takes filename lenght, minus the dot
a = (int)strlen(save_name)-1;
b = (int)strlen(ext);
sprintf(file_name,"%s.%s",save_name,ext);
}while(a>8 || b>3);
//This is where my problem lies...
open = fopen(file_name,"w");
if(open==NULL){
printf("File %s failed to open, shutting down...",file_name);
}
else{
fprintf(open, "%s %s",first_name,last_name);
printf("\n\nSave successful! File was saved as: %s",file_name);
}
fclose(open);
return 0;
}

The problem is that your file_name has a leading newline character in it! The newline is being added by your scanf() call with the "%[^.]" format (but I'm not entirely sure why). It seems that using %s for string input automatically removes this but %[^.] will accept all characters except . (including whitespace). Use this to fix it (skipping the newline):
scanf("\n%[^.].%s", &save_name, &ext);
Comments welcome as to where this newline comes from - it's news to me!
PS: You don't need the - 1 in your calculation of a, as the dot is never read into save_name.

Related

How do I stop a blank line from being added in this instance?

I am trying to make it so you can write a multi line message and it will store it in a file of your choosing and to be done you enter ` but when I do this at the top there is a blank line printed. How can I prevent this?
#include <stdio.h>
char filename[BUFSIZ];
char input[BUFSIZ];
FILE *file;
int main() {
printf("What do you want to name the file?\n");
scanf("%s", filename);
printf("Enter the contents. Once you are done enter `\n");
scanf("%[^`]s", input);
file = fopen(filename, "w");
fprintf(file, "%s", input);
fclose(file);
}
Code:
/* multi.c
*/
#include <stdio.h>
#define BUFSIZE 1024
int main(void)
{
char filename[BUFSIZE];
char input[BUFSIZE];
FILE *fp;
/* using fprintf(stderr... is better because of output buffering.
* This way, we don't need the '\n' at the end for the string to
* appear in the console. You could also use:
*
* printf("Filename: "); fflush(stdout);
*/
fprintf(stderr, "Filename: ");
/* When you press ENTER, a '\n' will be created at the stdin buffer.
* However, this scanf() will NOT read it into #filename. So the '\n'
* is left in the buffer...
*/
scanf("%s", filename);
fprintf(stderr, "Contents: ");
/* when you call scanf() again, the old '\n' is the first character
* it reads into #input. So, to discard that, simply add a space
* before the % - this ignores whitespaces (tabs, newlines, spaces)
*/
scanf(" %[^`]", input);
/* open the file, check for errors */
if(!(fp = fopen(filename, "w"))) {
perror("fopen");
return -1;
}
/* print the contents to the file */
fprintf(fp, "%s", input);
/* clean up */
fclose(fp);
return 0;
}
This is the execution:
$ ./multi
Filename: hello.txt
Contents: My name is Enzo
I am writing some multiline content to a file
And then I'm posting it to
Stack Overflow.`
And this is hello.txt
$ cat hello.txt
My name is Enzo
I am writing some multiline content to a file
And then I'm posting it to
Stack Overflow.$
Notice that after the last line my terminal character $ is there. This is because we end the input with a ` character, and not with a new line. Therefore, there's no new-line at the end of the file.
int main() {
printf("What do you want to name the file?\n");
scanf(" %s", filename);
printf("Enter the contents. Once you are done enter `\n");
scanf(" %[^`]s", input); //do not forget to put a space in scanf
file = fopen(filename, "w");
fprintf(file, " %s", input); //try to make a space in there or if it doesn't work
fclose(file); //than try " %[^\n] but this is a little risky depends in the way you want use the code.
//if none of these works than try this other way "\b %s"
}
always put a white space before " %s" or other text format specificators because, you may have problems...
The reason is that when you add a scanf() directely after a printf() sometimes it scanf takes as part of the string that it has to read even the last character printed by printf(), depending in what kind of characters they are (mostly white spaces, \n, \t). It's a little bit weird but it happened me a lot of times in the past.
I think that the problem is in there
scanf(" %[^`]s", input); //put that white space
first try to make that space here and I think it will work, but if it doesn't try the others left in comments. One of them will definitively work.

Check if the user input an empty string in C using char array

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");
}
}

Reading whitespace when asking user input C

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.)

How to add multiple lines in text file

I am trying to write a program which can display the contents of the file then append the content dynamically by user to a text file in C.
Below is the code, but somehow it is working for single line input and not for multi-line input even in the loop.
fobj=fopen("test3.txt","a");
if (fobj==NULL)
{
printf("Error opening the file. ");
exit(0);
}
int contd;
char buff1[120];
char *chptr;
do
{
printf("Enter line : \n");
gets(buff1);
fputs(buff1,fobj);
printf("Enter Continuation code : ");
scanf("%d",&contd);
}while(contd!=0);
You are facing the typical stdin issue. You can use fflush(stdin); before gets, should work.
From gets:
The newline character, if found, is not copied into str.
So you will have to add the new line manually:
gets(buff1);
strcat(buff1, "\n");

Struggling to understand file pointers?

Main description of the problem below, where it happens. But simply, I cannot figure out why I get error messages after asking
if (outf!=NULL){
printf("Output file already exists, overwrite (y/n):");
scanf("%c",yn);
}
Where outf is a file pointer to an existing file. Please read description halfway through code.
#include <stdio.h>
#include <stdlib.h>
#include <float.h>
#include <string.h>
int main() {
/* Declare file pointer */
FILE *inf;
FILE *outf;
int linenumber,linecounter=0,linepresent;
char filename[21];
char detail[21];
char linedetail[21];
char outfilename[21];
char letter,yn='y';
int position;
/*INPUT DETAILS Ask user for file name and line number*/
printf("Please enter an input filename and a linenumber: ");
//scan filename to char string and line number to int variable
scanf("%s %i",&filename,&linenumber);
/*OUTPUT DETAILS Ask user for file name, letter & position, etc*/
printf("Please enter an output filename, a letter and a position:");
scanf("%s %c %i",&outfilename,&letter,&position);
/* Open file for reading */
inf=fopen (filename,"r");
outf=fopen(outfilename,"r");
/*check that file exists*/
if (inf!=NULL) {
Up until here everything works fine!
Then I try to find out if the outf file already exists. If outf points to an existing file, it DOES print "Output file already exists, overwrite (y/n):"
HOWEVER, as soon as it prints this I get error windows opening! This is probably an extremely rookie mistake - I'm still learning C. If there is no such file the program completes normally and bypasses the if statement okay.
if (outf!=NULL){
printf("Output file already exists, overwrite (y/n):");
scanf("%c",yn);
}
if (yn=='y'){
/*keep reading to end of file*/
while (feof(inf)==0) {
linecounter++;
/*read each line and store the line number in detail[WORDS GO HERE]*/
fscanf (inf,"%s", &detail);
/*If we reach the line selected by the user*/
if (linecounter==linenumber){
strcpy(linedetail,detail);
linepresent=1;
}
}
if (linepresent==0) {
printf("File only contains %i lines",linecounter);
}
} else {
exit(1);
}
} else {
printf("Input file not found");
}
printf("%s",linedetail);
/* close the file */
fclose(inf);
fclose(outf);
return (0);
}
First, already mentioned problems: You're opening the output file in reading mode. To open it for writing:
outf=fopen(outfilename,"w"); /* Note the "w". */
Also, scanf() accepts pointers to variables, not their values, so if you write scanf("%c", yn);, you will give scanf the character y as a pointer, which is nonsense. You need to do it like this: scanf("%c", &yn);.
Even if you fix these, however, your program won't do what you expect. If the file you're trying to open for writing doesn't exist, fopen() won't return NULL, it will create a new file. Your code will always overwrite the output file if it exists. NULL is returned only if fopen couldn't open/create the file (e.g. you didn't have the permissions to do it), and you should handle it like this:
outf=fopen(outfilename, "w");
if(outf == NULL) {
perror("Failed to open output file: ");
fclose(inf); /* Don't leave files opened. It's bad form. */
exit(1);
}
/* Open succeeded, do your stuff here. */
Note that no else block is needed after the if, because exit() ends the program immediately.
Also, there is no such thing as a "pointer to a file". FILE is just a structure that represents an open file.
http://www.cplusplus.com/reference/clibrary/cstdio/fopen/
You are open the output file with the read flag. Try changing it to "w".
outf=fopen(outfilename,"w");
Although it is worth noting writing to a file opened with "w" will whack the old file. use "a" to append to the file.
You should pass the address of yn to scanf function.
scanf("%c", &yn);

Resources