Write system call C , fills file with garbage - c

I am facing some issues when trying to filter specific words from a file, and write them into a new file.
What I am trying to do is writing only words that comes after '&' until the first digit.
For example (This is the content of the file I am reading from):
& some 12 test1 test2
$ thisword 4 no no no no
For the above input , I want to write into a new file the words some and thisword only.
My code is working but , instead of printing only those words , it is printing garbage as well.
int main (argc,argv)
int argc;
char *argv[];
{
int inpfd,outpfd,n;
int i=0;
char tmp[2],buff[BUFFSIZE]; //This is our buffer
//Open the output file of ispell
inpfd = open("outputfile.txt",O_RDONLY);
//Check if open command failed
if(inpfd == -1) {
printf("Failed to open file");
exit(1);
}
//Here we are reading from output file
read(inpfd,buff,999);
buff[999] = '\0';
close(inpfd);
outpfd = open("w.txt",O_WRONLY);
if(outpfd == -1) {
printf("Cannot open file for writing!");
exit(1);
}
//Looping over the Buffer
for (i=0; i <BUFFSIZE; i++) {
printf("This is the char : %c \n",buff[i]);
if(buff[i] == '&') {
i++;
while( !(isdigit(buff[i])) ) { //Write into output file
//As long as we didnt reach
tmp[0] = buff[i]; // To the digit
write(outpfd,tmp,1);
i++;
}
write(outpfd,"\n",1); //Moving to the next line
}
}
close(outpfd);
return 0;
}
This the output of the file after the writing (I am pasting only small part of the garbage):
some
thisword
^#^#^#<FD>^?^#^#<80><B2>-<AD><FD>^?^#^#<B0>
<B0>be^#^#^#^#೵[^X^?^#^#^#<B4>-<AD><FD>^?^#^#s^X<F0>[^X^?^#^#^#<FF>^#^#^#^#^#^#
^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#^#/
I have no idea what is this garbage , can someone please assist?

