Alright, so basically what I have to do is change all the numbers of a text file to dollar sign, I know how to scan for the specific character but I am stuck on how to replace that specific character with dollar sign. I don't want to use fseek or any library commands, how do I proceed and why isn't my code working?
#include<stdio.h>
main()
{
FILE* fptr;
char filename[50];
char string[100];
int i;
printf("Enter the name of the file to be opened: ");
scanf("%s",filename);
fptr=fopen(filename,"w");
if(fptr==NULL)
{
printf("Error occurred, try again.");
return 0;
}
fgets(string,"%s",fptr);
do
{
if(string[i]>='1' && string[i]<='9')
{
string[i]='$';
}
}
while(i!=100);
fclose(fptr);
}
There are basically two approaches at first glance, the first is to use fseek() and the second to read the file in its entirety and replace the characters to your criteria and finally write that in one shot. You can choose either of the approaches depending on your need. For large file you should prefer the former and for small file you can prefer the latter.
Here's an example code of the former:
#include <stdio.h>
int main() {
// Open the file
FILE *fptr = fopen("input.txt", "r+");
if (!fptr) {
printf("Error occurred, try again.");
return -1;
}
int c;
// Iterate through all characters in a file
while ((c = getc(fptr)) != EOF) {
// Check if this current character is a digit?
if (c >= '0' && c <= '9') {
// Go one character back
if (fseek(fptr, -1, SEEK_CUR) != 0) {
fprintf(stderr, "Error while going one char back\n");
return -1;
}
// Replace the character with a '$'
if (fputc('$', fptr) == EOF) {
fprintf(stderr, "Error while trying to replace\n");
return -1;
}
}
}
// Flush the changes to the disk
if (fflush(fptr) != 0) {
fprintf(stderr, "Error while flushing to disk\n");
return -1;
}
// Close the file
fclose(fptr);
return 0;
}
Related
My program loads/saves double value into a text file using union.
I think I am having a buffer overflow, when I use fflush(stdin) it works, but I can't. The problem maybe somewhere else though. The code jumps without letting me enter a file to load from ( 2.000000 is autoinserted ).
Ps. Yes I know that tab[i] would be better than *(tab+i) but spare me, I just have to do it like this.
output :
Enter double value:8794.061758
Enter path to file you wish to save:valleykingstopwantreachspellshipcontinue
File saved
Enter a path to file you wish to load: 2.000000 ----- This value is inserted automatically ( I didnt write it)
Process finished with exit code 0
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
union double_to_char_t
{
double d;
char bytes[8];
};
int save_double(const union double_to_char_t *dtc, const char *filename)
{
if(dtc == NULL || filename == NULL) return 1;
FILE * f=fopen(filename,"w");
if(f == NULL) return 2;
int result = fwrite(dtc, sizeof(dtc), 1, f);
if( result != 1)
{
fclose(f);
return 3;
}
fclose(f);
return 0;
}
int load_double(union double_to_char_t *dtc, const char *filename)
{
if( dtc == NULL || filename == NULL) return 1;
FILE * f = fopen(filename,"r");
if( f == NULL ) return 2;
int result = fread(dtc, sizeof(dtc), 1, f);
if( result != 1)
{
fclose(f);
return 3;
}
fclose(f);
return 0;
}
int main()
{
union double_to_char_t unia;
char temp1[40] = {0};
char temp2[40] = {0};
char *input1 = temp1;
char *input2 = temp2;
printf("Enter double value: ");
if(scanf(" %lf",&(unia.d))!=1)
{
printf("Incorrect input");
exit(1);
}
printf("Enter path to file you wish to save:");
fgets(input1, 40, stdin);
int wynik = save_double(&unia,input1);
if(wynik > 0)
{
printf("Couldn't create file\n");
exit(5);
}
else
{
printf("File saved\n");
}
printf("Enter a path to file you wish to load: ");
fgets(input2, 40, stdin);
// scanf(" %39[^\n]", input2);
int score = load_double(&unia,input2);
if(score > 0 && score < 3)
{
printf("Couldn't open file\n");
exit(4);
}
if(score == 3)
{
printf("File corrupted\n");
exit(6);
}
printf("%f",unia.d);
return 0;
}
You used %39[^\n] to read the filename, then typed a 40 character filename. The first 39 characters were put into input1, and the last character was left in the input stream.
When you then tried to get the filename for input2, it read that last character. That's why it didn't wait for you to type anything -- there was still input available after the first filename was read.
So you saved to valleykingstopwantreachspellshipcontinu and loaded from e.
You need to ensure that your input buffer is longer than any potential input. If you use fgets() instead of scanf(), you can test whether the input ends with a newline. If not, you can report that the input was too long, read characters until the newline, then ask for input again. (The non-standard fflush(stdin) discards everything up to the next newline, which is why adding that fixed the problem.)
if (!fgets(input1, 40, stdin)) {
printf("input error\n");
exit(1);
}
if (input1[strlen(input1)-1] != '\n') { // check for trailing newline
printf("filename too long\n);
exit(3);
}
input1[strlen(input1)-1] = '\0'; // remove it before using as filename
You could also use the getline() function. This isn't standard C, but it's POSIX and widely implemented. It allocates the input buffer dynamically so any length can be accomodated.
I'm having trouble setting the file pointer to the very start of a file to write some stuff at first AFTER having already written some text in it.
I've tried rewind(), fseek(), opening the file in "r+" & "a+" modes, nothing seems to work.
Here's a small recreation of the program:
#include<stdio.h>
#include<stdlib.h>
void master_globalprint(int lim)
{
int i = 0;
FILE* maspass;
errno_t err;
err = fopen_s(&maspass, "Master_Password.txt", "r+");
if (err != 0)
{
printf("Error opening Master_Password.txt");
exit(0);
}
rewind(maspass);
printf("Pointing to %ld", ftell(maspass));
while (i < lim)
{
fprintf(maspass, "%d", i); //Writing the array infront of the encrypted code
i++;
}
fclose(maspass);
}
void master_create() //To Create a Master Password
{
int count = 0;
char pass;
FILE* maspass;
errno_t err;
err = fopen_s(&maspass, "Master_Password.txt", "a");
if (err != 0)
{
printf("Error creating Master_Password.txt");
exit(0);
}
printf(" Enter Master Password : ");
while ((pass = getchar()) != EOF && pass != '\n')
{
count++;
fprintf(maspass, "%c", pass); //The characters are then printed one by one
}
if (count == 0)
{
remove("Master_Password.txt");
printf("Master Password cannot be empty");
exit(0);
}
fprintf(maspass, "%c", (count + 33)); //To put the amount of letters into file, forwarded by 33 to reach a certain ASCII threshold and converted to char
fprintf(maspass, "\n");
fclose(maspass);
master_globalprint(count);
}
void main()
{
master_create();
}
The above functions work and print the correct values except the master_globalprint function starts printing exactly where the last function left off.
Is it because I've to use command line arguments to achieve the task? If so, can I set the command line arguments to be executed by default somehow so that if the code is distributed, the user won't have to bother?
EDIT : Added in a reproducible code sample. When I put "a" in line 31, it prints only the stuff I input and not the numbers in master_globalprint(). If I put "w", it ONLY prints the numbers in master_globalprint() and not the stuff I input.
Here the writing mode should be w+:
err = fopen_s(&maspass, "Master_Password.txt", "a" /* w+ */);
Here you should close the file and then remove it:
if (count == 0)
{
/*fclose_s(maspass);*/
remove("Master_Password.txt");
printf("Master Password cannot be empty");
exit(0);
}
Instead of doing this, you should keep the file descriptor open and pass it to master_globalprint:
fclose(maspass);
master_globalprint(count);
/* master_globalprint(count, maspass);
* fclose(maspass); */
Then keep reusing the open file descriptor.
I have a file formatted like:
01,Name1
02,Name2
03,Name3
04,Name4
05,Name5
I am tying it make it so that a user can type in a number like 01, or 02 and the corresponding name will be returned. This works fine when I type 01. However when I type any number after it doesn't work and it seems like when I replace the loop with:
fscanf(fp,"%20[^,],%s[^\n]",ln,name);
printf("1=%c 2=%c 3=%c 4=%c\n",ln[0],ln[1],search[0],search[1]);
fscanf(fp,"%20[^,],%s[^\n]",ln,name);
printf("1=%c 2=%c 3=%c 4=%c\n",ln[0],ln[1],search[0],search[1]);
The 2nd time around the ln[0] gets filled with a lot of spaces or a "\n". I can't tell.
Any help will be appreciated.
Here is my code:
#include <stdio.h>
int main()
{
puts("Enter seach number:");
char search[2];
scanf("%c%c",&search[0],&search[1]);
FILE *fp;
fp = fopen("/Users/user1/Desktop/text.txt","r");
if(fp == NULL){
puts("File dose not exits");
return (1);
}
else{
puts("File found");
}
char ln[3];
char name[20];
fopen("fp","r");
puts("File opened");
int searching = 1;
while(searching == 1)
{
fscanf(fp,"%20[^,],%s[^\n]",ln,name);
if(ln[0]==search[0]&&ln[1]==search[1])
{
printf("%s",name);
searching = 0;
}
else if(ln[0] == '\n')
{
puts("Could not find number");
searching = 0;
}
}
return 0;
}
Wrong use of fscanf() format
// fscanf(fp,"%20[^,],%s[^\n]",ln,name);
fscanf(fp,"%20[^,],%s%*[^\n]",ln,name);
// or
fscanf(fp,"%20[^,],%s ",ln,name);
// or
fscanf(fp," %20[^,],%s",ln,name);
Better to check results and add width to %s
char ln[20+1];
char name[30+1];
if (2 == fscanf(fp,"%20[^,],%30s%*[^\n]",ln,name)) Success();
Best to use fgets()
char buf[100];
if (fgets(buf, sizeof buf, fp) == NULL) {
if (2 == sscanf(buf,"%20[^,],%s",ln,name)) Success();
}
This is making me nuts I am trying to make a simple program to copy any type of file using the following code but the result I get is unexpected (one or two extra characters at the end of copied file?). For instance if my original file has This is an example the copied file contains This is an exampleÿ
CODE
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp,*fpp;
char pbuff, fname[32];
int i;
printf(" FILE NAME TO OPEN : ");
scanf(" %32s", fname);
fp = fopen(fname, "rb");
fpp = fopen("file", "wb");
if(fp==NULL)
{
printf("NO SUCH FILE. EXITING NOW.");
getch();
exit(1);
}
while(!feof(fp))
{
pbuff = fgetc(fp);
fputc(pbuff, fpp);
}
printf("SUCCESSFULLY CREATED!");
fclose(fp);
fclose(fpp);
getch();
return(0);
}
Can anyone help me out with this one? I will be really very thankful.
The reason is that feof (like most end-of-file indicators in most languages/environments) is only set AFTER the end-of-file has been reached. Since you write the character and only then check the EOF status, you're writing 1 too many characters. fgetc's return value is a predefined EOF if the end-of-file was reached during the call.
You could solve that in 1 of 2 ways:
while(true)
{
pbuff = fgetc(fp);
if(feof(fp))
break;
fputc(pbuff, fpp);
}
Or: (edit as melpomene correctly noticed!)
// Change pbuff to type int in the declartion, and then...
while(true)
{
pbuff = fgetc(fp);
if(EOF == pbuff)
break;
fputc(pbuff, fpp);
}
I have a question which maybe fairly simple. I have a file input.txt which is:
cat input.txt
testsuite1
test1
summary information of test
FAIL
testsuite2
test1
summary info ya
PASS
I am writing a program just to read each of these strings into variables and do further processing. What is the best way to do it? I am currently doing:
main() {
FILE *fp;
char testsuite[100],testname[100],summary[100],result[100];
fp = fopen("input.txt", "r");
while(1) {
if(fgets(testsuite,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(testname,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(summary,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(result,99,fp) == NULL)
{
ferror(fp);
break;
}
printf("testsuite: %s testname:%s summary:%s result:%s \n",testsuite,testname,summary,result);
}
fclose(fp);
}
Is there a better way to do it? The problem I am currently facing is that, if input.txt contains even one blank line, the blank like is read into a variable. Whats the best way to avoid it?
Thanks!
You should write your own function that skips empty lines (e.g. called getline()) and use it instead of fgets():
char *getline(char *buf, int size, FILE *fp)
{
char *result;
do {
result = fgets(buf, size, fp);
} while( result != NULL && buf[0] == '\n' );
return result;
}
You could now refine that function to also skip lines that consist of blanks only or whatever you need.
You can remove all blank lines of your files before your loop while.
After the open you parse the whole file and remove the blank ;).
But it don't seems like the best way to do it.
Overwise you can check after each fget if your variables are empty, and in this case, fget again.
Hope that will be helpfull.
If you do this, you will not be able to use the strings you read once loop quits, since each loop overwrites each string in the buffer. However, you could store your strings in a struct array:
typedef struct {
testsuite[100];
testname[100];
summary[100];
result[100];
}test;
test test_array[2];
int main(){
int iIndex=0;
FILE* fpPtr=NULL;
fpPtr = fopen("input.txt", "r");
if(fpPtr==NULL){ //<--- it is very important to check if fopen fails
perror("fopen");
}
for(iIndex=0; iIndex<2; iIndex++){ // 2 because it is the number of elements in test_array
if(fgets(test_array[i].testsuite,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].testname,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].summary,99,fp) == NULL)
{
ferror(fp);
break;
}
if(fgets(test_array[i].result,99,fp) == NULL)
{
ferror(fp);
break;
}
}
}
You can detect blank lines by checking for a newline character at position 0:
fgets(cBuffer, sizeof(cBuffer), fpPtr);
//<-- if the file was created on windows, check for '\r' instead, since a new line in windows is \r\n
if(cBuffer[0]=='\n')
{
printf("blank line"\n);
}