Parsing Specific Input File Using Fscanf - c

i`ve been trying o use fscanf to read the an input file on my application.
This is the input file
3
Process#1 - 2Kb
3
exec 20
io 5
exec 50
Process#2 - 8Kb
1
exec 100
Process#3 - 8Kb
4
exec 50
io 50
exec 50
io 50
First of all i want to read the First "3", which i am having no problems doing so.
After that, i will need to read the information after the # (which is 1) and the number right after the "kb" string (which is 2).
Why is this fscanf failing to do so ?
fscanf(inputFile, "Process#%d - %dKb", &id, &mem );
How can i do it ?
Thanks in advance

Probably because the newline left behind after the 3 is not being recognized by the P in Process.
This is why many people avoid scanf(); it is usually simpler to use fgets() or a related function (but not gets()!) and then use sscanf().
Demo code
Notice the rigorous checking of the return from scanf(). If you don't do that, you will not know when things have gone wrong. Note that the check is for the correct number of conversions, too.
#include <stdio.h>
int main(void)
{
int i;
int id;
int mem;
if (scanf("%d", &i) != 1)
printf("oops!\n");
/* With space - reads past newline on first line */
/* Without space - prints 'thank goodness!' */
if (scanf(" Process#%d - %d", &id, &mem) != 2)
printf("thank goodness!\n");
return 0;
}

Related

My program creates a file named date.in but it is not inserting all the numbers

Write a C program that reads from the keyboard a natural number n
with up to 9 digits and creates the text file data.out containing the
number n and all its non-zero prefixes, in a single line, separated by
a space, in order decreasing in value. Example: for n = 10305 the data
file.out will contain the numbers: 10305 1030 103 10 1.
This is what I made:
#include <stdio.h>
int main()
{
int n;
FILE *fisier;
fisier=fopen("date.in","w");
printf("n= \n");
scanf("%d",&n);
fprintf(fisier,"%d",n);
while(n!=0)
{
fisier=fopen("date.in","r");
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
}
Few things:
Function calls may return error. You need to check that every time.
fisier=fopen("date.in","w");
This should have been followed by an error check. To understand more on what it return, first thing you should do is read the man page for that function. See man page for fopen(). If there is an error in opening the file, it will return NULL and errno is set to a value which indicates what error occurred.
if (NULL == fisier)
{
// Error handling code
;
}
Your next requirement is separating the numbers by a space. There isn't one. The following should do it.
fprintf(fisier, "%d ", n);
The next major problem is opening the file in a loop. Its like you are trying to open a door which is already open.
fisier=fopen("date.in","r");
if(NULL == fisier)
{
// Error handling code
;
}
while(n!=0)
{
n=n/10;
fprintf(fisier,"%d",n);
}
fclose(fisier);
A minor issue that you aren't checking is the number is not having more than 9 digits.
if(n > 999999999)
is apt after you get a number. If you want to deal with negative numbers as well, you can modify this condition the way you want.
In a nutshell, at least to start with, the program should be something similar to this:
#include <stdio.h>
// Need a buffer to read the file into it. 64 isn't a magic number.
// To print a 9 digit number followed by a white space and then a 8 digit number..
// and so on, you need little less than 64 bytes.
// I prefer keeping the memory aligned to multiples of 8.
char buffer[64];
int main(void)
{
size_t readBytes = 0;
int n = 0;
printf("\nEnter a number: ");
scanf("%d", &n);
// Open the file
FILE *pFile = fopen("date.in", "w+");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
while(n != 0)
{
// Append to the file
fprintf(pFile, "%d ", n);
n = n / 10;
}
// Done, close the file
fclose(pFile);
printf("\nPrinting the file: ");
// Open the file
pFile = fopen("date.in", "r");
if(NULL == pFile)
{
// Prefer perror() instead of printf() for priting errors
perror("\nError: ");
return 0;
}
// Read the file
while((readBytes = fread(buffer, 1, sizeof buffer, pFile)) > 0)
{
// Preferably better way to print the contents of the file on stdout!
fwrite(buffer, 1, readBytes, stdout);
}
printf("\nExiting..\n\n");
return 0;
}
Remember: The person reading your code may not be aware of all the requirements, so comments are necessary. Secondly, I understand english to a decent level but I don't know what 'fisier' means. Its recommended to name variables in such a way that its easy to understand the purpose of the variable. For example, pFile is a pointer to a file. p in the variable immediately gives an idea that its a pointer.
Hope this helps!
To draw a conclusion from all the comments:
fopen returns a file handle when successfull and NULL otherwise. Opening a file twice might result in an error (it does on my machine), such that fisier is set to NULL inside the loop. Obvioulsy fprintf to NULL wont do anything.
You only need to call fopen once, so remove it from the loop. After that it will work as intended.
It's alwas good to check if the fopen succeeded or not:
FILE *fisier;
fisier=fopen("date.in","w");
if(!fisier) { /* handle error */ }
You print no spaces between the numbers. Maybe that's intended, but maybe
fprintf(fisier,"%d ",n);
would be better.

Why is My Program Unable To Read the Data from My File

My Program Works Mostly, except for When I try to read the Total Data that was Entered
#include <stdio.h>
#include <string.h>
#define bufferSize 300
char name[50], gift[50], list[300], end[50], *result;
int i;
int main()
{
FILE *appendPlace = fopen("NamesAndGifts.txt", "a");
FILE *readData = fopen("NamesAndGifts.txt", "r"); //my place for reading data
printf("This is a Gift Entering System for 3 People Only\nThe Name of the Person then their Gift Description will be taken\nThe Gift Description is Basically the Gift Name");
while (strcmp(end, "END") != 0) {
printf("\nEnter Name of Person %d or type 'END' to Exit Sequence\n", i + 1);
scanf("%s", &end);
if (strcmp(end, "END") != 0) {
strcpy(name, end);
printf("Now Enter Gift Description (Gift Name) of Person %d\n", i + 1);
scanf("%s", &gift);
strcat(list, "\n");
strcat(list, "Name: ");
strcat(list, name);
strcat(list, "\n");
strcat(list, "Gift: ");
strcat(list, gift);
strcat(list, "\n");
}
i++;
}
printf("The Gift Entering System (Names and their respective Gifts) is Below:\n");
printf("%s", list);
fputs(list, appendPlace);
fclose(appendPlace);
//below I attempt to read file Data to be able to print file's Data into running program
fscanf(readData, "%s", result);
printf("\n\n\n\n\n\n\nTotal Data in File Below:\n%s", result);
fclose(readData);
}
I tried out doing just file reading, and it seems that reading from the file like that can only read data that is not separated by (space bar) or (enter)
Is there a way to Solve this?
So there are 2 problems in your code.
result has no memory allocated to it. Since it is a global variable, it is initialized to 0, aka a NULL pointer. So your scanf() sees that and the reading fails and so does printf() and prints "(null)". The solution there is to allocate memory in result either by making it a static array or by using malloc().
Even if you fix the first problem, however, it will still not work as expected as fscanf() will stop reading input after the first whitespace is encountered. Since you want the whole (file) input to be read, you have four options:
Read character by character (not advisable for performance reasons but perhaps the easiest to implement)
read line by line (fairly a standard way)
read chunk by chunk given some pre-allocated buffer or
read the whole file at once (not advised for big files)
The functions to use are fgetc(), getline(), fread(). Additionally, you can find the size of the file by following this question

asking and reading in user input using unbuffered IO routines

We just started the topic of low level functions in C and for a part of this assignment we have to ask for user input. Normally I would use printf() and scanf() however for this assignment we are only allowed to use read(), write(), open(), close(), and lseek().
My question is how would you read input from the keyboard after printing to the screen?
I understand that I would have to use read, the file descriptor would be STDIN_FILENO, however how would I determine the size count? Also how would I keep track of what the user inputted? Would I have to create an char array just for that?
Also if anyone could reference some good reading material or tutorials for programming with low level functions that would help a lot.
Reading char by char would be bad for performance. System calls are kind of expensive. Most usually you want some kind of buffer (malloced, static memory, on the stack).
The size (once it's past certain size) doesn't really matter that much.
If your fd 0 is a terminal in cooked mode, you will get a line on each call to read (which will usually fail to fill your entire buffer). What's important to realize is that a read request for N bytes doesn't need to return N bytes and a return of less than N bytes doesn't need to mean an IO error. If it's a disk-based file, then your read request for the size of your buffer will tend to get fullfilled fully.
Advanced Programming in the Unix Environment by Richard Stevens is a good book on this.
Then of course, the man pages for the system calls.
Continuing from my earlier comment, there is really little difference between reading and writing to stdin using read and write and using higher level functions like fgets and printf. The primary difference is you cannot rely on the format string provided by the variadic printf, and with read, you are responsible for making use of the return to know how many characters were actually read.
Below is a short example showing the basics of reading input from stdin with read and then writing that information back with write (note: there are additional checks you should add like checking that the number of characters read is less than the size of the buffer to know if more characters remain to be read, etc...) You can always put much of the prompt and read into a function to ease repetitive use.
With write, just remember, the order you write things to stdout is the format string. So simply make logical calls to write to accomplish the formatting you desire. While you are free to use the STDIN_FILENO defines, you can also simply use 0 - stdin, 1 - stdout and 2 - stderr:
#include <unistd.h>
#define MAXC 256
int main (void) {
char buf[MAXC] = {0};
ssize_t nchr = 0;
/* write the prompt to stdout requesting input */
write (1, "\n enter text : ", sizeof ("\n enter text : "));
/* read up to MAXC characters from stdin */
if ((nchr = read (0, buf, MAXC)) == -1) {
write (2, "error: read failure.\n", sizeof ("error: read failure.\n"));
return 1;
}
/* test if additional characters remain unread in stdin */
if (nchr == MAXC && buf[nchr - 1] != '\n')
write (2, "warning: additional chars remain unread.\n",
sizeof ("warning: additional chars remain unread.\n"));
/* write the contents of buf to stdout */
write (1, "\n text entered: ", sizeof ("\n text entered: "));
write (1, buf, nchr-1);
write (1, "\n\n", sizeof ("\n\n"));
return 0;
}
Compile
gcc -Wall -Wextra -o bin/read_write_stdin read_write_stdin.c
Output
$ ./bin/read_write_stdin
enter text : The quick brown fox jumps over the lazy dog!
text entered: The quick brown fox jumps over the lazy dog!

fgets adding string to another variable

I'm trying to do a relatively simple library project in C, but I'm stuck. I'm using fscanf to set a variable (cote which is char[5]) and then fgets to set another variable (titre which is a char[50]). Both of these variables belong to a structure called Ouvrage.
The problem is that fgets seems to add the string it is reading to cote, before the fgets : strlen(o.cote) returns 5 yet afterwards it returns 31.
Here is the code for test.c :
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char cote[5];
char titre[50];
} Ouvrage;
void main(void)
{
FILE *flot;
Ouvrage o;
// Opening the file
flot = fopen("ouvrages.don", "r");
if(flot == NULL)
{
printf("Error opening file.\n");
exit(1);
}
// Reading the cote
fscanf(flot, "%s%*c", o.cote);
// Printing the length of cote
printf("STRLEN: %d\t", strlen(o.cote));
// Reading the titre
fgets(o.titre, 50, flot);
o.titre[strlen(o.titre) - 1] = '\0';
// Printing the length of cote again.... Different.
printf("STRLEN: %d\n", strlen(o.cote));
}
And here is the ouvrage.don file :
NJDUI
Charlie et la chocolaterie
ROM
Rhoal Doal
So how is fgets affecting a previous variable and how to stop it ? Any help is greatly appreciated.
Welcome to the world of c-strings. Assuming cote is supposed to be 5 characters long, you actually need to reserve 6 characters in order to have space for the end of string character ('\0'); what happened was that fscanf wrote that string character as the first character of titre,but then fgets overwrote that, which is why you saw what you saw. Also note that as far as I'm concerned, scanf and related is the tool of the devil; why not just use fgets (which allows you to specify the maximum number of bytes to read [read closely the manpage to avoid an off by one]) for both reads?

C, reading a multiline text file

I know this is a dumb question, but how would I load data from a multiline text file?
while (!feof(in)) {
fscanf(in,"%s %s %s \n",string1,string2,string3);
}
^^This is how I load data from a single line, and it works fine. I just have no clue how to load the same data from the second and third lines.
Again, I realize this is probably a dumb question.
Edit: Problem not solved. I have no idea how to read text from a file that's not on the first line. How would I do this? Sorry for the stupid question.
Try something like:
/edited/
char line[512]; // or however large you think these lines will be
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
/* "rt" means open the file for reading text */
int cur_line = 0;
while(fgets(line, 512, in) != NULL) {
if (cur_line == 2) { // 3rd line
/* get a line, up to 512 chars from in. done if NULL */
sscanf (line, "%s %s %s \n",string1,string2,string3);
// now you should store or manipulate those strings
break;
}
cur_line++;
}
fclose(in); /* close the file */
or maybe even...
char line[512];
in = fopen ("multilinefile.txt", "rt"); /* open the file for reading */
fgets(line, 512, in); // throw out line one
fgets(line, 512, in); // on line 2
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 2 is loaded into 'line'
// do stuff with line 2
fgets(line, 512, in); // on line 3
sscanf (line, "%s %s %s \n",string1,string2,string3); // line 3 is loaded into 'line'
// do stuff with line 3
fclose(in); // close file
Putting \n in a scanf format string has no different effect from a space. You should use fgets to get the line, then sscanf on the string itself.
This also allows for easier error recovery. If it were just a matter of matching the newline, you could use "%*[ \t]%*1[\n]" instead of " \n" at the end of the string. You should probably use %*[ \t] in place of all your spaces in that case, and check the return value from fscanf. Using fscanf directly on input is very difficult to get right (what happens if there are four words on a line? what happens if there are only two?) and I would recommend the fgets/sscanf solution.
Also, as Delan Azabani mentioned... it's not clear from this fragment whether you're not already doing so, but you have to either define space [e.g. in a large array or some dynamic structure with malloc] to store the entire dataset, or do all your processing inside the loop.
You should also be specifying how much space is available for each string in the format specifier. %s by itself in scanf is always a bug and may be a security vulnerability.
First off, you don't use feof() like that...it shows a probable Pascal background, either in your past or in your teacher's past.
For reading lines, you are best off using either POSIX 2008 (Linux) getline() or standard C fgets(). Either way, you try reading the line with the function, and stop when it indicates EOF:
while (fgets(buffer, sizeof(buffer), fp) != 0)
{
...use the line of data in buffer...
}
char *bufptr = 0;
size_t buflen = 0;
while (getline(&bufptr, &buflen, fp) != -1)
{
...use the line of data in bufptr...
}
free(bufptr);
To read multiple lines, you need to decide whether you need previous lines available as well. If not, a single string (character array) will do. If you need the previous lines, then you need to read into an array, possibly an array of dynamically allocated pointers.
Every time you call fscanf, it reads more values. The problem you have right now is that you're re-reading each line into the same variables, so in the end, the three variables have the last line's values. Try creating an array or other structure that can hold all the values you need.
The best way to do this is to use a two dimensional array and and just write each line into each element of the array. Here is an example reading from a .txt file of the poem Ozymandias:
int main() {
char line[15][255];
FILE * fpointer = fopen("ozymandias.txt", "rt");
for (int a = 0; a < 15; a++) {
fgets(line[a], 255, fpointer);
}
for (int b = 0; b < 15; b++) {
printf("%s", line[b]);
}
return 0;
This produces the poem output. Notice that the poem is 14 lines long, it is more difficult to print out a file whose length you do not know because reading a blank line will produce the output "x�oA". Another issue is if you check if the next line is null by writing
while (fgets(....) != NULL)) {
each line will be skipped. You could try going back a line each time to solve this but i think this solution is fine for all intents.
I have an even EASIER solution with no confusing snippets of puzzling methods (no offense to the above stated) here it is:
#include <iostream>
#include <fstream>
#include <string>
using namespace std;
int main()
{
string line;//read the line
ifstream myfile ("MainMenu.txt"); // make sure to put this inside the project folder with all your .h and .cpp files
if (myfile.is_open())
{
while ( myfile.good() )
{
getline (myfile,line);
cout << line << endl;
}
myfile.close();
}
else cout << "Unable to open file";
return 0;
}
Happy coding

Resources