Your problem is in this code
read(inpfd,buff,999);
buff[999] = '\0';
close(inpfd);
where you are ignoring the actual length of what you are reading
You should at least use the length of data actually read -- like this
int len = read(inpfd,buff,999);
buff[len] = '\0';
close(inpfd);
However note that the above have it own issues, as read does not always return everything in one go and can terminate early for interrupts etc etc, but that is beyond the scope of this question. For very simple apps, you may just get away with the simple modification.
Now after null terminating knowing the actual length of the file from the result of read, you also need to fix your loop -- the first step would be to have your outer loop only looking at the data that you read, so
So instead
for (i=0; i <BUFFSIZE; i++) {
use the actual length;
for (i=0; i <len; i++) {
Your code inside the loop contains several issues as well, loop termination for one, that you will have to fix as well.

You are looping over the entire size of your buffer, or 999 items.
for (i=0; i <BUFFSIZE; i++) {
The input file is almost certainly shorter than 999 items. So once you're done processing the supplied input, you're just processing garbage until your counter reaches 999!

Related

Why is the number of lines showing as 0 when I also print the lines out but works fine when its just the line count

So both the code to print the lines from the txt file and the code to count the lines in the txt file work fine when the other is commented out but when i try to have both work only the code that comes first works e.g. if i put the code to print out the lines first, the line count is always zero. However if i put the code to count the lines first, the number is correct but the lines from the txt file are not printed :S
#include <stdio.h>
int main(int argc, char const *argv[])
{
const int SIZE = 128;
char line[SIZE];
FILE *srcFile;
int c;
int count = 0; // Line counter (result)
if (argc == 1)
{
printf("No command line arguments given!\n");
return 1;
}
srcFile = fopen(argv[1], "r");
if (srcFile == NULL)
{
perror("\n*** FILE OPEN FAILED ***");
}
else
{
printf("\n*** FILE OPEN SUCCESSFUL ***\n\n");
}
while(fgets(line, SIZE, srcFile) != NULL)
{
printf("%s", line);
}
for (c = fgetc(srcFile); c != EOF; c = fgetc(srcFile))
{
if (c == '\n')
{
count ++;
}
}
if(c != '\n' && count != 0)
{
count ++;
}
printf("The file %s has %d lines\n ", argv[1], count);
fclose(srcFile);
return 0;
}
Here is a quick overview of how working with files is done in most programming languages:
When you open a file in a program you obtain a handle to that file. What the handle representation is depends on the language. In c it is the FILE structure. The handle contains - among other things - a file position indicator. Every read and write to that file through this handle happens at that position. Usually a read/write operation advances this file position indicator. Think about it: how do consecutive reads know to each read where the previous one left? You don't provide an argument to the read function telling it where to read from. You just "say" read. What happens is that each read call reads at the file position indicator and then advances this indicator, thus when the next read happens the handle has an updated file position indicator.
So the solution to your problem is - as mentioned in the comments - to put this position indicator to the beginning of the file. In c this can be done with rewind.
curious how the code fragment would have to look to include the line
count int the same loop as the print lines
Simple. Pseudocode:
line_count = 0
while (read line successful)
{
print line
increment line_count
}
print line_count

Find end of text in a text file padded with NULL characters in C [duplicate]

file looks like this:
abcd
efgh
ijkl
I want to read the file using C so that it read the last line first:
ijkl
efgh
abcd
I cannot seem to find a solution that does not use an array for storage. Please help.
edit0:
Thanks for all the answers. Just to let you know, I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?
It goes like this:
Seek to one byte before the end of the file using fseek. There's no guarantee that the last line will have an EOL so the last byte doesn't really matter.
Read one byte using fgetc.
If that byte is an EOL then the last line is a single empty line and you have it.
Use fseek again to go backwards two bytes and check that byte with fgetc.
Repeat the above until you find an EOL. When you have an EOL, the file pointer will be at the beginning of the next (from the end) line.
...
Profit.
Basically you have to keep doing (4) and (5) while keeping track of where you were when you found the beginning of a line so that you can seek back there before starting your scan for the beginning of the next line.
As long as you open your file in text mode you shouldn't have have to worry about multibyte EOLs on Windows (thanks for the reminder Mr. Lutz).
If you happen to be given a non-seekable input (such as a pipe), then you're out of luck unless you want to dump your input to a temporary file first.
So you can do it but it is rather ugly.
You could do pretty much the same thing using mmap and a pointer if you have mmap available and the "file" you're working with is mappable. The technique would be pretty much the same: start at the end and go backwards to find the end of the previous line.
Re: "I am the one creating this file. So, can I create in a way its in the reverse order? Is that possible?"
You'll run into the same sorts of problems but they'll be worse. Files in C are inherently sequential lists of bytes that start at the beginning and go to the end; you're trying to work against this fundamental property and going against the fundamentals is never fun.
Do you really need your data in a plain text file? Maybe you need text/plain as the final output but all the way through? You could store the data in an indexed binary file (possibly even an SQLite database) and then you'd only have to worry about keeping (or windowing) the index in memory and that's unlikely to be a problem (and if it is, use a "real" database); then, when you have all your lines, just reverse the index and away you go.
In pseudocode:
open input file
while (fgets () != NULL)
{
push line to stack
}
open output file
while (stack no empty)
{
pop stack
write popped line to file
}
The above is efficient, there is no seek (a slow operation) and the file is read sequentially. There are, however, two pitfalls to the above.
The first is the fgets call. The buffer supplied to fgets may not be big enough to hold a whole line from the input in which case you can do one of the following: read again and concatenate; push a partial line and add logic to the second half to fix up partial lines or wrap the line into a linked list and only push the linked list when a newline/eof is encountered.
The second pitfall will happen when the file is bigger than the available ram to hold the stack, in which case you'll need to write the stack structure to a temporary file whenever it reaches some threshold memory usage.
The following code should do the necessary inversion:
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *fd;
char len[400];
int i;
char *filename = argv[1];
int ch;
int count;
fd = fopen(filename, "r");
fseek(fd, 0, SEEK_END);
while (ftell(fd) > 1 ){
fseek(fd, -2, SEEK_CUR);
if(ftell(fd) <= 2)
break;
ch =fgetc(fd);
count = 0;
while(ch != '\n'){
len[count++] = ch;
if(ftell(fd) < 2)
break;
fseek(fd, -2, SEEK_CUR);
ch =fgetc(fd);
}
for (i =count -1 ; i >= 0 && count > 0 ; i--)
printf("%c", len[i]);
printf("\n");
}
fclose(fd);
}
The following works for me on Linux, where the text file line separator is "\n".
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void readfileinreverse(FILE *fp)
{
int i, size, start, loop, counter;
char *buffer;
char line[256];
start = 0;
fseek(fp, 0, SEEK_END);
size = ftell(fp);
buffer = malloc((size+1) * sizeof(char));
for (i=0; i< size; i++)
{
fseek(fp, size-1-i, SEEK_SET);
buffer[i] = fgetc(fp);
if(buffer[i] == 10)
{
if(i != 0)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && (buffer[loop] == 10))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
start = i;
printf("%s\n",line);
}
}
}
if(i > start)
{
counter = 0;
for(loop = i; loop > start; loop--)
{
if((counter == 0) && ((buffer[loop] == 10) || (buffer[loop] == 0)))
{
continue;
}
line[counter] = buffer[loop];
counter++;
}
line[counter] = 0;
printf("%s\n",line);
return;
}
}
int main()
{
FILE *fp = fopen("./1.txt","r");
readfileinreverse(fp);
return 0;
}
Maybe , The does the trick , It reverse content of the file in whole
just like a string
Define a variable of type string with size of your file
Get Contents of the file and store in the variable
Use strrev() to reverse the string.
You can later on display the output or even write it to a file. The code goes like this:
#include <stdio.h>
#include <String.h>
int main(){
FILE *file;
char all[1000];
// give any name to read in reverse order
file = fopen("anyFile.txt","r");
// gets all the content and stores in variable all
fscanf(file,"%[]",all);
// Content of the file
printf("Content Of the file %s",all);
// reverse the string
printf("%s",strrev(all));
fclose(file);
return 0;
}
I know this question has been awnsered, but the accepted awnser does not contain a code snippet and the other snippets feel too complex.
This is my implementation:
#include <stdio.h>
long file_size(FILE* f) {
fseek(f, 0, SEEK_END); // seek to end of file
long size = ftell(f); // get current file pointer
fseek(f, 0, SEEK_SET); // seek back to beginning of file
return size;
}
int main(int argc, char* argv[]) {
FILE *in_file = fopen(argv[1], "r");
long in_file_size = file_size(in_file);
printf("Got file size: %ld\n", in_file_size);
// Start from end of file
fseek(in_file, -1, SEEK_END); // seek to end of file
for (int i = in_file_size; i > 0; i--) {
char current_char = fgetc(in_file); // This progresses the seek location
printf("Got char: |%c| with hex: |%x|\n", current_char, current_char);
fseek(in_file, -2, SEEK_CUR); // Go back 2 bytes (1 to compensate)
}
printf("Done\n");
fclose(in_file);
}

