C - Fgets &Scanf to read from a text file - c

#include <stdio.h>
int main() {
FILE *f;
unsigned int num[80];
int i=0;
int rv;
int num_values;
f=fopen("values.txt","r");
if (f==NULL){
printf("file doesnt exist?!\n");
return 1;
}
while (i < 80) {
rv = fscanf(f, "%x", &num[i]);
if (rv != 1)
break;
i++;
}
fclose(f);
num_values = i;
if (i >= 80)
{
printf("Warning: Stopped reading input due to input too long.\n");
}
else if (rv != EOF)
{
printf("Warning: Stopped reading input due to bad value.\n");
}
else
{
printf("Reached end of input.\n");
}
printf("Successfully read %d values:\n", num_values);
for (i = 0; i < num_values; i++)
{
printf("\t%x\n", num[i]);
}
return 0
}
Got the code above from another question, but having probelms editing it to suit my requirements, everytime i change it seems to error everywhere.
Its only a simple change aswell.
Example input from the file would be
12345678
87654321
1234567811
12345678
When reading in from the file using this method take tthe whole of every line when i only want it to take the first 8 hex numbers and save them.
I tryed using a fgets to get the line and than scanf to format it but the errors just get out of hand.
The idea i had in my head but just not sure how to implement is
1. Open file
fgets current line
scanf to format current line
Getting first 8 digits
Saving them to the array
loop till end of file (rather than <80 like it is in the code above)
Im a newbee to c and to used to java.

Try
char buffer[201];
while (fgets(buffer, 200, f) != NULL)
{
if (strlen(buffer) > 7)
{
buffer[8] = 0;
sscanf(buffer, "%x", &num[i++]);
}
else
{
/* report that the line is error ?! */
}
}

Related

Comparing a user input string to a line from a text file in c creates infinite loop

I'm trying to get better at coding in general and C in particular, and am coding a small text adventure game. I read a string input by the user i.e LOOK room and compare it to a txt file with the list of commands for that particular section.
As I am reading from the text file I have a counter which keeps track of which line is being read, when the match is made I convert the line number to a character and concatenate it to "outside.txt" so that when the correct command is input it will read from the correct file i.e LOOK room would load text from 1outside.txt etc.
However, when inputting anything it just loops on "I dont understand" forever. Any explanation as to why or constructive comments on my code are appreciated, especially if I am misunderstanding how files and/or strings in c.
int mansionOutside(void)
{
int stop = 1;
char choice[25];
char word_match[25];
char text_line[73];
char line1[25];
char temp[2];
int counter;
FILE *fptr;
fptr = fopen("mansion_commands.txt", "r");
if (fptr == NULL)
{
printf("ERROR!");
}
else
{
while (stop == 1)
{
printf("\n");
fgets(choice, sizeof choice, stdin);
while (fgets (line1, 25, fptr)!= NULL)
{
if (strcmp(line1, choice) == 0)
{
printf("%s\n", line1);
stop = 0;
break;
}
else
{
counter++;
printf("%s + %s\n", line1, choice);
}
}
if (stop == 1)
{
printf("I dont understand\n");
counter = 1;
}
}
fclose(fptr);
counter = counter + '0';
temp[0] = counter;
temp[1] = '\0';
strncat(word_match, temp , 1);
strcat(word_match, ".txt");
fptr = fopen(word_match, "r");
if (fptr == NULL)
{
printf("ERROR!\n");
}
else
{
printf("Debugging : File opened Successfully\n");
while (fgets (text_line, 72, fptr) != NULL)
{
printf("%s", text_line);
//delay(2);
}
}
}
}
EDIT : Took in suggestions for improvements to avoid Buffer overflows such as using > fgets , but I think there is something I have missed. Now If I input anything contained in the file, it works fine. If however I input something wrong, then something correct on re-prompt, It skips the inner while loop all together and goes straight to "I don't understand".
The following is what happens when my input is LOOK room, and then LOOK mansion.

Change the logic of text file reading program to suspend output after 4 lines

