Reading a text file up to a certain character - c

Here's my dilemma. I have a file, and wish to read in all characters up until the program hits a '#', and ignore everything on that line after the '#'. For example
0 4001232 0 #comment, discard
This is frustrating, as it feels like there is a very simple solution. Thanks!

FILE *f = fopen("file.txt", "r");
int c;
while ((c = getc(f)) != '#' && c != EOF)
putchar(c);

Read a line using fgets, read through this line till you get a '#' character.
Read an another line...

There are plenty of ways and examples of how to do it. Usually, the idea is to have a variable that holds the state (before #, after # , after \n etc.) and run in a while loop until EOF. an example you can see here it's a program to remove C comments, but the idea is the same.

filePointer = fopen("person.txt", "r");
do
{
read = fgetc(filePointer);
//stop when '#' read or when file ends
if (feof(filePointer) || read == '#')
{
break;
}
printf("%c", read);
} while (1);
fclose(filePointer);
also you better check if file opened succesfully
if (filePointer == NULL)
{
printf("person.txt file failed to open.");
}
else
{
file operations
}

The solution depends on how you are "reading" that.
I could, for example, just remove all of those comments with sed 's/#.*//' <infile >outfile in bash.
EDIT: However, if I was parsing it manually, I could simply (in my loop for parsing it) have
if(line[i]=='#') {
continue;
}
which would stop parsing that line by exiting the loop.

Related

Affine Code Errors

So I've been trying to experiement with some decryption algorithms and ciphers and tried to do some of them on my own. At them moment I'm writing in C an affine algorithm which I am trying to decrypt a line from a .txt file which I decrypted myself so here's where I think my problem appears since my code always pops text file corrupted and doesn't proceed to the next task.
file = fopen("encr_affine.txt", "r");
if(file)
{
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
fgets(str,100,file);
if ( fgets(str,100,file) == NULL )
{
fprintf(stderr, "Text file corrupted\n");
return -1;
}
What is the mistake here? Is it reading the whole line of the txt file or just the first char? And why it doesn't proceed on into the next tasks?
Thank you in advance
It always prints your Text file corrupted message because the file is always closed (or never open) when it gets there.
Look what this first part does:
file = fopen("encr_affine.txt", "r");
if(file)
{
while ((c = getc(file)) != EOF)
putchar(c);
fclose(file);
}
It opens the file, then (if it's really open), it reads the entire file, byte by byte, then prints it all to stdout. It then closes the file.
Then you try to do stuff on a closed file:
fgets(str,100,file);
This would do nothing because the file is closed, and would return NULL. If the file were never opened, it would still return NULL due to an error.
But then you try it again:
if ( fgets(str,100,file) == NULL )
{
fprintf(stderr, "Text file corrupted\n");
return -1;
}
This fgets(str,100,file) always returns NULL because once again the file is closed.
Perhaps what you really want to do is to process the bytes one at a time in your first loop before printing them with putchar().

How to add text at the end of line

for example I have test.txt with
test1
test2
at the end of each line I would like to add some text
my code is:
fp = fopen("test.txt", "w");
while ((ch=getc(fp)) != EOF)
if (ch == '\n')
fprintf(fp, "newText");
my output is:
test1
newText
The outcome should be:
test1newText
test2newText
You cannot do it with a single file.
Here is what you need to do:
Open an auxiliary file for temporary output
Read the actual file line by line
For each line write the copy of the line into the auxiliary output
After writing the line write the suffix that you would like to append
Go to the next line until you process the whole file
Once you finished processing the whole file, close both files, and move the auxiliary file in place of the original input.
How to avoid a new line?, I successfully copy [the text] but when I try to add some text at the end of each line, it starts from new line
This is because you include the end-of-line character in your copied text.
If you read character-by-character, do not copy '\n's when you see them; if you read with fgets, check the last character, and skip it if it happens to be '\n' (fgets includes it in its return value).
You can’t read from your output file like that. It is possible to open a file for reading and writing, but it’s an advanced topic and isn’t really appropriate for text files.
The normal approach is to write to another file, and then replace the original if desired. Note that you’ll have to emit all the characters you read and your extra text.
If this is the whole function of the program, consider making it a filter (by using the standard streams); this is what’s expected by experienced users and saves some error checking.
eventually, I have succeed
if (!strcmp(fileName, SWM_DEBUG))
{
fp = fopen(fileName, "r");
fpOut = fopen("tmp.txt", "w");
while ((ch = fgetc(fp)) != EOF)
{
if (ch == '\n')
fprintf(fpOut, "TEST");
fputc(ch, fpOut);
}
}
Thanks for your support ☺
You need to change the fopen call to read from the file and use the fputc function to re-output the character you read, like this:
fp = fopen("test.txt", "r");
while ((ch=fgetc(stdin)) != EOF) {
if (ch == '\n') {
fprintf(fp, "newText");
}
fputc(ch, fp);
}
fprintf(fp, "newText");
As pointed out elsewhere, you can't simultaneously read and write a file in the way you were trying to do, so i've changed it to read from stdin to illustrate the code

Reading lines ahead in a file (In C)

I have a file that looks like this:
This is the first line in the file
This is the third line in the file
Where I have a blank line in the file (On line 2). I want to read the file line by line (Which I do using fgets), but then i want to read ahead just check if a line there is a blank line in the file.
However, My while fgetshas a break statement in it, because my function is only so posed to read the file a line at a time per function call.
so if I call the function:
func(file);
It would read the first line, then break.
If I called it again, it would read the second line then break, etc.
Because I have to implement it this way, it's hard to read ahead, is there any way I can accomplish this?
This is my code:
int main(void) {
FILE * file;
if(file == NULL){perror("test.txt"); return EXIT_FAILURE;}
readALine(file);
}
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
//Read lines ahead to check if there is a line
//which is blank
break; //only read a line each FUNCTION CALL
}
}
So to clarify, if I WAS reading the entire file at once (Only one function call) it would go like this (Which is easy to implement).
int main(void) {
FILE * file = fopen("test.txt","r");
if(file == NULL){perror("test.txt"); return EXIT_FAILURE;}
readALine(file);
}
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if(isspace(buffer[0]) {
printf("Blank line found\n");
}
}
}
But since I'm reading the file in (Line by line, per function call), The second piece of code above wouldn’t work (Since I break per line read, which I can't change).
Is there a way I could use fseek to accomplish this?
A while loop ending in an unconditional break is an if statement, so I don't really see why you are using a while loop. I'm also assuming you are not worried about a single line being longer than 1000 chars.
the continue statement jumps over to the next iteration of the loop and checks the condition again.
void readALine(FILE * file) {
char buffer[1000];
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if(!isspace(buffer[0]) { //note the not operator
//I'm guessing isspace checks for a newline character since otherwise this will be true also for lines beginning with space
continue; //run the same loop again
}
break;
}
//buffer contains the next line except for empty ones here...
}
You can "read ahead" by simply storing your position in the file (with position = ftell(your_file)), then read the line, if this is a blank line do whatever you have to do, and finally go back to the position you were (with fseek(your_file, position, SEEK_SET)).
Hope this helps !
The while loop in readALine reads lines until the end of the file. So it will skip blank lines, and all other lines.
You can return from within the loop if you've found a non-blank line:
while(fgets(buffer,sizeof(buffer),file) != NULL) {
if (buffer[0] != '\n')
return;
}
If you also want to skip lines that consist of nothing but spaces, you can write a function that does that check:
bool isNothingButWhitespace(char *s) {
while (*s == ' ' || *s == '\n')
s++;
return *s == '\0';
}
This will find the first character that's not whitespace. If it's the string terminator '\0' then it will return true (the string was nothing but whitespace) otherwise falseS (there was some non-whitespace character found).
If the while loop in readALine completes due to it reaching the end of file, you need some way to signal that back to the caller. I recommend setting buffer[0] = '\0'.