read text file and show text line in random

I want a code to read a text file that is include some question and then select one of the questions in random and show for user till all of the question shows;
For example question:
How old are you?
Where are you from?
Now, this is my code but i don't Know to continue.
int main()
{
int i = 0, line = 5;
char ch[1000];
char *str;
time_t t;
srand((unsigned) time(&t));
FILE *myfile;
myfile = fopen("question.txt","r");
if (myfile== NULL)
{
printf("can not open file \n");
return 1;
}
while (fgets(ch,1000, myfile)!=NULL)
printf("%s",ch);
fclose(myfile);
line = 5;
int counter;
for( i = 0 ; i < line ; i++ ) {
counter = rand() % 6;
printf("first question: %s\n", ch[counter]);
}
return 0;
}
How can i to continue?
I'd read the enitire file into a contiguous block of memory, then count the number of lines in the file (in memory) , then make an array of pointers - one pointer to each line and change all the '\n's to `'\0``s .
Finally I'd pick pointers from the array in a random order (using a basic shuffle algorithm) and display the question pointed to to the user.
if the list of questions is too big to fit in memory, the user will probably fall asleep before answering them all so, I'm assuming that won't happen.

reading text file, copying into array in C

The code is supposed to read a user-inputted text file name, copy every character into a multidimensional array, then display it with standard output. It compiles, but produces unintelligible text. Am I missing something?
for (i = 0; i < BIGGEST; i++) {
for (j = 0; j < BIGGESTL; j++) {
if (fgetc(array, fp) ) != EOF)
array[i][j] = c;
else array[i][j] = '\0'
}
fclose(fp);
return 0;
}
You stop filling the array when you encounter EOF, but you print the full array out no matter what.
If the data read from the file is smaller than the input array, you will read that data in and then print that data out, plus whatever random characters were in the memory locations that you do not overwrite with data from the file.
Since the requirement seems to be to print text data, you could insert a special marker in the array (e.g. '\0') to indicate the position where you encountered EOF, and stop displaying data when you reach that marker.
You had better read each line from file
For example:
int i = 0;
while(fgets(text[i],1000,fp))
{
i++;
}
Though the question is edited and only part of the code is left in question. I am posting more than what is required for the question at the moment.
Reason being, there can be numberous improvements to originally posted full code.
In main() function:
You need to check for the argc value to be equal to 2 for your purpose and only then read in value of argv[1] . Else if program executed without the command-line-argument which is file_name in this case, invalid memory read occurs, resulting in segmentation fault if you read in argv[1].
In read_file_and_show_the contents() function:
Stop reading file if end of file is reached or maximum characters is read and store in the character array.
Below Program will help you visualize:
#include <stdio.h>
/*Max number of characters to be read/write from file*/
#define MAX_CHAR_FOR_FILE_OPERATION 1000000
int read_and_show_the_file(char *filename)
{
FILE *fp;
char text[MAX_CHAR_FOR_FILE_OPERATION];
int i;
fp = fopen(filename, "r");
if(fp == NULL)
{
printf("File Pointer is invalid\n");
return -1;
}
//Ensure array write starts from beginning
i = 0;
//Read over file contents until either EOF is reached or maximum characters is read and store in character array
while( (fgets(&text[i++],sizeof(char)+1,fp) != NULL) && (i<MAX_CHAR_FOR_FILE_OPERATION) ) ;
//Ensure array read starts from beginning
i = 0;
while((text[i] != '\0') && (i<MAX_CHAR_FOR_FILE_OPERATION) )
{
printf("%c",text[i++]);
}
fclose(fp);
return 0;
}
int main(int argc, char *argv[])
{
if(argc != 2)
{
printf("Execute the program along with file name to be read and printed. \n\
\rFormat : \"%s <file-name>\"\n",argv[0]);
return -1;
}
char *filename = argv[1];
if( (read_and_show_the_file(filename)) == 0)
{
printf("File Read and Print to stdout is successful\n");
}
return 0;
}

