C - regarding the EOF function - c

I am trying to mess around with file input in C, mainly with integer values in a matrix format. For instance, if I have a file like...
4 5 7 3
6 8 5 2
5 7 3 4
9 4 8 7
I am confused as to what the EOF command will do. I know I can use it to check for end of file, but what if I wanted to test the end of a row? What if I wanted to print the diagonal right to left ( so 3,5,7,9 ). I know I would have to go row by row, set a counter that counts at each iteration to find the length of the rows, print out the last value of that row, then deduct the pointer by 1 and go onto the next row. But how can I do this? As in, is EOF only for the file as a whole, or is there a C command that can more directly define row lengths and such.

A typical C program that reads multiple lines would look something like this:
char line[MAX_LINE_SIZE];
while (fgets(line, sizeof(line), inputFile) != NULL)
{
/* Do something with line */
}
The part that says "Do something with line" is where you should do something. One thing to do in your case would be to parse the line, and get one of the numbers in it. Which one would depend on the line number (which you have to keep track of your self), so the first number for the first line, the second number for the second line, etc. Then when you have all numbers (i.e. when the loop ends) you do what you want with the data.
After the loop ends, you can use feof or ferror to see if it ended because of end-of-file or an error.

When scanning through a file, you can separate the file into lines by splitting the file on the \n token. This is a newline and is present at the end of every line. Also, you can split on the \t token. This represents a tab.

#include <stdio.h>
#include <ctype.h>
#define MAX_DIGIT_OFLINE 10
#define EOR '\n' //END OF ROW
int main(){
char digits[MAX_DIGIT_OFLINE];
FILE *fp;
fp = fopen("data.txt", "r");
int n=0,last=-1;
for(;;){
int ch = fgetc(fp);
if(isdigit(ch)){
digits[n++] = ch;
} else if(ch == EOR || ch == EOF){
last = (last==-1) ? n -1: last -1;
putchar(digits[last]);
if(ch == EOF) break;
n = 0;
}
}
fclose(fp);
putchar(EOR);
return 0;
}

Related

How to use EOF as the condition to finish the loop? In C

