The objective is to write an int function that returns the number of occurrences of numbers greater than 100 in a text file. The function should receive the file pointer as an argument.
Here is my code so far:
#include <stdio.h>
int function(FILE *infp);
int main ()
{
FILE *infp;
printf("\n%d\n",function(infp));
}
int function(FILE *infp)
{
int num, counter=0;
if ((infp = fopen ("text.txt", "r")) == NULL)
printf ("\ncannot open the file text.txt\n");
while ((num = getc())!=EOF)
{
if (num>100)
counter++;
}
fclose(infp);
return (counter);
}
It is always outputting 0. I'm thinking either getc is not the right command to use here or maybe I am formatting the text file wrong? Any help would be great
here you are using getc() to catch numbers from file but your getc() will give you only one character at a time so
for example :
if your file content is like : "103 9";
then your getc() will give "1" at 1st time then it will give you "0" and then "3"..
in this way you will never be reading a number completely and you are getting one character at a time.
To get rid of this you can use : fscanf(infp, "%d", &num);....
this will give you one complete number in one go.
then you can easily match the numbers.
It's going to be a tad bit of work to do this in C. How about grabbing the text content. Splitting on space. Verifying the correct ASCII characters that represent a base 10 number [48,57] (interval notation), from there you can apply a conversion algorithm, such as atoi
getc() reads the next character from a stream. What you want is to possibly tokenize the file via some delimiter (let's say space). See here for more details.
Related
I need to write a program in C, that prints out last five lines of file by using basic functions like open, read, write, close, lseek. My code so far:
int main(int argc, char *argv[]){
int fd1=open(argv[1], O_RDONLY);
char c;
int currPos = lseek(fd1,-2,SEEK_END);
while(currPos != -1){
read(fd1,&c,sizeof(c));
currPos--;
currPos=lseek(fd1,currPos,SEEK_SET);
if (c == '\n'){
}
}
return 0;
}
Can anybody help me? I think I need to store those characters in array and then print it backwards, but I don't know how.
Why not count the number of characters read while reading back to the fifth newline (call that n) and then do a read of n characters? You don't need to store the data, it's already stored in the file.
Inside the if statement you can count how many '\n' characters you encounter from the end of your file. When you encounter the 6th end-of-line, you know you are at the end of the 6-th-from-the-end line (assuming that the last line also contains an end-of-line character at the end) , so you just print from that point to the end of the file.
You do not need to save the characters in an array, since they are already saved in your file.
You can just do (after your while loop):
int i=read(fd1,&c,1);
while(i){
printf("%c",c);
i = read(fd1,&c,1);
}
It may not be the most efficient way to do it, but it should do the trick.
Note: There is no need to write sizeof(c), since c is a char, and chars are always 1 byte long.
Also, you should always check the return value of read, you never know when something goes wrong in your system and your program crashes because of a read gone wrong.
I wrote the following code:
main()
{
FILE *fp;
fp=fopen("ftest.txt","r");
char c, filestring[100];
int i=0;
while((c=getc(fp))!=EOF)
{
filestring[i]=c;
}
printf("str is %s",filestring);
fclose(fp);
}
The file ftest.txt contains the words Hello World.
The output displayed is not correct, it is either some other font or some other encoding.
What is the reason for this? And how do I solve this problem?
At the same time, this code runs well (shows output on stdout in "English"):
main()
{
FILE *fp;
fp=fopen("ftest.txt","r");
char c;
while((c=getc(fp))!=EOF)
{
printf("%c",c);
}
fclose(fp);
}
I need the first code to work, as I've to search in the text file. How to solve this?
The question is different from Output is not displying correctly in file operation as I'm able to "display" the correct output (as in second code), but I'm not able to write the contents of the file into a string.
Things I've tried:
1) Changing the mode in which the file is opened from "r" to "rb".
2) Changing the Notepad encoding to all available options: ANSI, UTF etc.
There are two parts of the answer:
You never increment i. This means you're just overwriting the same spot (the first space in the array) in the while loop. That's why the first value of the junk is a 'd' (the last character of your input).
The junk after the 'd' is because the array is never initialized, meaning that there is random junk already there that is never overwritten.
Another note: doing the first way would require manually adding a null byte \0 to the end of the array (either by initializing the whole thing to \0s or just after the last character is read in. This is so the string is read correctly by printf.
... and there's also a third part that's wrong here:
getc() returns an int, you're assigning it to a char before comparing it with EOF, which is defined as -1. If it just so happens that getc returns character 255, it gets assigned to a char, a signed 8 bit value, which results in, in a manner of speaking (char)-1, which then gets signed-extended to -1.
this is my first question in this site, and I've just started programming, please be patient with me.
I'm having some trouble with this code to read strings and intergers from a file, they are separated by a semicolon ";" and it starts with the number of lines. The file is something like this:
13;
A;15;B;1;0;0;0;
A;9;C;0;3;2;0;
A;9;D;0;4;0;2;
A;3;E;2;3;2;0;
A;7;F;5;5;3;1;
A;5;G;5;7;6;0;
A;13;H;0;0;0;0;
A;1;I;8;1;0;0;
A;1;J;2;2;1;0;
A;6;K;7;3;2;0;
A;5;L;2;4;3;0;
A;12;AA;0;3;2;0;
A;9;BA;0;1;0;0;
What I tried to do was to create a function that would receive a file pointer (fp) and the number of lines that was read in the main function. It would read the file and save the intergers and strings in matrices :
#include<stdio.h>
#include<stdlib.h>
char timesjogos[100][2][100];
int golsjogos[100][3];
int faltasjogos[100][3];
int camajogos[100][3];
int cverjogos[100][3];
int ReadGames(FILE *caminho,int njogos){
printf("starting to read jogos.\n");
int i=0;
while(fscanf(caminho, " %[^;];%d[^;];%[^;];%d[^;];%d[^;];%d[^;];%d[^;];",
timesjogos[i][0], &golsjogos[i][0], timesjogos[i][1], &golsjogos[i][1],
&faltasjogos[i][0], &camajogos[i][0], &cverjogos[i][0]) == 7)
{
if(i < njogos)
i++;
else
break;
}
}
int main()
{
FILE *fp;
int nbets;
fp = fopen("jogos.txt", "r");
if (!fp){
printf ("Error trying to open file.");
}
fscanf(fp, " %d[^;];", &nbets);
ReadGames(fp, nbets);
}
My doubts are about the %[^;]; I used to read each string up to the ; , should I use %d[^;] for the intergers? What is the correct way to do it?
Also, I'm using global variables to save the information read, the problem is that they can be not large enough to save huge amounts of lines (my professor made a 24180 lines file to test our codes). I was thinking about using the number of lines it gives in the first line to make pre-sized matrices inside the function, but how can I return or save it after the function ends?
I'm sorry for the huge code, but I wanted to show all the details. I would be very thankful for your more experienced help :D
The %[^;] notation reads a string consisting of any number of non-semicolons. The parsing stops when a semicolon is encountered. With numbers, the parsing stops at a semicolon anyway; the semicolon is not a part of the representation of a number.
Your use of %d[^;] means that fscanf() is looking for an integer (%d), then an open square bracket, caret, semicolon and close square bracket. These don't appear in the input, of course, so the scanning fails.
Therefore, your input loop should probably be:
while (fscanf(caminho, " %[^;];%d;%[^;];%d;%d;%d;%d;",
timesjogos[i][0], &golsjogos[i][0], timesjogos[i][1],
&golsjogos[i][1], &faltasjogos[i][0], &camajogos[i][0],
&cverjogos[i][0]) == 7)
{
...
}
You might prefer to specify a maximum length for the %[^;] conversion specifications; %99[^;] would be appropriate since the third dimension of timesjogos is 100. There's an off-by-one difference between the length specified and the length used (enshrined because of ancient history; it was that way before the first C standard, and the C standard codified existing practice).
I am new to C programming, so I am having difficulties with the problem below.
I have a text file inp.txt which contains information like the following:
400;499;FIRST;
500;599;SECOND;
670;679;THIRD;
I need to type a number and my program needs to compare it with numbers from the inp.txt file.
For example, if I type 450, it's between 400 and 499, so I need write to the word FIRST to the file out.txt
I have no idea how to convert a character array to an int.
I think you'll want these general steps in your program (but I'll leave it to you to figure out how you want to do it exactly)
Load each of the ranges and the text "FIRST", "SECOND", etc. from the file inp.txt, into an array, or several arrays, or similar. As I said in the comment above, fscanf might be handy. This page describes how to use it - the page is about C++, but using it in C should be the same http://www.cplusplus.com/reference/clibrary/cstdio/fscanf/. Roughly speaking, the idea is that you give fscanf a format specifier for what you want to extract from a line in a file, and it puts the bits it finds into the variables you specify)
Prompt the user to enter a number.
Look through the array(s) to work out which range the number fits into, and therefore which text to output
Edit: I'll put some more detail in, as asker requested. This is still a kind of skeleton to give you some ideas.
Use the fopen function, something like this (declare a pointer FILE* input_file):
input_file = fopen("c:\\test\\inp.txt", "r") /* "r" opens inp.txt for reading */
Then, it's good to check that the file was successfully opened, by checking if input_file == NULL.
Then use fscanf to read details from one line of the file. Loop through the lines of the file until you've read the whole thing. You give fscanf pointers to the variables you want it to put the information from each line of the file into. (It's a bit like a printf formatting specifier in reverse).
So, you could declare int range_start, range_end, and char range_name[20]. (To make things simple, let's assume that all the words are at most 20 characters long. This might not be a good plan in the long-run though).
while (!feof(input_file)) { /* check for end-of-file */
if(fscanf(input_file, "%d;%d;%s", &range_start, &range_end, range_name) != 3) {
break; /* Something weird happened on this line, so let's give up */
else {
printf("I got the following numbers: %d, %d, %s\n", range_start, range_end, range_name);
}
}
Hopefully that gives you a few ideas. I've tried running this code and it did seem to work. However, worth saying that fscanf has some drawbacks (see e.g. http://mrx.net/c/readfunctions.html), so another approach is to use fgets to get each line (the advantage of fgets is that you get to specify a maximum number of characters to read, so there's no danger of overrunning a string buffer length) and then sscanf to read from the string into your integer variables. I haven't tried this way though.
I'm trying to read in a text file line by line and process each character individually.
For example, one line in my text file might look like this:
ABC XXXX XXXXXXXX ABC
There will always be a different amount of spaces in the line. But the same number of characters (including spaces).
This is what I have so far...
char currentLine[100];
fgets(currentLine, 22, inputFile);
I'm then trying to iterate through the currentLine Array and work with each character...
for (j = 0; j<22; j++) {
if (¤tLine[j] == 'x') {
// character is an x... do something
}
}
Can anyone help me with how I should be doing this?
As you can probably tell - I've just started using C.
Something like the following is the canonical way to process a file character by character:
#include <stdio.h>
int main(int argc, char **argv)
{
FILE *fp;
int c;
if (argc != 2) {
fprintf(stderr, "Usage: %s file.txt\n", argv[0]);
exit(1);
}
if (!(fp = fopen(argv[1], "rt"))) {
perror(argv[1]);
exit(1);
}
while ((c = fgetc(fp)) != EOF) {
// now do something with each character, c.
}
fclose(fp);
return 0;
}
Note that c is declared int, not char because EOF has a value that is distinct from all characters that can be stored in a char.
For more complex parsing, then reading the file a line at a time is generally the right approach. You will, however, want to be much more defensive against input data that is not formatted correctly. Essentially, write the code to assume that the outside world is hostile. Never assume that the file is intact, even if it is a file that you just wrote.
For example, you are using a 100 character buffer to read lines, but limiting the amount read to 22 characters (probably because you know that 22 is the "correct" line length). The extra buffer space is fine, but you should allow for the possibility that the file might contain a line that is the wrong length. Even if that is an error, you have to decide how to handle that error and either resynchronize your process or abandon it.
Edit: I've added some skeleton of an assumed rest of the program for the canonical simple case. There are couple of things to point out there for new users of C. First, I've assumed a simple command line interface to get the name of the file to process, and verified using argc that an argument is really present. If not, I print a brief usage message taking advantage of the content of argv[0] which by convention names the current program in some useful way, and exit with a non-zero status.
I open the file for reading in text mode. The distinction between text and binary modes is unimportant on Unix platforms, but can be important on others, especially Windows. Since the discussion is of processing the file a character at a time, I'm assuming that the file is text and not binary. If fopen() fails, then it returns NULL and sets the global variable errno to a descriptive code for why it failed. The call to perror() translates errno to something human-readable and prints it along with a provided string. Here I've provided the name of the file we attempted to open. The result will look something like "foo.txt: no such file". We also exit with non-zero status in this case. I haven't bothered, but it is often sensible to exit with distinct non-zero status codes for distinct reasons, which can help shell scripts make better sense of errors.
Finally, I close the file. In principle, I should also test the fclose() for failure. For a process that just reads a file, most error conditions will already have been detected as some kind of content error, and there will be no useful status added at the close. For file writing, however, you might not discover certain I/O errors until the call to fclose(). When writing a file it is good practice to check return codes and expect to handle I/O errors at any call that touches the file.
You don't need the address operator (&). You're trying to compare the value of the variable currentLine[j] to 'x', not it's address.
ABC XXXX XXXXXXXX ABC has 21 characters. There's also the line break (22 chars) and the terminating null byte (23 chars).
You need to fgets(currentLine, 23, inputFile); to read the full line.
But you declared currentLine as an array of 100. Why not use all of it?
fgets(currentLine, sizeof currentLine, inputFile);
When using all of it, it doesn't mean that the system will put more than a line each time fgets is called. fgets always stops after reading a '\n'.
Try
while( fgets(currentLine, 100, inputFile) ) {
for (j = 0; j<22; j++) {
if (/*&*/currentLine[j] == 'x') { /* <--- without & */
// character is an x... do something
}
}
}