So what I'm basically doing here is using a command line argument to open a file but only open it 4 lines at a time, then a prompt to print out add'l lines. I can get the file to print out but I cannot figure out how to get it to only print out a few lines at a time. This is where I'm at....thoughts?
#include <stdio.h>
int main(int argc, char *argv[])
{
char line[1000];
FILE *pt;
pt = fopen(argv[1], "r");
if(pt == NULL) return -1;
printf(argv[1], line);
while(fgets(line, 1000, pt) != NULL)
printf("%s", line);
fclose(pt);
return 0;
}
I start from strange line of your code, and then I will try to answer the question.
Statement
printf(argv[1], line);
make me curious - what you what to print, actually?
Here line is not initialized, and argv[1] can hardly be used as format line.
So I suppose it should be just
printf(argv[1]);
or
printf("Filename is %s\n", argv[1]);
As for reading from a file with name provided as argv[1] your code looks able to work, I mean your code read line by line till the end of file and prints these lines at the screen.
If you want to change this logic, e.g. read only 4 first line, add condition with counter, e.g.:
int cnt;
for (cnt = 0; cnt < 4; cnt++) // repeat reading 4 times
{
if (fgets(line, 1000, pt) != NULL)
printf("%s", line);
else
break; // stop when reading fails
}
or (I prefer this version)
int cnt = 0;
while (fgets(line, 1000, pt) != NULL && cnt < 4)
{
printf("%s", line);
cnt++;
}
Such changes allows to stop reading (as well as output), so only 4 or less lines will be shown at console screen.
Finally, for case when you want to show file by groups of 4 (or other constant value), consider the following snippet:
#include <stdio.h>
#define MAX_LINES_TO_PRINT 4
int main(int argc, char *argv[])
{
char line[1000];
FILE *pt;
pt = fopen(argv[1], "r");
if (pt == NULL) return -1;
printf("Filename is %s\n", argv[1]);
int cnt = 0;
while (fgets(line, 1000, pt) != NULL)
{
printf("%s", line);
cnt++;
if (cnt % MAX_LINES_TO_PRINT == 0)
{
int answer;
printf("[%d lines printed] Continue? (Y/N) : ", cnt);
answer = getchar(); // get user's response
while (getchar() != '\n'); // clean input buffer after getchar
if (toupper(answer) == 'N')
{
break; // stop reading the file
}
}
}
fclose(pt);
return 0;
}
Try this program with your file and ask question if something is unclear.
Changing the value in the line #define MAX_LINES_TO_PRINT 4 you can regulate maximum number of lines printed at once (before the next request to continue), e.g. #define MAX_LINES_TO_PRINT 15 make your program printing up to 15 lines.

How to detect last extra Empty Line and Ignore it in C (using getc)

Hello I am using this code for reading floating numbers in txt. If end of txt file has extra blank empty line program reads it 0.00000 and this affect my calculation Last empty line
(# means end of the calculation I added comment line if it exist update comment line)
I try "getline" and other function I can't fix it
fptr = fopen(fileName,"r+");
if(fptr == NULL){
printf("Error!! Cannot open file: %s \n", fileName );
return 1;
}
else {
printf("File opened successfully\n");
while((c = getc(fptr)) != '#' && c != EOF) {
fscanf(fptr,"%f" ,&arr[i]);
++i;
}
}
Check the return value of fscanf -- it should return 1 when it successfully reads a number and 0 on that blank line.
OP is reading a file, line by line and has 4 outcomes:
Successful translated to a number.
Line begins with a # or whitespace only.
No more input (end-of-file).
Something else.
Suggest new approach: read line by line as text and then attempt various parsings. It is important to check the return value of *scanf() to help determine success.
printf("File opened successfully\n");
float /* or double */ arr[N];
size_t i = 0;
char buffer[100];
while (fgets(buffer, sizeof buffer, fptr)) {
double x;
char sof[2];
if (sscanf(buffer, "%lf" ,&x) == 1) {
if (i < N) {
arr[i++] = x;
} else {
puts("No room");
}
} else if (sscanf(buffer, "%1s" , sof) != 1 || sof[0] == '#') {
; // quietly ignore white-space only lines and that begin with #
} else {
puts("Unexpected input");
}
}
fclose(fptr);
puts("Done");

Using fscanf for a txt file and ignoring everything but letters

Hello I'm writing a program that needs to read from a text file and only takes in the letters of the whole file. It could be something as
Hello, my name is whatever. I'm thinking of trying to write a program: "name!"
What I need to do is only read in the letters so my output would be:
hellomynameiswhateverimthinkingoftryingtowriteaprogramname
I have something of this sort:
while (fscanf(ifp2, "%c", &file[i]) != EOF) //scans until end of file
{
for (i = 0; i < 10000; i++) //loops a possible 10000, file could possibly be that big
{
//printf("Got inside while loop [%d]\n", i); //this just lets me see the loop
if (fscanf(ifp2, "%c ", &file[i]) == 0) //im trying to see how i can ignore some data
{
fscanf(ifp2, "%c ", &file[i]); //scans in the character
}
}
}
for (i = 0; i < 10000; i++)//prints the array of characters.
{
if(file[i] == NULL)//keeps from printing uninitialized parts of array
{
break;
}
else
{
if (counter % 80 == 0) //makes it print 80 characters per line
{
printf("\n");
}
printf("%c", file[i]);//prints the character
counter++;
}
}
I know I can use fscanf somehow and I know it should be much simpler than this. I just need a *pointer (pun intended) in the right direction!
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp;
char c;
fp = fopen("sample.txt", "r");
if (fp == NULL) {
printf("Couldn't open file for reading.\n");
exit(0);
}
while (fscanf(fp, "%c",&c) != EOF)
{
if (isalpha(c))
printf("%c", c);
}
printf("\n");
return 0;
}
Technially, you can use fscanf to ignore directly (the * suppresses assignment):
fscanf(in, "%*[^A-Za-z]%c", &c);
It's not incredibly useful in this case - intpreted format strings are slow. I would just use fgetc.

