This is the c code that I wrote to write something to a file. But when I compile it, the process terminates without getting input for the contents. What is the error?
#include <stdio.h>
#include <string.h>
void main()
{
FILE *fp;
char name[20];
char content[100];
printf("Enter file name:\n");
scanf("%s", name);
printf("Enter the content:\n");
gets(content);
fp = fopen(name, "w");
fprintf(fp, "%s", content);
fclose(fp);
}
It blew right past the gets line. Why? Because the scanf family has lots and lots of problems. Avoid them.
Specifically it tends to leave input on the buffer. In this case scanf("%s", name); read in all the text and left a newline on stdin. Then gets dutifully read that newline... and throws it out because that's how gets behaves. We can see this if we print name and content just before gets.
printf("name: '%s'\n", name);
printf("content: '%s'\n", content);
name: 'foo'
content: ''
Then your program dutifully writes nothing to the file.
Instead, use fgets to read entire lines, and sscanf to parse them. This avoids the danger of leaving input on the buffer.
printf("Enter file name:\n");
fgets(name, sizeof(name), stdin);
printf("Enter the content:\n");
fgets(content, sizeof(content), stdin);
fgets does not strip newlines, so you'll have to do that yourself. There's a variety of ways to do it.
void trim( char *string, char to_trim ) {
size_t len = strlen(string);
if( len == 0 ) {
return;
}
size_t last_idx = len -1;
if( string[last_idx] == to_trim ) {
string[last_idx] = '\0';
}
}
I prefer this approach because it only removes the newline if it's the final character.
Finally, always check your file operations. You're not checking if the fopen succeeded. If it fails for whatever reason you'll get another mysterious error. In my case the name I was using for testing already existed as a directory.
#include <string.h> // for strerror
#include <errno.h> // for errno
fp = fopen(name, "w");
if( fp == NULL ) {
fprintf(stderr, "Could not open '%s' for writing: %s.\n", name, strerror(errno));
return 1;
}
Related
I am writing a basic program to copy text to another text file. But in the console window after entering the filename from where text should be taken, the program ends and does not go further. How can I solve this problem?
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1, filename2;
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s", filename1);
infile = fopen("filename1", "r");
printf("Enter a input file name:");
scanf("%s", filename2);
outfile = fopen("filename2", "w");
if (infile == NULL || outfile == NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
char characters;
do {
characters = getc(infile);
fprintf(outfile,"%s", characters);
printf("%s", characters);
} while (!feof(infile));
fclose(infile);
fclose(outfile);
return 0;
}
There are a few problems with your program:
You are using char variables to hold names of files. These variables should be char arrays or pointers to the first char of some allocated memory.
fopen("filename2", "w") seems wrong. Although, the first argument should be a char *, you are not reading / writing the files you just asked the user to enter.
fprintf(outfile,"%s",characters) - You are using %s to print characters. This will invoke UB.
char characters - The last character of a file, the EOF character is guaranteed to fit in an int. The characters variable should be declared as an int so that it can hold the EOF character.
Here is the program that works:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
char filename1[10], filename2[10];
FILE *infile;
FILE *outfile;
printf("Enter a data file name:");
scanf("%s",filename1);
infile = fopen(filename1, "r");
printf("Enter a input file name:");
scanf("%s",filename2);
outfile = fopen(filename2, "w");
if (infile==NULL || outfile==NULL) {
printf("Problem in opening files");
exit(0);
}
printf("files opened successfully");
int characters;
/*do {
characters=getc(infile);
fprintf(outfile,"%s",characters);
printf("%s",characters);
} while(!feof(infile));
*/
while ((characters = getc(infile)) != EOF) {
fprintf(outfile, "%c", characters);
printf("%c", characters);
}
fclose(infile);
fclose(outfile);
return 0;
}
There are a number of issues.
char filename1, filename2;
This only allows filename1 and filename2 to hold a single char - not a C string. You need to reserve memory as a char array. Like:
char filename1[64], filename2[64]; // Allow 63 chars for file name
Then
scanf("%s",filename1);
is really bad as it allows the user to overflow your input buffers. Consider using fgets or at least do:
scanf("%63s",filename1); // Limit user input to 63 chars as the buffer is 64
// The "last" char is for the string termination
Then the loop:
First, characters shall be int so that you can check for EOF. Further, check directly on getc instead of using feof. And don't use %s for printing a single char to the output file - use %c. Like
int characters;
while(1) {
characters=getc(infile);
if (characters == EOF) break; // Break (aka jump out of the loop) on
// end-of-file or errors
fprintf(outfile,"%c",characters); // %c instead of %s
// or use: putc(characters, outfile)
// instead of fprintf
printf("%s",characters);
}
This is the C code I have so far. I am reading the first name and last name from the input file but the thing that is giving me trouble is to print out the other stuff.
I have to take a line like this:
Venus Jensen 33770530841 vbjensen#oqtu.edu FRNO 624-771-4676 SIJ SBE WHV TVW
and remove the extra stuff to make it like this:
vbjensen Venus Jensen (624)771-4676
My problem is that I am getting the right output but for some of the lines that(1) don't have the FRNO or something equivalent and (2) not having the # symbol, the line still shows up. For example, the lines:
Noe Richard 974927158 nirichar#bvu.edu 079-651-3667 HAVQ
Phillip Sandoval 836145561 pusandov#luu.edu OXRU 697-728-1807 LHPN GUX
These lines should not be printed since the first one does not have the FRNO equivalent and the second one does not have the # symbol. Every time I try to add the format operation to match but not save, the program sscanf function starts to mess up.
#include <stdio.h>
#include <stdbool.h>
#include <stdlib.h>
int main()
{
// Open the input file and print an error message if we're unsuccessful.
// (the error message is mostly to help you with debugging. We won't test
// this behavior).
FILE *fp = fopen("input.txt", "r");
char line[500];
if(!fp) {
printf("Can't open input file\n");
exit(1);
}
// Counting input lines, so we can report errors.
// Keep reading input lines until we reach the end-of-file.
// Write an output line or an error message for each one.
do {
int lineCount = 1;
char fName[12];
char lName[12];
//char skipNum[12];
char email[9];
//char firstNum[4];
//char secondNum[4];
//char thirdNum[5];
//printf("%c", ch);
char phone[] = "(123)123-1234";
//fscanf(fp, "%s", fName);
//fscanf(fp, "%s", lName);
//fscanf(fp, "%[1-9]", skipNum);
//fscanf(fp, "%[a-z]", email);
sscanf (line, "%11s%11s%*[ 0-9]%9[^#]%*[^0-9]%3c-%3c-%4c", lName, fName, email, &phone[1], &phone[5], &phone[9]);
//printf("Invalid line");
//printf("\n");
// exit(1);
printf("%s", line);
printf("\n");
printf("%s", email);
printf("%s", fName);
printf("%s", lName);
//printf("%s", skipNum);
//printf("%s", firstNum);
printf("%s", phone);
printf("\n");
lineCount++;
}
while (fgets(line, sizeof line, fp));
return EXIT_SUCCESS;
}
In the format string "%20s%20s%*[ 0-9]%20[^#]#%*s%20s %3c-%3c-%4c"
%20s will scan up to 20 non-whitespace characters. Ignoring leading whitespace and stopping at trailing whitespace.
%*[ 0-9] will scan spaces and digits. The asterisk, *, tells sscanf to discard the scanned characters.
%20[^#]# will scan up to 20 characters or will stop scanning at a #. Then it will try to scan a #. If the # is missing the scan will terminate early.
%*s will scan non-whitespace and discard the characters.
%20s will scan up to 20 non-whitespace characters.
%3c will ignore any leading whitespace and scan three characters.
-%3c will scan a - and then three characters. If the - is missing the scan will terminate early.
-%4c will scan a - and then four characters. If the - is missing the scan will terminate early.
If sscanf does not scan seven items, nothing will be printed.
#include <stdio.h>
#include <stdlib.h>
int main ( void) {
char line[500] = "";
int lineCount = 0;
FILE *fp = NULL;
if ( NULL == ( fp = fopen("input.txt", "r"))) {
fprintf( stderr, "Can't open input file\n");
exit(1);
}
while ( fgets ( line, sizeof line, fp)) {//read each line from the file
char fName[21];
char lName[21];
char match[21];
char email[21];
char phone[] = "(123)567-9012";
lineCount++;
if ( 7 == sscanf ( line, "%20s%20s%*[ 0-9]%20[^#]#%*s%20s %3c-%3c-%4c"
, lName, fName, email, match, &phone[1], &phone[5], &phone[9])) {
printf ( "line [%d] %s %s %s %s\n", lineCount, email, fName, lName, phone);
}
}
fclose ( fp);
return 0;
}
I am trying to repeatedly read a string from the command line and print it to a file. This is my code:
int main ()
{
FILE* fp=fopen("test.txt","w");
char* tofile[10];
while(1){
printf("cat: ");
scanf("%s",tofile);
fprintf(fp,"%s\n",tofile);
}
return 0;
}
It works just fine outside the loop. But inside, it just doesn't print.
The fprintf function returns the correct amount of characters it has to print.
Note: I know there's a similar question out there, but it hasn't been answered yet, and I hope my code can help in this matter since it's simpler.
Well first it doesn't seem that what you want is reading on the command line.
The command line what you write right when you execute your program such as:
./main things that are on the command line
What it seems you want to do is to read on the standard input.
What you should consider is to use the fgets function, as it has a limit of characters to be read, so that you can store them "safely" into a buffer, like your tofile.
As you want to read on the standard input you can use the stdin stream (which is a FILE* that is automatically created for every program)
The line goes
fgets(tofile, 10, stdin);
Your loop becoming :
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
meaning: as long as we can read on the standard input, print "cat :" and store what we just read in the file controlled by the stream pointer fp.
Some important stuff
When you try to open a stream it may fail and you should test it:
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
Right before exiting your main, you should also close the file and check if it has succeeded, like that for example:
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
The whole thing becomes:
#include <stdio.h>
#include <stdlib.h>
int main (void) {
char filename[] = "test.txt";
FILE *fp = fopen(filename, "w");
if (fp == NULL) {
fprintf(stderr, "Failed to open the file of name : %s", filename);
return EXIT_FAILURE;
}
char tofile[10];
printf("cat: ");
while (fgets(tofile, 10, stdin) != NULL) {
printf("cat: ");
fprintf(fp, "%s\n", tofile);
}
if (fclose(fp) != 0) {
fprintf(stderr, "Failed to close the file of name : %s", filename);
return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}
Improvements
I don't know if it is just a little program or it aspires to become a greater program.
In the last case you should consider using defines and not a magical number such as
#define BUFFER_MAX_SIZE 10
char tofile[BUFFER_MAX_SIZE];
while (fgets(tofile, BUFFER_MAX_SIZE, stdin) != NULL) { ... }
This helps for readability and makes the program less apt to debug when modifying such a size. Because with the define all the part of the code needing the size will still be fully functional without modifying them.
Please also keep in mind that your tofile acts as a buffer, and it's really a small buffer that can easily be overflowed.
This will work. fgets() returns the string it reads from the specified file pointer. If this string returns only a newline ("\n"), that means nothing was entered at stdin.
#include <stdio.h>
#include <string.h>
int main(void)
{
FILE *fp = fopen("test.txt","w");
// always check if fopen() == null
if (!fp) {
fprintf(stderr, "Could not write to file\n");
return 1;
}
char tofile[30];
printf("cat: ");
while (fgets(tofile, 30, stdin)) {
if (strcmp(tofile, "\n") == 0)
break;
fprintf(fp, "%s", tofile);
printf("cat: ");
}
// always fclose()
fclose(fp);
return 0;
}
Edited code.
My goal is to be able to write a string to a file and have the whole thing show up, and not just part of it. The problem is that when i check into my text file there is a few charters left off of the string that i typed in.
Here is My code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("file.txt", "w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
char comment[100];
fp=fopen("/home/matthew/Desktop/BBE.txt","w");
printf("Enter, String: ");
scanf("%s", &comment);
fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
}
And the input that i want in my text file is this:
Enter, String: Hello World
But when i check my text file i get this:
World
I am missing a word here and have no idea why, please help.
Get rid of the scanf, as it is reading in the first word of your input, so your code looks like this:
char comment[100];
fp=fopen("/home/matthew/Desktop/BBE.txt","w");
printf("Enter, String: ");
fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
You are reading the input from the user using both fgets and scanf. You don't need both. Also, in your scanf, you are passing the address of the address of the first element of the character array instead of just the address of the first element (use 'comment' instead of '&comment' in your scanf). You are also not closing the File after write. Try following:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp = fopen("/home/matthew/Desktop/BBE.txt", "w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
char comment[100];
fp=fopen("file.txt","w");
printf("Enter, String: ");
scanf("%s", comment); //Don't pass &comment. Just pass 'comment' - the addr of zeroth element.
//fgets(comment, sizeof comment, stdin);
fputs(comment,fp);
fclose(fp);
}
Why are you using two files here when you've to write the input from stdin in one of the file? Below piece of code will help you get the desired output. Better to use gets() here instead of fgets() as you're not reading input from file. Also, don't forget to close the files when you're done. Hope this helps!!
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
FILE *fp;
char comment[100] = {0};
fp=fopen("tempfile.txt","w");
if (fp == NULL)
{
printf("Error opening file!\n");
exit(1);
}
printf("Enter String: ");
gets(comment);
fwrite(comment, sizeof(comment), 1, fp) ;
fclose(fp);
return 0;
}
How i can make a new line at the end of a file to fprintf() user inputed text?
My code right now is this:
#include <stdio.h>
#include <stdlib.h>
int main()
{
int lines;
int number;
FILE *fp;
printf("Insert random number: ");
scanf("%d", &number);
fp = fopen("textfile.txt", "r");
char ch;
while((ch=fgetc(fp))!=EOF)
{
if (ch=='\n') {
lines++;
}
}
fclose(fp);
fopen("textfile.txt", "ab");
fseek(fp, lines, SEEK_SET);
fprintf(fp,"%d", number);
fclose(fp);
}
You just need to add a '\n' to the fprintf() like this
fprintf(fp,"\n%d", number)
/* ^ */
but you also need a lot of error checking, for instance fopen() returns NULL when it fails to open the file.
Your code is actually very broken, you count the lines in the file opened with "r", i.e. for reading, then you call fopen() with "ab" but discard the return value, you then fseek() the number of lines, and fseek() is for the number of characters not lines, then you write to the closed fp pointer, because
fopen("textfile.txt", "ab"); /* you don't assign the return value anywhere */
fseek(fp, lines, SEEK_SET); /* this is the same pointer you `fclosed()' */
/* ^ this will not seek to the end of the file */
fprintf(fp,"%d", number); /* here `fp' is still invalid */
Test this
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *file;
const char *filename = "textfile.txt";
printf("Insert a number: ");
if (scanf("%d", &number) != 1)
{
fpritnf(stderr, "invalid input, expected a number\n");
return -1;
}
file = fopen(filename, "a");
if (file == NULL)
{
fprintf(stderr, "cannot open %s for appending\n", filename);
return -1;
}
fprintf(file, "\n%d", number);
fclose(file);
return 0;
}
You don't need to fseek() if you open with "a" because new content is appended to the end of the file, you need a '\n' before the user input if there was no '\n' in the file or if you want to force the new value in a new line.
You don't need the "b" in the mode string, because you are writing text to the file, and on some platforms the file will have issues when you open it in a text editor.