I'm making somewhat like an othello game. I receive a file that contains strings, and i have to read and process them, making the board as it goes.
Example of the file received:
Alejandro,B
Federico,N
B
D6
C4
G5
then i would convert the characters to numbers, so it can fit in the int board[8][8] i use
I was expecting that when it reaches the EOF it would get out of the loop, but instead it never stops the loop and keeps reapeting the last line with the printf.
This is in the main function:
while( EOF != 1 && *error != 1)
{
tomaJugada(&fp,jugada); //takes 1 line of the file
toupper(jugada[0]);
int columna = convierte_a_int(jugada[0])-1; //converts the letter to a number
int fila = (jugada[1]-'0')-1; //converts the char number to int number
printf("columna %i, fila %i \n",columna, fila);
}
This is the auxiliary function:
void tomaJugada(FILE** fp, char jugada[])
{
fgets(jugada,5,*fp);
jugada[2] = '\0';
//jugada[strcspn(jugada, "\n")] = 0;
}
I have seen people using thi:
int ch = getc(fp);
  while (ch != EOF){...
but it would consumme data that i need to use, maybe i'm using it wrong?
Resumming: i want to use all the data in the file, reach de EOF, and end the loop. How can i put the condition for the EOF?
I hope i explained myself well, i appreciate any help
EOF in c is just a constant (typically -1), EOF != 1 would always evaluate to the same (that is guaranteed to be true as EOF will always be negative). What you need to do is to check if fgets returns null pointer (that is in the tomaJugada function) and when that happens, then either an error occurred or you've reached the end of the file. To disambiguate between the two you could use the feof function for instance.

C Programming - File io parsing strings using sscanff

I am trying to do the following the C programming language, any help or if you can finish the code I will be greatly appreciated:
I am trying to write a program in C programming language that uses file io, that will parse through the words using sscanf function and output each word in all the sentences inside a txt document (bar.txt). Here is the instructions.
Write a program that opens the file bar.txt name the program "reader". Pass a parameter to indicate lines to read. Read all the lines in the file based on the parameter 'lines' into a buffer and using sscanf parse all the words of the sentences into different string* variables. Print each of the words to the screen followed by a carriage return. You can hardwire filename (path of bar.xt) or use option to enter filename.
This is the txt file (bar.txt) i am working with:
bar.txt
this is the first sentence
this is the 2nd sentence
this is the 3rd sentence
this is the 4th sentence
this is the 5th sentence
end of file: bar.txt
usage of argv: Usage: updater [-f "filename"] 'lines'
-f is optional (if not provided have a hardwired name from previous program 2 (bar.txt))
'lines' integer from 1 to 10 (remember the files has 5-10 strings from previous program)
a sample input example for the input into the program is:
./reader -f bar.txt 1
OUTPUT:
Opening file "bar.txt"
File Sentence 1 word 1 = this
File Sentence 1 word 2 = is
File Sentence 1 word 3 = the
File Sentence 1 word 4 = first
File Sentence 1 word 5 = sentence
another example
./reader -f bar.txt 5
OUTPUT:
File Sentence 5 word 1 = this
File Sentence 5 word 2 = is
File Sentence 5 word 3 = the
File Sentence 5 word 4 = 5th
File Sentence 5 word 5 = sentence
Examples of commands:
./reader -f bar.txt 5
./reader -f bar.txt 2
./reader -f bar.txt 7
./reader 2
./reader 5
./reader 8
./reader 11
this is the code that I have so far please fix the code to show the desired output:
#include <stdlib.h>
#include <stdio.h>
#define MAXCHAR 1000
int main(int argc, char *argv[]) {
FILE *file;
char string[MAXCHAR];
char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
int integer = argv[3][0] - 48;
int i; //for loops
if (argv[1][0] == '-' && argv[1][1] == 'f')
{
file = fopen(filename, "r");
if (file == NULL){
printf("Could not open file %s",filename);
return 1;
}
while (fgets(string, MAXCHAR, file) != NULL)
printf("%s", string);
fclose(file);
return 0;
}
}
You need to get the filename from argv if they use the -f option. And you need to get the number of lines from a different argument depending on whether this option was supplied.
Use strcmp() to compare strings, rather than testing each character separately. And use atoi() to convert the lines argument to an integer, since your method only works for single-digit numbers.
#include <stdlib.h>
#include <stdio.h>
#define MAXCHAR 1000
function usage() {
fprintf(stderr, "Usage: reader [-f filename] lines\n");
exit(1);
}
int main(int argc, char *argv[]) {
FILE *file;
char string[MAXCHAR];
char* filename = "c:\\cprogram\\fileio-activity\\bar.txt";
int integer;
int i; //for loops
if (argc < 2) {
usage();
}
# Process arguments
if (strcmp(argv[1], "-f") == 0)
{
if (argc < 4) {
usage();
}
filename = argv[2];
integer = atoi(argv[3]);
} else {
integer = atoi(argc[1]);
}
file = fopen(filename, "r");
if (file == NULL){
fprintf(stderr, "Could not open file %s\n",filename);
return 1;
}
while (fgets(string, MAXCHAR, file) != NULL)
printf("%s", string);
fclose(file);
return 0;
}
To add to what Barmar already answered, for the further steps in completing the assignment:
Splitting a string into separate words is usually called tokenization, and we normally use strtok() for this. There are several ways how one can use sscanf() to do it. For example:
Use sscanf(string, "%s %s %s", word1, word2, word3) with however many word buffers you might need. (If you use e.g. char word1[100], then use %99s, to avoid buffer overrun bugs. One character must be reserved for the end-of-string character \0.)
The return value of sscanf() tells you how many words it copied to the word buffers. However, if string contains more than the number of words you specified, the extra ones are lost.
If the exercise specifies the maximum length of strings, say N, then you know there can be at most N/2+1 words, each of maximum length N, because each consecutive pair of words must be separated by at least one space or other whitespace character.
  
Use sscanf(string + off, " %s%n", word, &len) to obtain each word in a loop. It will return 1 (with int len set to a positive number) for each new word, and 0 or EOF when string starting at off does not contain any more words.
The idea is that for each new word, you increment off by len, thus examining the rest of string in each iteration.
  
Use sscanf(string + off, " %n%*s%n", &start, &end) with int start, end to obtain the range of positions containing the next word. Set start = -1 and end = -1 before the call, and repeat as long as end > start after the call. Advance to next word by adding end to off.
The beginning of the next word (when start >= 0) is then string + start, and it has end - start characters.
To "emulate" strtok() behaviour, one can temporarily save the terminating character (which can be whitespace or the end of string character) by using e.g. char saved = string[off + end];, then replace it with an end-of-string character, string[off + end] = '\0';, so that (string + start) is a pointer to the word, just like strtok() returns. Before the next scan, one does string[off + end] = saved; to restore the saved character, and off += end; to advance to the next word. 
The first one is the easiest, but is the least useful in practical programs. (It works fine, but we do not usually know beforehand the string length and word count limitations.)
The second one is very useful when you have alternate patterns you can try for the next "word" or item; for example, when reading 2D or 3D vectors (points in a plane, or in three-dimensional space), you can support multiple different formats from <1 2 3> to [1,2,3] to 1 2 3, by trying to parse the most complicated/longest first, and trying the next one, until one of them works. (If none of them work, then the input is in error, of course.)
The third one is most useful in that it describes essentially how strtok() works, and what its side effects are. (It's saved character is hidden internally as a static variable.)

fscanf() how to go in the next line?

So I have a wall of text in a file and I need to recognize some words that are between the $ sign and call them as numbers then print the modified text in another file along with what the numbers correspond to.
Also lines are not defined and columns should be max 80 characters.
Ex:
I $like$ cats.
I [1] cats.
[1] --> like
That's what I did:
#include <stdio.h>
#include <stdlib.h>
#define N 80
#define MAX 9999
int main()
{
FILE *fp;
int i=0,count=0;
char matr[MAX][N];
if((fp = fopen("text.txt","r")) == NULL){
printf("Error.");
exit(EXIT_FAILURE);
}
while((fscanf(fp,"%s",matr[i])) != EOF){
printf("%s ",matr[i]);
if(matr[i] == '\0')
printf("\n");
//I was thinking maybe to find two $ but Idk how to replace the entire word
/*
if(matr[i] == '$')
count++;
if(count == 2){
...code...
}
*/
i++;
}
fclose(fp);
return 0;
}
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array..also I don't know how to replace $word$ with a number.
Not only will fscanf("%s") read one whitespace-delimited string at a time, it will also eat all whitespace between those strings, including line terminators. If you want to reproduce the input whitespace in the output, as your example suggests you do, then you need a different approach.
Also lines are not defined and columns should be max 80 characters.
I take that to mean the number of lines is not known in advance, and that it is acceptable to assume that no line will contain more than 80 characters (not counting any line terminator).
When you say
My problem is that fscanf doesn't recognize '\0' so it doesn't go in the next line when I print the array
I suppose you're talking about this code:
char matr[MAX][N];
/* ... */
if(matr[i] == '\0')
Given that declaration for matr, the given condition will always evaluate to false, regardless of any other consideration. fscanf() does not factor in at all. The type of matr[i] is char[N], an array of N elements of type char. That evaluates to a pointer to the first element of the array, which pointer will never be NULL. It looks like you're trying to determine when to write a newline, but nothing remotely resembling this approach can do that.
I suggest you start by taking #Barmar's advice to read line-by-line via fgets(). That might look like so:
char line[N+2]; /* N + 2 leaves space for both newline and string terminator */
if (fgets(line, sizeof(line), fp) != NULL) {
/* one line read; handle it ... */
} else {
/* handle end-of-file or I/O error */
}
Then for each line you read, parse out the "$word$" tokens by whatever means you like, and output the needed results (everything but the $-delimited tokens verbatim; the bracket substitution number for each token). Of course, you'll need to memorialize the substitution tokens for later output. Remember to make copies of those, as the buffer will be overwritten on each read (if done as I suggest above).
fscanf() does recognize '\0', under select circumstances, but that is not the issue here.
Code needs to detect '\n'. fscanf(fp,"%s"... will not do that. The first thing "%s" directs is to consume (and not save) any leading white-space including '\n'. Read a line of text with fgets().
Simple read 1 line at a time. Then march down the buffer looking for words.
Following uses "%n" to track how far in the buffer scanning stopped.
// more room for \n \0
#define BUF_SIZE (N + 1 + 1)
char buffer[BUF_SIZE];
while (fgets(buffer, sizeof buffer, stdin) != NULL) {
char *p = buffer;
char word[sizeof buffer];
int n;
while (sscanf(p, "%s%n", word, &n) == 1) {
// do something with word
if (strcmp(word, "$zero$") == 0) fputs("0", stdout);
else if (strcmp(word, "$one$") == 0) fputs("1", stdout);
else fputs(word, stdout);
fputc(' ', stdout);
p += n;
}
fputc('\n', stdout);
}
Use fread() to read the file contents to a char[] buffer. Then iterate through this buffer and whenever you find a $ you perform a strncmp to detect with which value to replace it (keep in mind, that there is a 2nd $ at the end of the word). To replace $word$ with a number you need to either shrink or extend the buffer at the position of the word - this depends on the string size of the number in ascii format (look solutions up on google, normally you should be able to use memmove). Then you can write the number to the cave, that arose from extending the buffer (just overwrite the $word$ aswell).
Then write the buffer to the file, overwriting all its previous contents.

C Resetting data counters in FOR loop

I've got a very large text file that I'm trying to do word analysis on. Among word count, I might be looking for other information as well, but I left that out for simplicity.
In this text file I have blocks of text separated by asterisks '*'. The code I have below scans the text file and prints out # of characters and words as it should, but I'd like to reset the counter after an asterisk is met, and store all information in a table of some sort. I'm not so worried on how I'll make the table as much as I am unsure of how to loop the same counting code for each text block between asterisks.
Maybe a for loop like
for (arr = strstr(arr, "*"); arr; arr = strstr(arr + strlen("*"), "*"))
Example text file:
=-=-=-=-=-=-=-=-=-=-=-=-=-=-
I have a sentence. I have two sentences now.
*
I have another sentence. And another.
*
I'd like to count the amount of words and characters from the asterisk above this
one until the next asterkisk, not including the count from the last one.
*
...
...
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
(EOF)
Desired output:
*# #words #alphaChar
----------------------------
1 9 34
-----------------------------
2 5 30
-----------------------------
3 28 124
...
...
I have tried
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main()
{
int characterCount=0;
int counterPosition, wordCount=0, alphaCount=0;
//input file
FILE *file= fopen("test.txt", "r");
if (file== NULL)
printf("Cannot find the file.\n");
//Count total number of characters in file
while (1)
{
counterPosition = fgetc(speechFile);
if (counterPosition == EOF)
break;
++characterCount;
}
rewind(file); // Sends the pointer to the beginning of the file
//Dynamically allocate since array size cant be variable
char *arr= ( char*) malloc(totalCharacterCount);
while(fscanf(speechFile, "%c", &arr[i]) != EOF ) //Scan until the end of file.
i++; //increment, storing each character in a unique position
for(i = 0; i <characterCount; i++)
{
if(arr[i] == ' ') //count words
wordCount++;
if(isalpha(arr[i])) //count letters only
alphaCount++;
}//end for loop
printf("word count is %d and alpha count is %d", wordCount,alphaCount);
}
Since you are having full files text in array arr[], you need to divide that string arr using * as delimiter. you can use strtok() to divide that string using * as delimiter. Then perform the word count and character count operation on each token. read this link to know about strtok.

Program to read a code and count the number of lines in it,do not include comments and blank lines in count

I am trying to create a program which, given an input file, returns the count of all the lines of code in the input file, excluding blank lines and comment lines. I have written the following code, however I need help with how to exclude lines containing comments and blank lines.
#include<stdio.h>
int main()
{
int count;
char ch;
FILE *fptr;
clrscr();
fp=fopen("test.cpp","r");
if(fp==EOF)
{
perror("Error:");
}
else
{
while(ch!=EOF)
{
ch=fgetc(fptr);
if(ch=='\n')
count++;
if(ch=='\\')
count--;
if(ch=='\*')
{
while(ch!='*\')
{
ch=fgetc(fptr);
}
}
}
printf("the lines in the code are %d\n",count);
fclose (fptr)
}
getchar();
return 0;
}
How can I modify the above code so that blank lines and comment lines are not counted?
If you read the input file character by character, you'll have a lot more work than if you read it line by line. After all you're counting lines ...
psudocode
1. initialize line count to 0
2. read a line
3. end of file? yes: goto 7
4. is it a good line? yes: goto 5; no: goto 2
5. increment line count
6. repeat from 2
7. output line count
Now you ask ... what is a good line?
For an approximation of the program, I suggest you consider a line everything except lines composed of 0 or more whitespace. This approximation will count comments, but you can develop your program from here.
The following version ignores lines with // coments on an otherwise empty line.
Version 3 could ignore lines containing both /* and */
and version 4 would deal with multi line comments.
Above all, have fun!
C comments are // and /* */. The following lines are where your problem is:
if(ch=='\\')
count--;
if(ch=='\*')
while(ch!='*\')
ch=fgetc(fptr);
The other problem is that you can't match a two-character comment delimiter by reading a character at a time without some sort of state machine.
Also, your code should cater for the case where comments are embedded in real lines of code. eg.
x = 1; // Set value of x
You'd be far better off reading the file a line at a time, and checking whether or not each line is blank or a comment, and incrementing a counter if not.
you mean //, /* and */ instead of \ * and *\
the \ is used as an escape character, which changes the "meaning" of the character after it.
\n gives you a newline. with \\ you get a single \ and with \' you get something that doesn't close the opening '
If you replace those comment-characters with the correct one you should get code that will compile.
But it wont count correctly.
Imagine a line like this:
doSomething(); // foo
Apart from your problems with character constants you have errors in the way you deal with fputc. fputc returns an int. It can return either EOF which is a negative integer constant if there were no remaining characters to red or there was an error, or it can return the value of the character read as an unsigned char and converted to a int.
If you convert the return value of fputc to char before comparing it to EOF then a valid character might compare as equal to EOF causing premature termination of your loop.
Also, not that the while loop starts before the first call to fputc so you are using the uninitialized value of ch in the first iteration. This could cause anything to happen.
The idiomatic way to form the loop would be:
int ch;
while ((ch = fgetc()) != EOF)
{
/* ... */
}
In side the loop you need to be careful in the comparison of the returned value due to the way the fact that ch is the unsigned char converted to an int.
On most platforms the simplest thing to do would be to create a char variable for comparison purposes although you could put your character constants throught the same unsigned char to int conversion routine.
E.g.
char c = ch;
if (c == '\n')
or
if (ch == (unsigned char)'\n')
Others have pointed out the problems with your character literals.
Well, part of the problem is that your ch variable is only a character in length, but when you test for comments, such as \\ and \*, these are two characters long, and thus need to use string comparison.
Another problem is that one-line comments in C/C++ actually start with //, and multi-line comments start with /* and end with */.
You can write something like this in Python:
def goodline(l : str) -> int:
if l.lstrip().startswith("/*") and l.rstrip().endswith("*/"):
# single line
return 0
elif l.lstrip().startswith("/*") and not l.rstrip().endswith("*/"):
# multi line start
return 1
elif not l.lstrip().startswith("/*") and l.rstrip().endswith("*/"):
# multi line end
return 2
elif l.strip() == "":
# empty line
return 3
elif l.lstrip().startswith("//"):
# single line
return 0
else:
# good line
return 4
if return from above function is 1, keep iterating on lines until return becomes 2.

Resources