skip to next line of file ignoring content

hi so i have a program where if there is an # at the begining of the first line of the text file it needs to be ignored, how do you jump to the next line of file? ignoring all that there is after the #?
for example:
#1234
5
I want to print 5 and the rest to be ignored.
I only managed to skip the # if there is nothing behind it
while (a == '#' || a == '\r'|| a == '\n') {
fscanf(inp, "%c", &a);
}
As for your previous question, if your want to ignore comment lines with an initial #, it is highly recommended to read the file line by line with fgets() and to handle non comment lines directly while ignoring comment lines.
It is actually non trivial to do it with fscanf because depending on your format lines, the linefeed may or may not have been consumed.
If you are at the start of a line and want to read the next char while ignoring the comment lines, do this:
int c; // Must be int to accommodate for EOF.
while ((c = getc(inp)) == '#') {
while ((c = getc(inp)) != EOF && c != '\n')
continue;
}
// Here c contains the first char from a non comment line or EOF.
Instead of
while (a == '#' || a == '\r'|| a == '\n') {
fscanf(inp,"%c",&a);
}
Try (pseudo code):
If FirstChar == '#'
Loop/scan until '\n'
On nextline here
If you want to use fscanf().
If better performance is needed, work on buffers directly.

Reading the number of lines in a file

I need to calculate the number of lines in a file , however , I must do that without
the "easy" functions such as : fopen , fscanf ,fgets ... and so on .
Meaning I can't do this :
int calculateLines(char *filename)
{
FILE *myFile;
char c;
int myLines = 0;
myFile = fopen(filename, "r");
if(myFile == NULL)
return 0;
while ((c = fgetc(f)) != EOF)
if(c == '\n')
myLines++;
fclose(f);
if(c != '\n')
myLines++;
return myLines;
}
For that , I can use only the system calls read , write , close , open & fork.
From what I've done so far , I think that :
open the file with open : someResult = wrapper_open(argv[1],O_RDONLY,0);
reading line after line with read : Can I manipulate read somehow to read line after line ? I've tried to check with its tutorial however came empty handed .
You can't really read line-by-line with read. Instead, you'd read in a block of data (which might contain an arbitrary number of lines, and probably some partial lines). Count the new-line characters in that block, then repeat the read/count process 'til you reach the end of the file.

Resources