Can't open a file using fopen() - c

I'm writing a program that simulates a platform where users can register. In register function I ask the user for his username and the program should create a new file with username as file name to store his password and other data for other functions. Problem here is that fopen returns NULL which means that it can't be created.
void Register()
{
char name[11];
char password[11];
char aux[11];
system("cls");
FILE *fp=fopen("Users.txt","a+"); //I've created this .txt, just has one user which is admin
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
printf("Write a new username (no more than 10 characters, no spaces) ");
fflush(stdin);
fgets(name,sizeof(name),stdin);
getchar();
do{
if((fgets(aux,sizeof(aux),fp))!=NULL){ //Checks is reading lines
if ((strcmp(name,aux))==0){ //Username already exists
printf("\nUsername already exists, try another: ");
fflush(stdin);
fgets(name,sizeof(name),stdin);
rewind(fp); //Takes pointer to the beginning
}
}
}while(!(feof(fp)));
fseek(fp,0,SEEK_END); //Takes pointer to end
fprintf(fp,"%s",name);
fclose(fp);
fp=fopen(name,"w"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
printf("\nChoose a password(no more than 10 characters): ");
fflush(stdin);
fgets(password,sizeof(password),stdin);
getchar();
fprintf(fp,"%s\n",name);
fprintf(fp,"%s",password);
fclose(fp);
printf("\nUser successfully registered\nName: %s\nPassword: %s",name,password);
getchar();
}
I've already tried with another method. For example, use strcpy() to copy name to a new array and then strcat() to add ".txt" but it doesn't work either. Like this:
[...]
char aux2[20];
strcpy(aux2,name);
strcat(aux2,".txt");
fp=fopen(aux2,"w"); /*FAILS TOO */
if (fp==NULL){
printf("\nFile cant be opened");
getchar();
return;
}
Can't figure out what is going wrong. Hope you can help me

List of problems:
You have not declared fp (at least in shown code) before trying to use it.
Change line to:
FILE *fp=fopen("Users.txt","a+");
You have not declared nombre. Add line:
char nombre[11];//to match size of name
(Or, you may have meant to use name?)
Everywhere it exists in your code, comment out the line:
//fflush(stdin);
Change the line
fp=fopen(name,"w"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/
to:
fp=fopen(name,"w+"); /*THIS IS WHERE IT FAILS, RETURNS NULL*/

the question was not clear about the actual format of the data within the file. So I decided to use a format of name password for each line of the file.
Here is a version of the code that cleanly compiles and performs the desired function.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void Register( void );
void Register( void )
{
char name[11];
char password[11];
char aux[11];
system("cls");
printf("Write a new username (no more than 10 characters, no spaces) ");
if( !fgets(name,sizeof(name),stdin) )
{
fprintf( stderr, "fgets for user name failed" );
exit( EXIT_FAILURE );
}
// implied else, fgets successful
// code should remove trailing new line, if any
char *newline;
if( (newline = strchr( name, '\n' ) ) )
{
*newline = '\0';
}
FILE *fp=fopen("Users.txt","a+"); //I've created this .txt, just has one user which is admin
if ( !fp)
{
perror("fopen for Users.txt for read/write failed");
getchar();
exit( EXIT_FAILURE );
}
// implied else, fopen successful
while( fgets(aux,sizeof(aux),fp) )
{ //Checks is reading lines
// separate out the name field
char *token = strtok( aux, " " );
if( token )
{
if ((strcmp(name,aux))==0)
{ //Username already exists
printf("\nUsername already exists, try another: ");
rewind(fp); //Takes pointer to the beginning
}
}
}
// name not already in file
printf("\nChoose a password(no more than 10 characters): ");
if( !fgets(password,sizeof(password),stdin) )
{
perror( "fgets for password failed" );
fclose( fp ); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fgets successful
//remove trailing newline
if( (newline = strchr( password, '\n' ) ) )
{
*newline = '\0';
}
fprintf(fp,"%s %s\n",name, password);
fclose(fp);
printf("\nUser successfully registered\nName: %s\nPassword: %s",name,password);
getchar();
} // end function: Register

Just figured it out, I had to change the line
if((fgets(aux,sizeof(aux),fp))!=NULL){ //Checks is reading lines
And instead use fscanf() just like this:
if((fscanf(fp,"%s",&aux)==1){ //Checks if is reading a string (a line)

Related

How can I copy some strings from file to another using c programming

I have this code:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
char buf[100];
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
printf("%s\n", buf);
printf("Create a file \n");
scanf("%s", filename);
fptr2 = fopen(filename, "w");
if (fptr2 == NULL)
{
printf("Cannot open file %s \n", filename);
exit(0);
}
c = fgetc(fptr1);
while (c != EOF)
{
fputc(c, fptr2);
c = fgetc(fptr1);
}
printf("\nContents copied to %s", filename);
fclose(fptr1);
fclose(fptr2);
return 0;
}
}
It coppies full content from one file to another. I need to copy only strings that have 5 as the last character (3 column)
For example Data.txt looks like that:
Alex 10B 4
John 10A 3
Kate 10C 5
In file that I will create during execution has to be coppied only Kate 10C 5 string. I've been trying for hours but I don't know how to do this. Can you help me?
In the end of each line there is a newline character, (\n) you can use that to read line by line and copy only the ones that you want:
FILE* dest = fopen("out.txt", "w+"); // supressed null check for simplicity
char buf[100];
char* char_to_find;
// parse line by line
while (fscanf(ptr, " %99[^\n]", buf) == 1){
char_to_find = buf;
// reach the end of the line
while(*char_to_find){
char_to_find++;
}
//move one back
char_to_find--;
// if it's 5 save, if not move on
if(*char_to_find == '5' && *(char_to_find - 1) == ' '){
fputs(buf, dest);
}
}
Live demo
The problem is that the function call
while (fscanf(ptr,"%*s %*s %s ",buf)==1)
consumes the input from the input stream, so that it is no longer available for copying. You are only saving the contents of the last field, but all other data is lost.
I suggest that you read one line at a time into a memory buffer, by calling the function fgets in a loop. That way, you will process one line of input per loop iteration, and will be saving the contents of the entire line.
In every loop iteration, you can use sscanf on this memory buffer to determine whether the third field has the desired value, and if it does, then you copy the entire line to the output file. Otherwise, you do nothing and proceed to the next line (i.e. the next loop iteration).
char line[100];
//process one line of input per loop iteration
while ( fgets( line, sizeof line, input_file ) != NULL )
{
char third_field[20];
if (
//third field was successfully extracted
sscanf( line, "%*s%*s%19s", third_field ) == 1
&&
//third field contains the string "5"
strcmp( third_field, "5" ) == 0
)
{
//copy entire line to output file
fputs( line, output_file );
}
}
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE* ptr = fopen("data.txt","r");
char filename[100];
if (ptr==NULL)
{
printf("no such file.");
return 0;
}
printf("Create a file \n");
scanf("%s", filename);
FILE* dest = fopen(filename, "w+"); // check for null like above
char buf[100];
char* char_to_find;
while (fscanf(ptr,"%99[^\n] ", buf) == 1){
char_to_find = buf;
while(*char_to_find != 0){
char_to_find++;
}
char_to_find--;
if(*char_to_find == '5'){
printf("%s\n", buf); // test ptint
fputs(buf, dest);
}
}
}

C code to write content to a file not working

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

Saving struct to a file in C

In my assignment I was given two functions to write
int openFileFromConsole(FILE *fp)
It takes an empty file pointer as input to the function using call by reference. And updates the pointer to point to the appropriate HDD address. IMPORTANT: Later, it asks the user through the console to provide the name and also asks for the file open type: "w", "r", "a" and UPDATES the file pointer. It returns 1 if succeeded, or 0 if fails.
void saveStudentGradeInfoTofile(FILE *fp)
This function gets the student info and saves it first into the student data-type (which is struct but disguised using typedef) then saves it to file. The student information is being provided by the register through the console. This takes the file pointer by reference as input and update the file using fprint.
This program is supposed to open a file through console depending on the user input then collect information and store them to a struct and save it to that file.I have written the two functions(correctly I think?).But I am having a hard time implementing them to main() since the first one is an int type function.Any help would be appreciated.
typedef struct student {
char name[50];
char id [20];
int score;
}student;
int openFileFromConsole(FILE *fp);
void saveStudentGradeInfoTofile(FILE *fp);
int main()
{
return 0;
}
int openFileFromConsole(FILE *fp){
char filePath[100],fileOpenType[10];
printf("Enter Path name: ");
scanf("%s", filePath);
printf("Enter file open type w, r or a: ");
scanf("%s", fileOpenType);
fp = fopen(filePath,fileOpenType);
if(fp != NULL) {
printf("File has been opened");
return 1;
}
else printf("File not found");
return 0;
}
void saveStudentGradeInfoTofile(FILE *fp){
int numOfStudent ;
student s[100];
printf ("Get the number of students :");
scanf("%d",&numOfStudent);
for(int i = 0; i < numOfStudent; i++) {
printf("\nEnter ID number:");
scanf(" %s",s[i].id);
printf("Enter name: ");
scanf("%s,",s[i].name);
printf("Enter score: ");
scanf("%d",&s[i].score);
fprintf(fp,"id : %s, Name: %s, score =%d\n",s[i].id,s[i].name,s[i].score);
printf("\n");
}
}
the posted code has a few problems.
it does not follow the axiom: only one statement per line and (at most) one variable declaration per statement. The result is the code is much more difficult to understand, debug, maintain.
The calls to system functions need to have their returned values checked to assure the operation was successful.
To modify where a pointer, located in the calling function, points, the pointer must be passed as a 'pointer to a pointer'.
when calling any of the scanf() family of functions, when using the '%s' input conversion specifier, always include a MAX CHARACTERS modifier that is 1 less than the length of the input buffer, so the user cannot overrun the input buffer. Such overrun results in undefined behavior and can lead to a seg fault event.
when using the '%s' input conversion specifier, insert a space before the specifier to consume any leading 'white space', like any newline sequence.
always cleanup when exiting a program. Do not leave the cleanup to the OS.
when working with numeric values that will never be less than 0, it is best to use size_t rather than int
The posted code is never reading from the student grade info file, so should never be opened with r
the 'mode' in a call to fopen() is always a string, even if it is only a single char, so needs to be written as "w" not just a w
the code contains lots of 'magic' numbers. 'magic' numbers are numbers with no basis. Such numbers make understanding, debugging, etc much more difficult than necessary. Suggest using an enum statement or #define statements to give those 'magic' numbers meaningful names, then use those meaningful names throughout the code.
for ease of readability and understanding, consistently indent the code. indent after every opening brace '{'. unindent after every closing brace '}'. Suggest using 4 spaces for each indent level as that is visible even with variable width fonts.
it is a poor programming practice to combine a 'struct' definition with a 'typedef'. code them separately.
when posting code, include the needed header file statements, so we do not have to guess what your code actually uses.
for ease of readability and understanding, separate code blocks (for, if, else, while, do...while, switch, case, default) via a single blank line. Separate functions by 2 or 3 blank lines (be consistent).
While modern compilers will handle the duplication of names, as modern compilers keep the struct names in a separate namespace from the typedef names, it is a poor programming practice that easily leads to confusion. Suggest keeping names unique (although that was not followed in this answer.
Here is a possible implementation of the desired functionality:
#include <stdio.h> // fopen(), fclose(), perror(), FILE
#include <stdlib.h> // exit(), EXIT_FAILURE
enum {
MAX_NAME_LEN =50,
MAX_ID_LEN =20,
MAX_PATH_LEN =100,
MAX_TYPE_LEN =10,
MAX_NUM_STUDENTS =100
};
struct student
{
char name[ MAX_NAME_LEN ];
char id [ MAX_ID_LEN ];
int score;
};
typedef struct student student;
int openFileFromConsole(FILE **fp);
void saveStudentGradeInfoTofile(FILE *fp);
int main( void )
{
FILE * fp = NULL;
int openStatus = openFileFromConsole(&fp);
if( 0 == openStatus )
{
saveStudentGradeInfoTofile( fp );
}
fclose( fp );
return 0;
} // end function: main
int openFileFromConsole(FILE **fp)
{
char filePath[ MAX_PATH_LEN ];
char fileOpenType;
printf("Enter Path name: ");
if( 1 != scanf("%100s", filePath) )
{
perror( "scanf for file path failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter file open type w, r or a: ");
if( 1 != scanf(" %c", &fileOpenType) )
{
perror( "scanf for file open type failed" );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
char buffer[ MAX_TYPE_LEN ];
buffer[0] = '\"';
buffer[1] = fileOpenType;
buffer[2] = '\"';
buffer[3] = '\0';
*fp = fopen(filePath, buffer);
if( *fp )
{
return 1;
}
else
{
perror( "fopen failed" );
return 0;
}
} // end function: openFileFromConsole
void saveStudentGradeInfoTofile(FILE *fp)
{
size_t numOfStudent;
student s[ MAX_NUM_STUDENTS ];
printf ("Get the number of students :");
if( 1 != scanf("%lu",&numOfStudent) )
{
perror( "scanf for number of students failed:" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
for( size_t i = 0; i < numOfStudent; i++)
{
printf("\nEnter ID number:");
if( 1 != scanf(" %19s",s[i].id) )
{
perror( "scanf for student ID failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter name: ");
if( 1 != scanf(" %49s,",s[i].name) )
{
perror( "scanf for student ID failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
printf("Enter score: ");
if( 1 != scanf("%d",&s[i].score) )
{
perror( "scanf for student Score failed" );
fclose( fp );
exit( EXIT_FAILURE );
}
// implied else, scanf successful
fprintf(fp,"id : %s, Name: %s, score =%d\n",
s[i].id,
s[i].name,
s[i].score);
printf("\n");
} // end while
} // end function: saveStudentGradeInfoToFile
Just in case you want to pass the file path as an argument to your program
int main(int c /* argument counter */, char *v[] /*argument list */)
{
FILE *fp;
if(c >= 2) {
char *path = v[1]; /* this is the second argument (the first one, v[0], is the program's name): ./foo myfile.txt */
fp = fopen(path, "your mode goes here");
/* ... */
}
}

Reading/writing txt strings

I'm trying to learn how to manipulate txt files in C at the moment. This program should read in population.txt (http://pastebin.com/Q5fNRuJG), find the highest population and display it, make a file with populations of greater than 1 million, make a file with all the irish cities, and print the total population. It only creates empty files, and prints the total population (now also prints most populous city). Can anyone help?
The program (compiled in Borland):
//Program that filters and processes data with fscanf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
main()
{
FILE *fp;
FILE *ireland;
FILE *mmplus;
int pop;
int highest_pop=0;
char country[50];
char city[50];
int total_pop=0;
fp = fopen("population.txt","r");
ireland = fopen("ireland_pop.txt","w");
mmplus = fopen("greater_than_1MM.txt","w");
//Checking if the file opened correctly
if (fp==NULL)
{
printf("Cannot open file.\n");
exit(1);
}//End if
//Scanning fp row by row
while (fscanf(fp, "%s" "%s" "%i", country, city , &pop) != EOF)
{
//Getting the total population
total_pop=total_pop+pop;
//Storing the highest pop
if (pop > highest_pop)
{
highest_pop=pop;
}//End if
//Finding 1 million+ cities
if(pop>=1000000)
{
fprintf(mmplus,"%s %s %d\n",country,city,pop);
}//End if
//If the city is in Ireland
if (strcmp("ireland",country) == 0)
{
fprintf(ireland,"%s %s %d\n",country,city,pop);
}//End if
}//End while
rewind(fp); //Fix 1
while (fscanf(fp, "%s" "%s" "%d", country, city , &pop) != EOF)
{
//Finding the city with the highest population
if (pop == highest_pop)
{
printf("The city with the highest population is %s, %s, with a population of %d",city, country, pop);
}//End if
}//end while
printf("The total population of all the cities is %d.",total_pop);
getchar();
fclose(fp);
fclose(ireland);
fclose(mmplus);
}
The first time I ran your program I got empty files. The second time I ran it I got correct output. The third time I got one correct file and one incorrect file.
I think I may have typed ctrl-C to end the program. So I made a couple of changes to the last few lines of the program - adding newline to the output, and closing the files before waiting for input. After that, it works every time, but I can't explain everything.
fclose(fp);
fclose(ireland);
fclose(mmplus);
printf("The total population of all the cities is %d.\n",total_pop);
getchar();
return 0;
here is one way to implement the algorithm
//note: the system function: perror()
// outputs the strerror() message,
// the first parameter text, etc
//Program that filters and processes data with fgets() and sscanf()
#include <stdio.h>
#include <stdlib.h>
#include <string.h> // strcpy(), strlen()
#include <unistd.h> // unlink()
int main()
{
FILE *fp = NULL; // input
FILE *ireland = NULL; // list irish cities
FILE *mmplus = NULL; // list cities > 1million population
int pop;
char country[50];
char city[50];
int total_pop=0;
int maxPopulation = 0;
char maxPopulationCity[50] = {'\0'};
char maxPopulationCountry[50] = {'\0'};
char buffer[200]; // input work area
if( NULL == (fp = fopen("population.txt","r") ) )
{ // then, fopen failed
perror( "fopen for population.txt failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (ireland = fopen("ireland_pop.txt","w") ) )
{ // then, fopen failed
perror( "fopen for ireland_pop.txt failed" );
fclose(fp); // cleanup
exit( EXIT_FAILURE );
}
// implied else, fopen successful
if( NULL == (mmplus = fopen("greater_than_1MM.txt","w") ) )
{ // then, fopen failed
perror( "fopen for greater_than_1MM.txt failed" );
fclose(fp); // cleanup
fclose(ireland);
unlink("ireland_pop.txt");
exit( EXIT_FAILURE );
}
// implied else, fopen successful
//Scanning fp row by row
while ( fgets( buffer, sizeof buffer, fp ) )
{
// this code makes the following assumptions
// 1) city is all one word
// (I.E, no 'st paul'
// 2) country is all one word and 'ireland' is always lower case
// (I.E. no 'Ireland' and no 'United States'
// 3) pop contains no ',' and is always positive
// 4) data item delimiters are only ' ', \t
if( 3 != sscanf(buffer, " %s %s %i", country, city , &pop) )
{
//calculate the total population
total_pop += pop;
//Storing the highest pop found so far
if (pop >maxPopulation)
{
maxPopulation=pop; // save new largest population
strcpy( maxPopulationCity, city ); // save new city
strcpy( maxPopulationCountry, country ); // save new country
}//End if
//Finding 1 million+ cities
if(pop>=1000000)
{
fprintf(mmplus,"%s %s %d\n",country,city,pop);
}//End if
//If the city is in Ireland
if (strcmp("ireland",country) == 0)
{
fprintf(ireland,"%s %s %d\n",country,city,pop);
}//End if
if( buffer[strlen(buffer)-1] != '\n' )
{ // then, input line to long for buffer[]
// read chars until newline consumed
while( '\n' != getchar() ) ;
}// end if
} // end if
}//End while
printf("The city with the highest population is %s, %s, with a population of %d",
maxPopulationCity,
maxPopulationCountry,
maxPopulation);
printf("The total population of all the cities is %d.",total_pop);
getchar();
fclose(fp);
fclose(ireland);
fclose(mmplus);
return(0);
} // end function: main

Writing to a text file from another text file line by line in c

I'm trying to write to a the text file fileout a line at a time from another file, file_in1, which is defined globally. I'm getting errors from the code bellow and I don't know why, If someone could figure out why that'd be great. Thanks!
void output()
{
FILE *fileout;
char line[40];
file_in1 = fopen(filename1, "r");
printf("Please enter the name of the output file: ");
scanf("%s", filename); //Reads filename
fileout = fopen(filename, "w");
if (fileout == NULL) {
printf("(Ensure the file is located in the project \n file folder and has the .txt extension) \n");
output();
}
while (fgets(line, 90, file_in1) != NULL) //Looks through characters until end of the file
{
fputs(line, fileout);
}
}
You declare
char line[40];
but later do
// v--- 90?
while (fgets(line, 90, file_in1) != NULL)
line cannot hold 90 characters. Either make line larger or read fewer characters.
the following code
compiles cleanly
does proper error checking
properly reads in the output file name
does not cause undefined behaviour (leading to a seg fault event)
I.E. it limits the number of characters read by fgets()
-
void output()
{
FILE *fileout;
char line[40];
//file_in1 = fopen(filename1, "r"); // <-- always check results
if( NULL == (file_in1 = fopen(filename1, "r") ) )
{ // fopen failed
perror( "fopen failed for input file" ); // writes failure details to stderr
exit( EXIT_FAILURE );
}
// implied else, fopen successful for input file
printf("Please enter the name of the output file: ");
//scanf("%s", filename); //Reads filename // <-- always check return code
// and allow for leaidng white space skipping
if( 1 != scanf( " %s", filename) )
{ // scanf failed
perror( "scanf failed for output file name" ); // writes failure details to stderr
}
// implied else, scanf for output file name successful
//fileout = fopen(filename, "w");
//if (fileout == NULL) // <-- always place the literal on the left to enable compiler to catch certain syntax errors
if( NULL == (fileout = fopen(filename, "w")))
{ // then, fopen failed
perror( "fopen failed for output file" ); // writes failure details to stderr
printf("(Ensure the file is located in the project \n file folder and has the .txt extension) \n");
// output(); <-- the program failed, do not continue and certainly not recursively
exit( EXIT_FAILURE );
}
// implied else, fopen successful for output file
//while (fgets(line, 90, file_in1) != NULL) //Looks through characters until end of the file
// <-- line is only defined as 40 characters
while( NULL != fgets(line, sizeof(line), file_in1))
{
fputs(line, fileout);
}
} // end function: output

Resources