Weird Scanf Issue

I am trying to finish a homework program that compares a string with a text file, so the user can essentially search the text file for the search term (string) in the file. I'm getting there :)
However today I'm running into a very weird issue. When it asks for the term to search for I input the text, but it never ends. I could type all day long and it still asks for input. What weird issue(s) am I overlooking? Fresh pair of eyes might help :)
/*
ask the user for a word
convert user word to LOWER CASE
open output file
open input file
test to be sure input file is open
search for target word and keep count --> how??
print results to monitor
write results to file
close files
*/
#include<stdio.h>
#include<stdlib.h>
int main (void)
{
//declare
int i =0;
int count = 0;
/*************************************************************
working with arrays and strings
*************************************************************/
char mystring[50]; //what user puts in
char target[50]; //the word in the file we are looking for
printf("input your message ");
scanf("%s", mystring);
//printf("%s", mystring);
/*************************************************************
find file, write to it, output the string, end and close file
**************************************************************/
//define text file to use
FILE *cfile;
//name of file == file
cfile = fopen("./thanksgiving_proclamation.txt", "a");
//error handling if file does not exist
if(cfile == NULL) printf("Cannot open file");
/*************************************************************
parse through file and search for string
**************************************************************/
//convert string to lowercase
for(i = 0; i < /*strlen(mystring)*/ 500; i++)//convert to string length
{
if(target[i] >= 'A' && target[i] <='Z')
//convert char between a and z into lowercase
target[i] = target[i] + 32; //makes uppercase char
}
//compare our strings
do{
//scan through file
fscanf(cfile, "%s", mystring);
//convert string to lowercase
for(i = 0; i < /*strlen(mystring)*/ 300; i++)//convert to string length
{
if(mystring[i] >= 'A' && mystring[i] <='Z')
//convert char between a and z into lowercase
mystring[i] = mystring[i] + 32; //makes uppercase char
}
if(strcmp(mystring, target) == 0)
count++;
}while(!feof(cfile));
//while(strcmp(target,"quit")!=0)//end loop
//print to file
fprintf(cfile, "%s", mystring);
//close file
fclose(cfile);
//show user file has been written
printf("\nSuccess. File has been written\n");
printf("Press Enter to Continue...");
getchar();
return 0;
}
You open the file in append mode:
cfile = fopen("...", "a");
and then you try to read from it.
fscanf(cfile, "%s", mystring);
For a first attempt at solving the problem, I'd try to open the file for reading, read from it inside the loop and close the file. Then open it again, this time for appending to add the mystring there (and fclose it).
Once that works, if you want to, try to see if opening in "reading and appending mode" works ...
cfile = fopen("...", "a+");
You don't need "&mystring", "mystring" is already the address of the array.
It would be better to use gets or getline.
You are reading the search string into mystring, but then you are also reading the file contents into mystring.
I think pmg has hit on the actual problem; you've opened the file in append mode, and according to my copy of H&S reading from an append stream is not permitted. You'd have to open it "a+" (append/update) in order to read and write the stream.
You should always check the result of the *scanf() call (fscanf(), sscanf(), scanf(), etc.) for success before checking feof() or ferror(), and you should never make feof() the loop test condition (since it won't return true until after you've attempted to read past the end of the file, your loop will always execute once too many times).
I'd change your loop to something like this:
for(;;)
{
if (fscanf(cfile, "%s", mystring) != 1)
{
if (feof(cfile))
{
fprintf(stderr, "Reached end of file!\n");
break; // exit loop
}
if (ferror(cfile))
{
fprintf(stderr, "Error while reading from file!\n");
break;
}
}
/**
* continue as before
*/
}
It ends when you hit Enter and only stores characters till a whitespace.

Resources