i have a c project and i have serious problem , i want to open file and replace line number nb (nb is an int) with "*" . this is my code could some one help me please ? it show me the word i want to replace that's mean that the pointer is pointing on the wanted line but nothing happen .help me please
#include <stdio.h>
int main( void )
{
FILE * f;
char ch[1024];
int i, nb;
i = 0;
scanf( "%d", &nb ) ;
f = fopen( "dict.txt", "r+t" );
while( i < nb )
{
fscanf( f, "%s", ch ) ;
i++;
}
printf( "%s", ch );
fprintf( f, "%s", "****" );
fclose( f );
}
You've opened the file for reading and writing. According to the MSDN man page for fopen (I am assuming from the r+t mode on the file that you are using Visual Studio):
When the "r+", "w+", or "a+" access type is specified, both reading and writing are allowed (the file is said to be open for "update"). However, when you switch from reading to writing, the input operation must encounter an EOF marker. If there is no EOF, you must use an intervening call to a file positioning function. The file positioning functions are fsetpos, fseek, and rewind.
Some other things to keep in mind:
When fscanf reads a string with %s, it reads only one word at a time, not a whole line. It is easier to read whole lines of input with fgets than with fscanf.
A file consists of a stream of bytes. If the line you want to replace is 47 characters long, then fprintf(f, "%s", "****") will only replace the first four bytes in the line.
That means that if you want to replace line #nb, you will need to read in the line, figure out how long it is, then seek back to the beginning of the line and print out the correct number of asterisks.
Try something like this instead:
#include <stdio.h>
#include <string.h>
int main()
{
FILE * f;
char ch[1024];
int i,nb ;
fpos_t beginning_of_line;
i=0;
scanf("%d",&nb) ;
f = fopen("dict.txt", "r+t");
while (i<nb)
{
fgetpos(f, &beginning_of_line);
fgets(ch, 1024, f);
i++;
}
fseek(f, beginning_of_line, SEEK_SET); // return to beginning of line
for (i = 0; ch[i] != '\n'; ++i) {
fputc('*', f);
}
fclose(f);
}
Related
there is very long "dict.txt" file.
the size of this file is about 2400273(calculated by fseek, SEEK_END)
this file has lots of char like this 'apple = 사과'(simillar to dictionary)
Main problem is that reading file takes very long time
I couldn't find any solution to solve this problem in GOOGLE
The reason i guessed is associated with using fgets() but i don't know exactly.
please help me
here is my code written by C
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main() {
int line = 0;
char txt_str[50];
FILE* pFile;
pFile = fopen("dict_test.txt", "r");
if (pFile == NULL) {
printf("file doesn't exist or there is problem to open your file\n");
}
else {
do{
fgets(txt_str, 50, pFile);;
line++;
} while (txt_str != EOF);
}
printf("%d", line);
}
Output
couldn't see result because program was continuosly running
Expected
the number of lines of this txt file
Major
OP's code fail to test the return value of fgets(). Code needs to check the return value of fgets() to know when to stop. #A4L
do{
fgets(txt_str, 50, pFile);; // fgets() return value not used.
Other
Line count should not get incremented when fgets() returns NULL.
Line count should not get incremented when fgets() read a partial line. (I. e.) the line was 50 or longer. Reasonable to use a wider than 50 buffer.
Line count may exceed INT_MAX. There is always some upper bound, yet trivial to use a wider type.
Good practice to close the stream.
Another approach to count lines would use fread() to read chunks of memory and then look for start of lines. (Not shown)
Recommend to print a '\n' after the line count.
int main(void) {
FILE* pFile = fopen("dict_test.txt", "r");
if (pFile == NULL) {
printf("File doesn't exist or there is problem to open your file.\n");
return EXIT_FAILURE;
}
unsigned long long line = 0;
char txt_str[4096];
while (fgets(txt_str, sizeof txt_str, pFile)) {
if (strlen(txt_str) == sizeof txt_str - 1) { // Buffer full?
if (txt_str[sizeof txt_str - 1] != '\n') { // Last not \n?
continue;
}
}
line++;
}
fclose(pFile);
printf("%llu\n", line);
}
fgets returns NULL on EOF.
You are never assigning the result of
fgets(txt_str, 50, pFile);
to txt_str, your program never sees the end of the file and thus enters an endless loop.
try something like this:
char* p_str;
do{
p_str = fgets(txt_str, 50, pFile);
} while (p_str != NULL);
First of all I am new to files in c, so it may be a simple question,
however I still didn't find a solution:
let's say that's the content of my file:
99
blah blah
...
...
I want to scan only the number from the beginning (it is always in a separate line)
My question is how to make it take the number (99) as one number and stop scanning.
int main(){
FILE* fp = fopen(file_name, "r");
int integer;
...
fclose(fp);
printf("%d", integer);
}
output for the file example:
99
-the nuber can be between 1 and 100-
I want to scan only the number from the beginning (it is always in a separate line).
That's a good hint, suggesting a line by line parsing of the input. You can use a combination of fgets(1) and sscan(2) to read that number.
fgets will read up to a certain number of character from a stream and store those character into a buffer. If it finds a newline, it stops reading, store the newline into the buffer followed by the null-terminator. Otherwise it only adds the terminator. If it fails, it returs a NULL pointer.
sscanf works basically like scanf or fscanf, but it reads from a character array, not from a stream.
It's also better to always check the return value of those library function.
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_SIZE 1024
int main(void)
{
char const *file_name = "data.txt";
FILE *in_file = fopen(file_name, "r");
if (!in_file) {
fprintf(stderr, "Error while reading \"%s\": %s", file_name, strerror(errno));
return EXIT_FAILURE;
}
char buffer[BUF_SIZE];
int number = 0;
while( fgets(buffer, BUF_SIZE, in_file) ) {
if ( sscanf(buffer, "%d", &number) == 1 ) {
if ( 0 < number && number < 100 ) {
printf("%d", number);
break;
}
}
}
fclose(in_file);
return EXIT_SUCCESS;
}
Example.
Some references of the functions used in the previous snippet
1) fgets: man-pages or cppreference.
2) sscanf: man-pages or cppreference
Why not use scanf? (fscanf to be more precise):
On success, the function returns the number of items of the argument
list successfully filled.
(source: cppreference)
So just check how many values did you read, if 0 that means it's not a number so you can just skip that string, for that you can use "%*" prefix to ignore the data.
You also said:
I want to scan only the number from the beginning (it is always in a
separate line)
so after you read the number just skip the whole line with "%*[^\n]" (reads
data until a new line symbol is encountered)
int num;
int scanReturn;
FILE* f = fopen("file.txt", "r");
...
do {
scanReturn = fscanf(f, "%d", &num);
if(scanReturn == 0)
{
scanReturn = fscanf(f, "%*s");
}
else if(scanReturn != EOF)
{
fscanf(f, "%*[^\n]");
printf("%d, ", num);
}
} while(scanReturn != EOF);
fclose(f);
I'm having some problems with this little function that can read a file:
void ReadFile(char *name) {
FILE *fr;
int lenght, i;
fr = fopen(name, "r"); //Open the file reader
fseek(fr, 0, 2); //Set the pointer at the EOF
lenght = ftell(fr); //Read the ending position
printf("\nDEBUG lenght:%d\n", lenght);
fseek(fr, 0, 0); //Return at the beginning of the file
printf("File read:\n\n");
for (i = 1; i <= lenght; i++) {
printf("%c", getc(fr));
fseek(fr, i, 0);
}
fclose(fr);
}
This is the file that it reads:
qwerty
asdfgh
zxcvbn
But this is the output of the program:
DEBUG lenght:24
File read:
qwerty
asdfgh
zxcvbn
It is basically reading an extra "\n" when there is one before.
Any ideas of why the code doesn't work?
Thanks
If you open a file in text mode (as you do), then a call to fseek may only contain offset values that have been previously retrieved by an ftell function (cf, for example, cppreference/fseek):
If the stream is open in text mode, the only supported values for
offset are zero (which works with any origin) and a value returned by
an earlier call to ftell on a stream associated with the same file
(which only works with origin of SEEK_SET).
In your for-loop, however, you are passing the value of i, which is not retrieved by ftell.
Besides that, your fseek in the loop is superflous, as fgetc moves the read pointer forward anyway. So for (i = 1; i <= lenght; i++) { printf("%c", getc(fr)); } should do the job.
the following proposed code:
cleanly compiles
performs the desired functionality
properly checks for errors
and now, the proposed code:
#include <stdio.h> // EOF, fopen(), getc(), putc() fclose() puts() perror()
#include <stdlib.h> // exit(), EXIT_FAILURE
// prototype
void ReadFile(char *filename);
void ReadFile(char *filename)
{
FILE *fp = fopen( filename, "r" );
if( !fp )
{
perror( "fopen failed" );
exit( EXIT_FAILURE );
}
// implied else, fopen successful
puts("File read:\n");
int ch;
while( (ch = getc( fp )) != EOF )
{
putchar( ch );
}
fclose(fp);
}
I am trying to open a text file inputted by the user and read this text file but print the text file 60 characters at a time so I think in order for me to do this I need to store the text into an array and if it is over 60 characters on a line it should start on a new line. However, when I run the code below an error message shows up saying : C^#
#include <stdio.h>
#include <stdlib.h>
int main()
{
char arr[];
arr[count] = '\0';
char ch, file_name[25];
FILE *fp;
printf("Enter file name: \n");
gets(file_name);
fp = fopen(file_name,"r"); // reading the file
if( fp == NULL )
{
perror("This file does not exist\n"); //if file cannot be found print error message
exit(EXIT_FAILURE);
}
printf("The contents of %s file are :\n", file_name);
while( ( ch = fgetc(fp) ) != EOF ){
arr[count] = ch;
count++;
printf("%s", arr);}
fclose(fp);
return 0;
}
char arr[]; is invalid.you need to specify a size.
array[count] = '\0'; : count is uninitialized.
gets(file_name); : gets is deprecated and dangerous.use another function like scanf.
Try the following code :
#include <stdio.h>
#include <stdlib.h>
int main()
{
int ch , count = 0;
char file_name[25];
FILE *fp;
printf("Enter file name: \n");
scanf(" %24s",file_name);
fp = fopen(file_name,"r"); // reading the file
if( fp == NULL )
{
perror("This file does not exist\n"); //if file cannot be found print error message
exit(EXIT_FAILURE);
}
fseek(fp, 0L, SEEK_END);
long sz = ftell(fp);
fseek(fp, 0L, SEEK_SET);
char arr[sz];
while( ( ch = fgetc(fp) ) != EOF )
{
if( count < sz )
{
arr[count] = ch;
count++;
}
}
arr[sz] = '\0';
printf("The contents of %s file are :\n", file_name);
printf("arr : %s\n",arr);
fclose(fp);
return 0;
}
fgetc always reads the next character until EOF. use fgets() instead:
char *fgets(char *s, int size, FILE *stream)
fgets() reads in at most one less than size characters from stream and
stores them into the buffer pointed to by s. Reading stops after an EOF
or a newline. If a newline is read, it is stored into the buffer. A
terminating null byte (aq\0aq) is stored after the last character in the
buffer.
1) your while loop is not properly delimited. In the absence of a { } block, the instruction arr[count] = ch; is the only repeted one.
I suppose it should include the incrementation of count too
while( ( ch = fgetc(fp) ) != EOF )
{
arr[count] = ch;
count++;
....
}
among other things (testing the counter etc).
2) there's no imperative need to read and store in an array. It is perfectly possible to transfer each character as soon as it is read, and add a line break when needed (new line, limit of 60 exceeded).
Three problems:
The variable count is not initialized, so it's value is indeterminate and using it will lead to undefined behavior.
The call printf(arr) treats arr as a string but arr is not terminated which again leads to undefined behavior.
The increment of count is outside the loop.
To solve the two first problems you must first initialize count to zero, then you must terminate the string after the loop:
arr[count] = '\0';
However, your printf(arr) call is still very problematic, what if the user enters some printf formatting codes, what will happen then? That's why you should never call printf with a user-provided input string, instead simply do
printf("%s", arr);
You also have a very big problem if the contents of the file you read is longer than 59 characters, and then you will overflow the array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main ( int argc, char *argv[] )
{
if ( argc != 4 ) /* argc should be 4 for correct execution */
{
/* Print argv[0] assuming it is the program name */
printf( "usage: %s filename\n", argv[0] );
}
else
{
// We assume argv[1] is a filename to open
char* wordReplace = argv[1];
char* replaceWord = argv[2];
FILE *file = fopen( argv[3], "r+" );
/* fopen returns 0, the NULL pointer, on failure */
if ( file == 0 )
{
printf( "Could not open file\n" );
}
else
{
char string[100];
int len = 0;int count = 0;int i = 0;int k = 0;
while ( (fscanf( file, "%s", string ) ) != EOF )
{
len = strlen(string);
count++;
char charray[len+1];
if(count == 1)
{
for (i = 0; i < len; i++)
{
charray[i] = replaceWord[i];
printf("%c\n", charray[i]);
}
}
//printf("%c\n", charray[0]);
printf( "%s\n", string );
if(strcmp(string, wordReplace) == 0)
{
for(k = 0; k < strlen(replaceWord); k++)
{
fseek (file, (-(long)len), SEEK_CUR);
fputc(charray[k],file);
//replaceWord++;
}
//strcpy(string, replaceWord);
//fprintf(file,"%s",replaceWord);
//fputs(string, file);
//printf("\n%d\n", len);
}
}
fclose( file );
}
}
printf("\n");
return 0;
}
This code currently works in replacing the First word properly, but if there are multiple words that i want overwritten with the replace word or the word appears somewhere else in the text it will not properly change it, and it will change it to ram trash etc. I was curious if anyone could lead me to a reason why thank you.
Assuming the words are the same length (if not you have quite a few more issues):
Let's say you have a 4 character word:
fseek (file, (-(long)len), SEEK_CUR); will go back to position 0 (4-4), fputc(charray[k],file); will update to position 1, then you back 4 more which is an error but since you're not checking the return value from fseek you will not know this. At this point the algorithm is not working any more since your assumed file positions are all wrong
EDIT:
if(strcmp(string, wordReplace) == 0)
{
fseek (file, (-(long)len), SEEK_CUR);
for(k = 0; k < strlen(replaceWord); k++)
{
fputc(charray[k],file);
}
}
fflush(file); //you need to flush the file since you are switching from write to read
EDIT 2: reason for flush: from 4.5.9.2 ANSI C, similar paragraph in C99 7.19.5.3):
When a file is opened with update mode ('+' as the second or third character in the mode argument), both input and output may be performed on the associated stream. However, output may not be directly followed by input without an intervening call to the fflush function or to a file positioning function ( fseek , fsetpos , or rewind ), and input may not be directly followed by output without an intervening call to a file positioning function, unless the input operation encounters end-of-file.
Between the read and write you have the fseek already so that is not a problem