In C, how do I read a file, and store only the doubles - ignoring text before?

I need to read in a file that contains text, and then a double for that text. It is simply to get the mean and standard deviation for the set of numbers, so the text that comes before is irrelevant. For example, my input file looks a little like:
preface 7.0000
chapter_1 9.0000
chapter_2 12.0000
chapter_3 10.0000
etc..
In this case, it is finding the mean and std dev for the chapters of a book. I have the section of code below, but I'm not quite sure how to "ignore" the text, and only grab the doubles. At the moment this code prints out zeros and only exits the loop when it exceeds the array limit, which I set as a constant to 20 at the beginning of the program.
FILE *ifp;
char *mode = "r";
ifp = fopen("table.txt", mode);
double values[array_limit];
int i;
double sample;
if (ifp==NULL)
{
printf("cannot read file \n");
}
else
{
i = 0;
do
{
fscanf(ifp, "%lf", &sample);
if (!feof(ifp))
{
values[i] = sample;
printf("%.4lf \n", values[i]);
i++;
if (i>=array_limit) //prevents program from trying read past array size limit//
{
printf("No more space\n");
break;
}
}
else
{
printf("read complete\n");
printf("lines = %d\n", i);
}
}while (!feof(ifp));
fclose(ifp);
}
I think you could use fscanf(ifp, "%*[^ ] %lf", &sample) for reading from your file. The * says to ignore that particular match, the [] specifices a list of characters to match and the ^ indicates to match all characters except those in [].
Or possibly (a bit simpler) fscanf(ifp, "%*s %lf", &sample).
You have two major problems -- you're using feof which is pretty much always wrong, and you're not checking the return value of fscanf, which it what tells you whether you got a value or not (or whether you got to the eof).
So what you want is something like
while ((found = fscanf(ifp, "%lf", &values[i])) != EOF) { /* loop until eof */
if (found) {
/* got a value, so count it */
if (++i >= ARRAY_LIMIT) {
printf("no more space\n");
break;
}
} else {
/* something other than a value on input, so skip over it */
fscanf(ifp, "%*c%*[^-+.0-9]");
}
}
When reading in from a file, it's often best to use fgets to read one line at a time, then extract the parts you are interested in using sscanf:
#include <stdlib.h>
#include <stdio.h>
#define ARRAY_LIMIT 10
#define LINE_LENGTH 128
int main()
{
double values[ARRAY_LIMIT];
int i, count = 0;
double sample;
FILE *ifp = fopen("table.txt", "r");
if (ifp==NULL)
{
printf("cannot read file \n");
return 1;
}
char buff[LINE_LENGTH];
while (fgets(buff, LINE_LENGTH, ifp) != NULL)
{
if (sscanf(buff, "%*s %lf", &sample) != 1) break;
values[count++] = sample;
if (count == ARRAY_LIMIT) {
printf("No more space\n");
break;
}
}
fclose(ifp);
for (i = 0; i < count; ++i) {
printf("%d: %f\n", i, values[i]);
}
return 0;
}
fgets returns NULL if it encounters the end of the file, or if a read error has occurred. Otherwise, it reads one line of the file into the character buffer buff.
The asterisk %*s in the sscanf means that the first part of the line is discarded. The second part is written to the variable sample. I am checking the return value of sscanf, which indicates how many values have been read successfully.
The loop breaks when the end of the file is reached or the count reaches the size of the array.

Resources