I am trying to read a text file using the FILE* type. Everything is fine, except with the fgetc() function.
In fact, I'd like to check how many '\n' characters are there in the file, but the function never returns that value even though there is one in the file I'm reading. Has someone ever experienced this situation?
The code i'm using is the following:
char ch;
while (ch!=EOF) {
ch = (char) fgetc(gl_file);
if(ch=='\n') newline_counter++;
}
newline_counter remains 0.
You don't initialize ch before checking its value and ch is char while fgetc returns int.
Rewrite to something like:
int ch;
while ((ch = fgetc(fp)) != EOF)
{
if(ch == '\n')
++newline_counter;
}
no need to cast returned value from fgetc. use getc instead of fgetc :
getc() is equivalent to fgetc() except that it may be implemented as a macro which evaluates stream more than once.
char ch = getc(fp);
do{
if (ch == '\n') ++newline_counter;
} while ((ch = getc(fp)) != EOF);
or you can use getline():
getline() reads an entire line from stream.
char *ch = NULL;
size_t len = 0;
while (getline(&ch, &len, file) != -1)
++line;
If *ch is set to NULL and *len is set 0 before the call, then getline() will allocate a buffer for storing the line.
Related
a new empty file:
touch /file.txt
read. print.
fp = fopen("/file.txt", "r");
char text[1000];
int i=0;
while(!feof(fp)){
text[i++] = getc(fp);
}
text[i]='\0';
printf("%s\n", text);
result:
ÿ
EXTRA INFO : if file.txt had many lines.. it would have appended that strange character at the very bottom of it. so perhaps it is not something that happens on every "while loop".
If you're using ISO 8859-15 or 8859-1 code set, the ÿ (LATIN SMALL LETTER Y WITH DIAERESIS, U+00FF in Unicode) has code 25510 or 0xFF. When you store EOF in the array, it gets converted to ÿ.
Don't store EOF in a char. And remember that getchar() returns an int, not a char. It has to be able to return every value that can be stored in an unsigned char, plus EOF which is negative (usually but not necessarily -1).
And, as noted in the comments, while (!feof(file)) is always wrong. This is just another reason why.
This code is fixed, more or less. It really should report an error if it fails to open the file. Note that it also ensures you don't overflow the buffer.
FILE *fp = fopen("/file.txt", "r");
if (fp != 0)
{
char text[1000];
int i=0;
int c;
while ((c = getc(fp)) != EOF && i < sizeof(text)-1)
text[i++] = c;
text[i]='\0';
printf("%s\n", text);
fclose(fp);
}
See also while ((c = getc(file)) != EOF) loop won't stop executing.
The ÿ is the byte 255 in your codepage, which is the constant EOF coerced into a char. Instead of using feof, you must store the return value of getc into an int, then compare it against EOF, here's an easy-to-read example (notice that you'd have to have bounds-checking too):
while (1) {
int c = getc(fp);
if (c == EOF) {
break;
}
text[i++] = c;
}
My input stream is from a text file with a list of words separated by the \n character.
The function stringcompare is a function that will compare the equivalence of two strings, case insensitive.
I have two string arrays, word[50] and dict[50]. word is a string that would be given by the user.
Basically what I want to do is pass word[] and each word in the text file as arguments of the stringcompare function.
I've compiled and run this code but it is wrong. Very wrong. What am I doing wrong? Can I even use fgetc() like this? would dict[] even be a string array after the inner loop is done?
char c, r;
while((c = fgetc(in)) != EOF){
while((r = fgetc(in)) != '\n'){
dict[n] = r;
n++;
}
dict[n+1] = '\0'; //is this necessary?
stringcompare(word, dict);
}
It is wrong.
The return value of fgetc() should be stored to int, not char, especially when it will be compared with EOF.
You might forgot to initialize n.
You will miss the first character of each line, which is stored to c.
Use dict[n] = '\0'; instead of dict[n+1] = '\0'; because n is already incremented in the loop.
Possible fix:
int c, r;
while((c = fgetc(in)) != EOF){
ungetc(c, in); // push the read character back to the stream for reading by fgetc later
n = 0;
// add check for EOF and buffer overrun for safety
while((r = fgetc(in)) != '\n' && r != EOF && n + 1 < sizeof(dict) / sizeof(dict[0])){
dict[n] = r;
n++;
}
dict[n] = '\0'; //this is necessary
stringcompare(word, dict);
}
I know I can get the first character of a line of standard input by using getchar(), but I only want the first character of each line. Is there a function I can use to get rid of the rest of the string entered into standard input (if it is more than one character)? if not, what methodology should I consider using to get rid of the rest of the standard input line?
char buf[100];
while(fgets(buf,sizeof(buf),stdin) != NULL)
{
if(strlen(buf)>0)
buf[1] = '\0';
printf("%s",buf);
}
Read the whole line using fgets() and just nul terminate it after the first character.
#include <stdio.h>
int main(void)
{
int ch;
size_t len;
for (len = 0; 1; ) {
ch = getc(stdin);
if (ch == EOF) break;
if (!len++) putc(ch, stdout); /* the first character on a line */
if (ch == '\n') len = 0; /* the line has ended */
}
return 0;
}
Please note that the first character on a line can actually be a '\n' !!!
// Get the character you need
char c = getchar();
// Skip the rest
int a;
while((a = getchar()) != '\n' && a != EOF);
If you know how many lines you'll have, you can put it in a loop.
I'm trying to read the first character of a file and whenever it's equal to '(' I should skip that line else get the first character from that line. I'm under a mac and I can make use of fgetln.
FILE *file = fopen("test.txt", "r");
char c;
while(fscanf(file, "%s", &c) != EOF) {
if (c != '(')
printf("%c", c);
}
That's my current code. I don't know how to skip lines, although I've tried to get the whole line and checked only the first char solving the skip problem. However this is not working I'm getting strange characters in my console instead of the ones inside test.txt. How should I do that?
The problem with using %s format specifier of fscanf is that is splits on spaces, not only on end-of-line characters. Moreover, reading it in a single-character buffer will nearly always produce undefined behavior.
There are several ways to solve this problem, using different APIs:
You could replace %s with %200[^\n], and passing a 201-character buffer instead of c,
Using fgets with a properly-sized buffer, and picking the initial character, or
Using a character-based API, and setting a "take next" flag each time that you see a '\n' character:
Here is how you can implement the third approach:
bool takeNext = true;
int ch;
while ((ch = fgetc(file)) != EOF) {
if (takeNext && ch != '(') {
printf("%c", ch);
}
takeNext = (ch == '\n');
}
Here is a slightly longer character-based approach, which conditions on whether the first character in a line is ( or not.
If it is (, then we consume everything up to and including the next newline without outputting.
If it not, then we do the same thing but we output the characters as we read them.
#include <stdio.h>
int main(){
FILE *file = fopen("test.txt", "r");
int c;
while((c = getc(file)) != -1) {
if (c == '(') {
// Skip until the next newline
do {
c = getc(file);
} while (c != -1 && c != '\n');
continue;
}
else {
putchar(c);
do {
c = getc(file);
putchar(c);
} while (c != -1 && c != '\n');
}
}
fclose(file);
}
Change c to string because fscanf reads string. See if the 1st character of c matches with (.
If it does not then print the line else skip the line.
FILE *file = fopen("test.txt", "r");
char c[100];
while(fscanf(file, "%s", c)) {
if (c[0] != '(')
printf("%s", c);
}
Use fgets to read whole lines. It is also safer than fscanf as it limits the reading to the buffer size.
To check if the first char is '(' you can refer to it directly:
if (buf[0]=='(')
or
if (*buf=='(')
I am trying to get fgetc to read through a file and skip from a certain indicator until a new line. This seems like a simple question, but I can't find any documentation on it.
Here is an example of my question:
read this in ; skip from semicolon on to new line
My best guess at a solution would be to read in the entire file, and for each line use strtok to skip from ; to the end of the line. Obviously this is horrible inefficient. Any ideas?
*I need to use fgetc or something like fgetc that will parse the file character by character
Easiest thing to do is read the entire line in, then truncate if there a ;.
char buffer[1024], * p ;
if ( fgets(buffer, sizeof(buffer), fin) )
{
if (( p= strchr( buffer, ';' ))) { *p = '\0' ; } // chop off ; and anything after
for ( p= buffer ; ( * p ) ; ++ p )
{
char c= * p ;
// do what you want with each character c here.
}
}
When you do the read, buffer will initially contain:
"read this in ; skip from semicolon on to new line\n\0"
After you find the ; in the line and stick a '\0' there, the buffer looks like:
"read this in \0 skip from semicolon on to new line\n\0"
So the for loop starts at r and stops at the first \0.
//Function of compatible fgets to read up to the character specified by a delimiter.
//However file stream keep going until to newline.
//s : buffer, n : buffer size
char *fgets_delim(char *s, int n, FILE *fp, char delimiter){
int i, ch=fgetc(fp);
if(EOF==ch)return NULL;
for(i=0;i<n-1;++i, ch=fgetc(fp)){
s[i] = ch;
if(ch == '\n'){
s[i+1]='\0';
break;
}
if(ch == EOF){
s[i]='\0';
break;
}
if(ch == delimiter){
s[i]='\0';//s[i]='\n';s[i+1]='\0'
while('\n'!=(ch = fgetc(fp)) && EOF !=ch);//skip
break;
}
}
if(i==n-1)
s[i] = '\0';
return s;
}
Given a requirement to use fgetc(), then you are probably supposed to echo everything up to the first semicolon on the line, and suppress everything from the semicolon to the end of the line. I note in passing that getc() is functionally equivalent to fgetc() and since this code is about to read from standard input and write to standard output, it would be reasonable to use getchar() and putchar(). But rules are rules...
#include <stdio.h>
#include <stdbool.h>
int main(void)
{
int c;
bool read_semicolon = false;
while ((c = fgetc(stdin)) != EOF)
{
if (c == '\n')
{
putchar(c);
read_semicolon = false;
}
else if (c == ';')
read_semicolon = true;
else if (read_semicolon == false)
putchar(c);
/* else suppressed because read_semicolon is true */
}
return 0;
}
If you don't have C99 and <stdbool.h>, you can use int, 0 and 1 in place of bool, false and true respectively. You can use else if (!read_semi_colon) if you prefer.