I'm trying to write a program where I add words to one text file. Also, I can delete any word from this file and I save the result without this word to another text file. But when I run it, my second text file is filled with H symbols, and its size can be more than 100 mb. What's wrong with this code? Here it is:
int main(void)
{
int wordNumbers;
int i;
char buf[512];
char word[128];
FILE *o_file = fopen("C:\\atest.txt", "a");
FILE *s_file = fopen("C:\\btest.txt", "w");
printf("please add an amount of words of the dictionary ");
scanf("%i", &wordNumbers);
for (i=0; i< wordNumbers; i++)
{ char word[100] = {0};
printf("add a word into the dictionary please\n");
scanf("%s", &word);
fprintf(o_file, "%s\n", word);
}
if(!o_file || !s_file) return -1;
printf("please write down the word you want to delete\n");
scanf("%s",&word);
do
{
fscanf(o_file, "%511s", buf);
if(!strcmp(buf, word))
continue;
fprintf(s_file, "%s\n", buf);
}
while(!feof(o_file));
fclose(o_file);
fclose(s_file);
}
You print to the file o_file to insert your strings. Then, immediately after this, you start to read from this same file.
Read and write to a single file both use the same file pointer. Because the file pointer is here always at the very end of the file after these writes, the next read should fail – but since you don't check the result of fscanf, you don't ever realize that, and you write uninitialized data into the new file.
After writing the new contents into o_file, reset the file pointer to the start with fseek (o_file, 0, SEEK_SET) or rewind (o_file).
Always test if fscanf (and scanf) returns the correct number of recognized items. The return value is there for a reason.
Also read Why is “while ( !feof (file) )” always wrong?.
Related
SO i'm supposed to write a block of code that opens a file called "words" and writes the last word in the file to a file called "lastword". This is what I have so far:
FILE *f;
FILE *fp;
char string1[100];
f = fopen("words","w");
fp=fopen("lastword", "w");
fscanf(f,
fclose(fp)
fclose(f);
The problem here is that I don't know how to read in the last word of the text file. How would I know which word is the last word?
This is similar to what the tail tool does, you seek to a certain offset from the end of the file and read the block there, then search backwards, once you meet a whitespace or a new line, you can print the word from there, that is the last word. The basic code looks like this:
char string[1024];
char *last;
f = fopen("words","r");
fseek(f, SEEK_END, 1024);
size_t nread = fread(string, 1, sizeof string, f);
for (int I = 0; I < nread; I++) {
if (isspace(string[nread - 1 - I])) {
last = string[nread - I];
}
}
fprintf(fp, "%s", last);
If the word boundary is not find the first block, you continue to read the second last block and search in it, and the third, until your find it, then print all the characters after than position.
There are plenty of ways to do this.
Easy way
One easy approach would be to to loop on reading words:
f = fopen("words.txt","r"); // attention !! open in "r" mode !!
...
int rc;
do {
rc=fscanf(f, "%99s", string1); // attempt to read
} while (rc==1 && !feof(f)); // while it's successfull.
... // here string1 contains the last successfull string read
However this takes a word as any combination of characters separated by space. Note the use of the with filed in the scanf() format to make sure that there will be no buffer overflow.
More exact way
Building on previous attempt, if you want a stricter definition of words, you can just replace the call to scanf() with a function of your own:
rc=read_word(f, string1, 100);
The function would be something like:
int read_word(FILE *fp, char *s, int szmax) {
int started=0, c;
while ((c=fgetc(fp))!=EOF && szmax>1) {
if (isalpha(c)) { // copy only alphabetic chars to sring
started=1;
*s++=c;
szmax--;
}
else if (started) // first char after the alphabetics
break; // will end the word.
}
if (started)
*s=0; // if we have found a word, we end it.
return started;
}
I have a txt file with some file names and their size.
This is how I wrote the txt file:
banana //file name
3 //the size of file banana
programs
12
music
524
I have to find a keyboard entered file name and display it's size.
This is my code:
FILE *text;
text=fopen("text.txt","r");
printf("Scan the number of letters of your file name");
int n;
scanf("%d",&n);
char s[++n];
printf("Scan the file name you are looking for: ");
int i;
for(i=0;i<=n;i++)
{
scanf("%c",&s[i]);
}
int l=0;
char c[n];
char g;
while(!feof(text))
{
if(l%2==1) {fgetc(text); fgetc(text); l++;}
if(l%2==0)
{
fgets(c,n,text);
fgetc(text);
for(i=0;i<n;i++)
{
printf("%c",c[i]);
}
l++;
}
}
Obviously, it's not correct. Can you help me? I'm a little bit confuse.
Ugh! Please learn more about basic input. Your program has various flaws:
fgetc reads single characters. This can be useful at times, but obviously you want to read whole lines. fgets does this. You use it once, but it is not advisable to mix these. Decide up front which input paradigm you want to use: char-wise (fgetc), line-wise (fgets) or token-wise (fscanf).
Please don't make the user enter the number of characters in the filename. Quick, how many characters are there in MySpiffyDocument.txt? That's work that the computer should do.
Don't use feof to control yopur input. All input functions have special return values toat indicate that either the end of the file was read or that an error occurred. For fgets, this return value is NULL, for fgetc, this return value is the special constant EOF. The functions feof and ferror are useful after you have encountered the special return values for a post mortem analysis of the two end conditions.
Your inner loop, which is responsible for the core program logic, doesn't make sense at all. For example, for an odd l, increment l and then test for an even l – which will be true, because you have just incrremented an odd l. Use else in such cases. And don't place things that happen anyway in conditional blocks: Increment l once after the if/else blocks.
Here's an example implementation:
#include <stdlib.h>
#include <stdio.h>
int process(const char *filename)
{
char line[80];
char name[80];
int size;
int count = 0;
FILE *f = fopen(filename, "r");
if (f == NULL) return -1;
while (fgets(line, sizeof(line), f)) {
if (count % 2 == 0) {
if (sscanf(line, "%s", name) < 1) continue;
} else {
if (sscanf(line, "%d", &size) < 1) continue;
printf("%12d %s\n", size, name);
}
count++;
}
fclose(f);
return 0;
}
int main()
{
char line[80];
char name[80];
puts("Please enter filename:");
while (fgets(line, sizeof(line), stdin)) {
if (sscanf(line, "%s", name) == 1) {
process(name);
break;
}
}
return 0;
}
Things to note:
The program uses 80 characters a max. buffer size; that means your lines can be up to 78 characters long – line content plus new-line '\n' plus null terminator '\0'. That should be okay for many cases, but eventually the line may overflow. (So your file-name letter count has some merit, but the real solution here is to allocate memory dynamically. I won't open that can of worms now.)
The code uses a double strategy: Read lines first, then scan into these lines with sscanf, so that only the first word on each line is read.
Empty lines are skipped. Even lines that don't hold a valid number are skipped, too. This is sloppy error handling and may trip the odd/even count.
Reading stuff interactively from the keyboard isn't very easy in C. The awkward fgets/sscanf construct in main tries to handle the case when the user enters an empty line or evokes an end-of-file signal via Ctrl-D/Z. A better and easier way is to provide arguments to the command line via argc and argv.
I've moved the file reading into a separate function.
I am trying to read a txt file with following contents:
test.txt
3,4
5,6
7,8
each pair is in one line. I want to put these values in an array. But I want the array size to adjust based on number of pairs in the test txt.
So I calculated the number of lines available in the txt file until EOF and assigned the number of lines to the array to assign the sizeof the array.Then when I try to read the file using fscanf I get some weird numbers which is not even part of this txt file like 2342,123123.
Here is my code:
#include <stdio.h>
int main(int argc , char **argv)
{
FILE *pf;
int k;
int counter=0;
int c;
pf = fopen("test.txt", "r");
if(pf==NULL)
{
printf("its nuull");
}
else
{
do
{
c=fgetc(pf);
if(c=='\n')
counter++;
}while(c!=EOF);
printf("counter value is = %d\n", counter);
int b[counter][2];
for(k=0;k<counter;k++)
{
fscanf(pf,"%d, %d" ,&b[k][0],&b[k][1]);
printf("%d,%d\n" ,b[k][0],b[k][1]);
}
}
fclose(pf);
}
I think you need to call:
rewind(pf);
after displaying your counter value.
This will reset the file pointer to the start of the file.
The issue is probably that the current file pointer is pointing at the end of the file. You need to read from the begining of the file now, so you need to do something like:
rewind(pf);
There are other mechanisms - for instance fseek or fsetpos, but rewind is what I would use here.
You might also check the return from fscanf - this will return the number of input items assigned. If this isn't 2 (in your case) then something went wrong.
Im having some trouble figuring out how to properly format fread statements. The below code is just some randomn stuff Im practicing with. Basically it fills information into the first array (s), writes 's' to a file, and then reads the file into the second array (s2). However I can't seem to get the fread statement formated in a way that doesnt give an error or return garbage. The arrays are in char datatype because, if my understanding is correct, char uses less memory than other datatypes. The eventual application of this practice code is for a data compression project.
#include<stdio.h>
#include<string.h>
FILE *fp;
//file pointer
char s[56];
//first string
char s2[56];
//target string for the fread
int n=0;
//counting variable
int m=0;
int main (void)
{
fp=fopen("test.bin", "w+");
//open a file for reading and writing
strcpy(s, "101010001101010");
//input for the string
for(n=0;n<56;n++)
{
if(s[n]==1)
m=n;
else if(s[n]==0)
m=n;
}
printf("%d\n", m);
//the above for loop finds how many elements in 's' are filled with 1's and 0's
for(n=0;n<m;n++)
{
printf("%c", s[n]);
}
//for loop to print 's'
fwrite(s, m, 1, fp);
//writes 's' to the first file
s2=fread(&s2, m, 1, fp);
//an attempt to use fread...
printf("\n\ns2\n\n");
for(n=0;n<m;n++)
{
printf("%c", s2[n]);
}
printf("\n");
//for loop to print 's2'
fclose(fp);
printf("\n\n");
printf("press any number to close program\n");
scanf("%d", &m);
}
A FILE structure has an implicit seek position within the file. You read and write from that seek position. If you want to read what you have written, you need to change the seek position back to the beginning of the file with a call to fseek(). In fact, for a file open for reading and writing, you must call fseek() when switching between reading and writing.
The return value of the fread function is of type size_t. It is the number of elements successfully read. (reference: http://www.cplusplus.com/reference/cstdio/fread/)
Don't assign it to s2. Simply use fread(&s2, m, 1, fp);
i'm new at c.. and still having trouble at the syntax, hope you can help me... cause i'm stuck at this code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int main(void){
FILE *stream = NULL;
stream = fopen("studentinfo.txt", "a+");
/*some of initialization were used for testing purposes only*/
char arr[5];
char arr2[5];
int i;
char name[3];
char course[5];
printf("enter details: ");
scanf("%s", arr2);
while(!feof(stream)){
fgets(arr, 100, stream);//i am confused if the line capture was stored at arr[0]
if(strcmp(arr, arr2)==0){//i want to compare
printf("success");//testing
}
printf("%s", arr);//i wonder does fgets just overwrites the new line to arr[0]
}
fclose(stream);
getch();
}
thanks guys...
You're opening studentinfo.txt for appending, but then reading from it (and you don't check the open succeeded
you've allocated 5 characters for arr, but read up to 100 characters into it with the fgets. This will overflow and cause memory corruption
you've allocated 5 characters for arr2, but read an arbitary number of characters into it - this will overflow and cause memory corruption
Fgets reads characters into memory starting at arr. arr[0] is the first character. &arr[0] is the same as arr
What's the getch() at the end for?
Also, "a+" positions the stream at the end of the file, so you won't be able to read anything.
if you have an existing file... and your file has data on it. then you could check if the data you typed is existing on the file or not. i'm not sure if this is what you want.
example if you typed... love
and the file also contains the exact word... love (on one line)
then it will print "success".
if the data you typed is not existing on the file, it will be appended on the file (on the next line).
int main(void){
char arr[5];
char arr2[5];
int i;
int n=0;
FILE *stream = NULL;
FILE *append = NULL;
stream = fopen("studentinfo.txt", "rt");
append = fopen("studentinfo.txt", "a+");
printf("enter details: ");
scanf("%s", arr2);
while(!feof(stream)){
fgets(arr, 6, stream);
if(strcmp(arr, arr2)==0){
printf("success");
} else n=-1;
}
if (n==-1){
fprintf(append, "%s\n", arr2);
}
fclose(stream);
fclose(append);
system("pause");
}
I am not sure why you are opening the stream with a+ because you never actually write to it. Maybe you want to make sure the file exists even if 0 length? You should still check that the open succeeded though.
You are then reading 100 characters into an array of just 5 bytes so you will get a serious memory overwrite if the file really does contain that number.
The scanf is unsafe too of course as the user may enter too many characters (they are actually limited to 4 because there is a NULL terminator that gets read).
At the end you appear to be writing the last line randomly if the user did not enter a matching line from the file.