Using FILE *f = stdin; - c

I want(ed) to implement POSIX tail in C language. If the input is file (filename received from argv), then I used fseek to get at the end of file, so implementation was somehow easy.
But when the input is stdin, I can't use fseek. I somehow figured out that i can do:
FILE *f = stdin;
Then I can use stdin as file and fseek, everything works as intended (with some little work :D).
My question is only, is this okay ? I mean (for me) it's kinda unusual to use stdin like that. Wouldn't be there any 'security' or another errors with this ? I tested my tail a lot and it looks like it works good even with edge cases.

It is indeed a weird thing to do because it doesn't help. Whether fseek works or not isn't affected by the name of the variable used as an argument.
It can succeed if the handle is for a plain file.
It can't succeed if the handle isn't for a plain file.
This is true for fseek(stdin, ...). (Code below.)
$ ./fseek_stdin <file
fghij
$ cat file | ./fseek_stdin
fseek: Illegal seek
This is true for fseek(f, ...). (Code below.)
$ ./fseek_f <file
fghij
$ cat file | ./fseek_f
fseek: Illegal seek
But there is also no harm in assigning stdin to another variable. For example, you might do
FILE *f;
if (...) {
f = stdin;
} else {
f = fopen(...);
}
Or you might do
void some_func(FILE *f) {
...
}
some_func(stdin);
These are both perfectly legitimate assignments of stdin to another variable.
Here are the files used in the earlier tests:
file:
abcdefghij
fseek_stdin.c:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
if (fseek(stdin, 5, SEEK_CUR) < 0) {
perror("fseek");
return EXIT_FAILURE;
}
char *line = NULL;
size_t n = 0;
if (getline(&line, &n, stdin) < 0) {
perror("getline");
free(line);
return EXIT_FAILURE;
}
printf("%s", line);
free(line);
return EXIT_SUCCESS;
}
fseek_f.c:
#include <stdio.h>
#include <stdlib.h>
int main(void) {
FILE *f = stdin;
if (fseek(f, 5, SEEK_CUR) < 0) {
perror("fseek");
return EXIT_FAILURE;
}
char *line = NULL;
size_t n = 0;
if (getline(&line, &n, f) < 0) {
perror("getline");
free(line);
return EXIT_FAILURE;
}
printf("%s", line);
free(line);
return EXIT_SUCCESS;
}
A diff of the two programs (slightly massaged for readability):
$ diff -y fseek_{stdin,f}.c
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
int main(void) { int main(void) {
> FILE *f = stdin;
>
if (fseek(stdin, 5, SEEK_CUR) < 0) { | if (fseek(f, 5, SEEK_CUR) < 0) {
perror("fseek"); perror("fseek");
return EXIT_FAILURE; return EXIT_FAILURE;
} }
char *line = NULL; char *line = NULL;
size_t n = 0; size_t n = 0;
if (getline(&line, &n, stdin) < 0) { | if (getline(&line, &n, f) < 0) {
perror("getline"); perror("getline");
free(line); free(line);
return EXIT_FAILURE; return EXIT_FAILURE;
} }
printf("%s", line); printf("%s", line);
free(line); free(line);
return EXIT_SUCCESS; return EXIT_SUCCESS;
} }

Related

how to print sentences with spaces from a txt?

I'm trying to copy text from a input.txt but programs thinks spaces are new lines. How should I go about this?
my input.txt (trial)
1. hero
2. angelic
3. hello world
4. demons
my source.c
int main(void) {
FILE* fread = fopen("C:\\Users\\EXAMPLE\\desktop\\input.txt", "r");
if (fread == NULL) {
printf("One file wouldn't open!\n");
return -1;
}
//this pastes the text from input.txt into the command-line
char line[1000] = "";
while (fscanf(fread, "%s", line) == 1) {
printf("%s\n", line);
}
fclose(fread);
fclose(fwrite);
output
1.
hero
2.
angelic
3.
hello
world
4.
demons
Here is what you do. There is already function implemented to help you in doing this.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * fp;
char * line = NULL;
size_t len = 0;
ssize_t read;
fp = fopen("C:\\Users\\EXAMPLE\\desktop\\input.txt", "r");
if (fp == NULL){
printf("One file wouldn't open!\n");
exit(EXIT_FAILURE);
}
while ((read = getline(&line, &len, fp)) != -1) {
printf("Retrieved line of length %zu:\n", read);
printf("%s", line);
}
fclose(fp);
if (line)
free(line);
exit(EXIT_SUCCESS);
}

Can't read file in C using fread()

Program asks for input and stores it in a variable, then confirms the operation printing the content of the file. Or at least it had to, when the program ends it doesn't print the file content, I can't seem to find an answer, I've been looking in the docs but can't really figure it out.
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE * file1 = fopen(".out", "w+");
char *s = malloc(513);
fgets(s, 513, stdin);
if (fprintf(file1, "%s", s) < 0)
{
printf("Something failed while writing to the file\n");
return 1;
}
else
{
char *t = malloc(513);
fread(t, sizeof(char), 1, file1);
printf("Success! Input was: %s \n", t);
return 0;
}
}
P.S: Very new to C, though it may seem obvious for you I have no clue whatsoever.
There are 2 issues here,
1 - you wrote to the file handler and you are trying to read from that point onwards - you didnt rewind the file pointer!
2 - you are just reading 1 character and not the amount you wrote to it!
#include <string.h>
...
int n = strlen(s);
rewind(file1); // rewind before read
fread(t, sizeof(char), n, file1); // read as much as you wrote
Some problems in your code:
You are not checking the return value of fopen(), malloc(), fgets() and fread().
You are writing one character to the output stream, without rewinding it.
Here's how your code should look like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
FILE * file1 = fopen(".out", "w+");
if (!file1) {
printf("Could not open file.\n");
return 1;
}
const size_t n = 513; // Use constants, not litterals.
char *s = malloc(sizeof(char) * n);
if (!s) {
printf("Internal error.\n");
fclose(file1);
return 1;
}
if (!fgets(s, n, stdin)) {
printf("Input failed.\n");
fclose(file1);
return 1;
}
if (fprintf(file1, "%s", s) < 0) {
printf("Something failed while writing to the file\n");
fclose(file1);
return 1;
}
char *t = malloc(sizeof(char) * n);
if (!t) {
printf("Internal error.\n");
fclose(file1);
return 1;
}
rewind(file1);
int ret = fread(t, sizeof(char), n, file1); // Read n characters, not 1.
if (ret != strlen(s)) {
if (feof(file1)) {
printf("Error reading .out: unexpected end of file.\n");
} else if (ferror(file1)) {
perror("Error reading .out");
}
fclose(file1);
return 1;
}
printf("Success! Input was: %s \n", t);
}

Compare each line from two different files and print the lines that are different in C

Supposing that I have two files like this:
file1.txt
john
is
the new
guy
file2.txt
man
the old
is
rick
cat
dog
I'd like to compare first line from file1 with all the lines from file2 and verify if it exist. If not, go two the second line from file1 and compare it with all the lines from file2.. and so on until eof is reached by file1.
The output that I expect is:
john
the new
guy
How I thought this should be done:
read file1 and file2
create a function which returns the line number of each of them
take the first line from file1 and compare it to all the lines from file2
do this until all the lines from file1 are wasted
Now, I don't know what I'm doing wrong, but I don't get the result that I expect:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int countlines(char *filename)
{
int ch = 0, lines = 0;
FILE *fp = fopen(filename, "r");
if (fp == NULL)
return 0;
do {
ch = fgetc(fp);
if (ch == '\n')
lines++;
} while (ch != EOF);
if (ch != '\n' && lines != 0)
lines++;
fclose(fp);
return lines;
}
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
int counter = 0;
for (int i = 0; i < countlines(argv[1]); i++)
{
fgets(buffer_line_template_file, 100, template_file);
for (int j = 0; j < countlines(argv[2]); j++)
{
fgets(buffer_line_data_file, 100, data_file);
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
counter++;
printf("%d", counter);
}
}
}
printf("\n\n");
return 0;
}
Could someone please point me into the right direction ? For testing purposes I created a counter at the end which was a part of a small debug. There should be the print() function
As per #chux answer I got the following simplified code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
FILE *template_file = fopen(argv[1], "r");
FILE *data_file = fopen(argv[2], "r");
char buffer_line_template_file[100];
char buffer_line_data_file[100];
if (argc != 3)
{
perror("You didn't insert all the arguments!\n\n");
exit(EXIT_FAILURE);
}
if (template_file == NULL || data_file == NULL)
{
perror("Error while opening the file!\n\n");
exit(EXIT_FAILURE);
}
while(fgets(buffer_line_template_file, 100, template_file))
{
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0)
{
printf("%s\n", buffer_line_template_file);
}
}
}
printf("\n\n");
return 0;
}
The above code is giving me the following output, which is not what is expected:
john
john
john
john
john
john
is
is
is
is
is
the new
the new
the new
the new
the new
the new
guy
guy
guy
guy
guy
guy
Problems with OP's code
Imprecise definition of line.
Excessive recalculation
Fuzzy determination of the number of lines in a file.
Unlike string, which has a precise definition in C, reading a line is not so well defined. The primary specificity issue: does a line contain the trailing '\n'. If the first answer is Yes, then does the last text in a file after a '\n' constitute a line? (Excessively long lines are another issue, but let us not deal with that today.)
Thus possibly some lines end with '\n' and others do not, fooling strcmp("dog", "dog\n").
The easiest solution is to read a line until either 1) a '\n' is encountered, 2) EOF occurs or 3) line buffer is full. Then after getting a line, lop off the potential trailing '\n'.
Now all lines code subsequently works with have no '\n'.
fgets(buffer_line_template_file, 100, template_file);
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
OP's loop is incredible wasteful. Consider a file with 1000 lines. Code will loop, calling 1000 times countlines() (each countlines() call reads 1000 lines) times when one countlines() call would suffice.
// for (int j = 0; j < countlines(argv[2]); j++)
int j_limit = countlines(argv[2]);
for (int j = 0; j < j_limit; j++)
There really is no need to count the line anyways, just continue until EOF (fgets() returns NULL). So no need to fix its fuzzy definition. (fuzzy-ness concerns same issues as #1)
int counter = 0;
for (fgets(buffer_line_template_file, 100, template_file)) {
buffer_line_template_file[strcspn(buffer_line_template_file, "\n")] = '\0';
rewind(data_file);
while ((fgets(buffer_line_data_file, 100, data_file)) {
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) != 0) {
counter++;
printf("%d", counter);
}
}
}
Other simplifications possible - for another day.
FWIW, following counts lines of text allowing the last line in the file to optionally end with a '\n'.
unsigned long long FileLineCount(FILE *istream) {
unsigned long long LineCount = 0;
rewind(istream);
int previous = '\n';
int ch;
while ((ch = fgetc(inf)) != EOF) {
if (previous == '\n') LineCount++;
previous = ch;
}
return LineCount;
}
Note that this function may get a different result that fgets() calls. Consider a file of one line of 150 characters. fgets(..., 100,...) will report 2 lines. FileLineCount() reports 1.
[Edit] Updated code to conform to OP functionality.
int found = 0;
while (fgets(buffer_line_data_file, 100, data_file))
{
buffer_line_data_file[strcspn(buffer_line_data_file, "\n")] = '\0';
if (strcmp(buffer_line_template_file, buffer_line_data_file) == 0)
{
found = 1;
break;
}
}
if (!found) printf("%s\n", buffer_line_template_file);
This program prints the diff of two files file1.txt and file2.txt.
#include<stdio.h>
#include <stdlib.h>
#include <memory.h>
int main() {
FILE *fp1, *fp2;
int ch1, ch2;
char fname1[40], fname2[40];
char *line = NULL;
size_t len = 0;
ssize_t read;
char *line2 = NULL;
size_t len2 = 0;
ssize_t read2;
fp1 = fopen("file1.txt", "r");
fp2 = fopen("file2.txt", "r");
if (fp1 == NULL) {
printf("Cannot open %s for reading ", fname1);
exit(1);
} else if (fp2 == NULL) {
printf("Cannot open %s for reading ", fname2);
exit(1);
} else {
while ((read = getline(&line, &len, fp1)) != -1 && (read2 = getline(&line2, &len2, fp2)) != -1) {
if (!strcmp(line, line2)) {
printf("Retrieved diff on line %zu :\n", read);
printf("%s", line);
}
}
if (ch1 == ch2)
printf("Files are identical \n");
else if (ch1 != ch2)
printf("Files are Not identical \n");
fclose(fp1);
fclose(fp2);
}
return (0);
}
You already have a very good answer (and always will from chux), but here is a slightly different approach to the problem. It uses automatic storage to reading file2 into an array of strings and then compares each line in file1 against every line in file2 to determine whether it is unique. You can easily convert the code to dynamically allocate memory, but for sake of complexity that was omitted:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 256, MAXL = 512 };
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1);
int main (int argc, char **argv) {
FILE *fp1 = fopen (argc > 1 ? argv[1] : "file1.txt", "r");
FILE *fp2 = fopen (argc > 2 ? argv[2] : "file2.txt", "r");
size_t n1 = 0, n2 = 0;
if (!fp1 || !fp2) {
fprintf (stderr, "error: file open failed.\n");
return 1;
}
printf ("\nunique words in file1, not in file 2.\n\n");
file1infile2 (fp2, fp1, &n2, &n1);
printf ("\nanalyzed %zu lines in file1 against %zu lines in file2.\n\n",
n1, n2);
return 0;
}
void file1infile2 (FILE *fp2, FILE *fp1, size_t *n2, size_t *n1)
{
char buf[MAXC] = "";
char f2buf[MAXL][MAXC] = { "" };
size_t i;
*n1 = *n2 = 0;
while (*n2 < MAXL && fgets (buf, MAXC, fp2)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0;
strcpy (f2buf[(*n2)++], buf);
}
while (*n1 < MAXL && fgets (buf, MAXC, fp1)) {
char *np = 0;
if (!(np = strchr (buf, '\n'))) {
fprintf (stderr, "error: line exceeds MAXC chars.\n");
exit (EXIT_FAILURE);
}
*np = 0, (*n1)++;
for (i = 0; i < *n2; i++)
if (!(strcmp (f2buf[i], buf)))
goto matched;
printf (" %s\n", buf);
matched:;
}
}
Look over the code and let me know if you have any questions.
Example Use/Output
$ ./bin/f1inf2 dat/f1 dat/f2
unique words in file1, not in file 2.
john
the new
guy
analyzed 4 lines in file1 against 6 lines in file2.

Unable to read a file and pass into arguments

1) I'm trying to open a file, read the mix data (ints, chars and strings) and store them into args.
1.1) so in the sample.txt is a total of 13 (excluding args[0])
2) Need to read a file from terminal "./myprog.c < sample.txt"
Heres my code and have no idea where i went wrong:
sample.txt:
123 213 110 90 1
hello my friend
boo bleh
a b c
myprog.c:
#include <stdio.h>
int main()
{
int i = 1;
FILE *fstin=fopen(argv[0], "r"); //open the file
if (fstin == NULL) {
puts("Couldn't fopen...");
return -1;
}
//Getting all the inputs from file
while ((fscanf(fstin, "%d", argv[i])) != EOF){
i++;
}
fclose(fstin);
for (i=0; i<10; i++) {
printf("%d\n",argv[i]);
}
return 0;
}
Any help is greatly appreciated!
PS: Would like if anyone could post their complete solution? Will upload unto this post and let everyone have a review of this problem
PPS: Please excuse the poor level of coding as I am a beginner and completely new to C.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int ac, char *av[]){
int i, argc=0;
char **argv=NULL, data[16];
FILE *fstin = stdin;
if(ac == 2){
if(NULL==(fstin = fopen(av[1], "r"))){
puts("Couldn't fopen...");
return -1;
}
}
while (1==fscanf(fstin, "%15s", data)){
argv = realloc(argv, (argc+1)*sizeof(char*));
argv[argc] = malloc(strlen(data)+1);
strcpy(argv[argc++], data);
}
if(ac == 2)
fclose(fstin);
for (i=0; i<argc; ++i) {
printf("%s\n", argv[i]);
}
//deallocate
return 0;
}
You are making mistake at 2nd point where you divert your file to other file which is wrong. Actually you need to first compile and need to make executable.
gcc -o my_prog ./myprog.c -Wall
You need to execute this program as below to read file from c program:
./my_prog ./sample.txt
As you are new to C programming first go to man pages related to file operations.
Solution:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
//If command line argument is not inserted then stop operation
if (2 != argc) {
printf("Invalid number of arguments : %d\n", argc);
return -1;
}
int size = 0, ret = 0;
char *data = NULL;
FILE *fp = NULL;
//Open file in read mode given from command line argument
if (NULL != (fp = fopen(argv[1], "r")))
{
//Find size of file
fseek(fp, 0L, SEEK_END);
size = ftell(fp);
fseek(fp, 0L, SEEK_SET);
//if file is empty no need to read it.
if (size > 0)
{
//Data pointer which contains file information
data = (char *) calloc(sizeof(char), size);
if (NULL != data)
{
//Read whole file in one statement
fread(data, sizeof(char), size, fp);
printf("File %s is readed successfully\n", argv[1]);
printf("Data:\n");
printf("%s\n", data);
free(data); data = NULL;
}
else
{
perror("memory allocation failed\n");
ret = -1;
}
}
else
{
printf("File %s is empty\n", argv[1]);
}
fclose(fp); fp = NULL;
}
else
{
perror("File open failed\n");
ret = -1;
}
return ret;
}
Now Test it on your setup and if any query please post comments.

How can I read an XML file into a buffer in C?

I want to read an XML file into a char *buffer using C.
What is the best way to do this?
How should I get started?
And if you want to parse XML, not just reading it into a buffer (something which would not be XML-specific, see Christoph's and Baget's answers), you can use for instance libxml2:
#include <stdio.h>
#include <string.h>
#include <libxml/parser.h>
int main(int argc, char **argv) {
xmlDoc *document;
xmlNode *root, *first_child, *node;
char *filename;
if (argc < 2) {
fprintf(stderr, "Usage: %s filename.xml\n", argv[0]);
return 1;
}
filename = argv[1];
document = xmlReadFile(filename, NULL, 0);
root = xmlDocGetRootElement(document);
fprintf(stdout, "Root is <%s> (%i)\n", root->name, root->type);
first_child = root->children;
for (node = first_child; node; node = node->next) {
fprintf(stdout, "\t Child is <%s> (%i)\n", node->name, node->type);
}
fprintf(stdout, "...\n");
return 0;
}
On an Unix machine, you typically compile the above with:
% gcc -o read-xml $(xml2-config --cflags) -Wall $(xml2-config --libs) read-xml.c
Is reading the contents of the file into a single, simple buffer really what you want to do? XML files are generally there to be parsed, and you can do this with a library like libxml2, just to give one example (but notably, is implemented in C).
Hopefully bug-free ISO-C code to read the contents of a file and add a '\0' char:
#include <stdlib.h>
#include <stdio.h>
long fsize(FILE * file)
{
if(fseek(file, 0, SEEK_END))
return -1;
long size = ftell(file);
if(size < 0)
return -1;
if(fseek(file, 0, SEEK_SET))
return -1;
return size;
}
size_t fget_contents(char ** str, const char * name, _Bool * error)
{
FILE * file = NULL;
size_t read = 0;
*str = NULL;
if(error) *error = 1;
do
{
file = fopen(name, "rb");
if(!file) break;
long size = fsize(file);
if(size < 0) break;
if(error) *error = 0;
*str = malloc((size_t)size + 1);
if(!*str) break;
read = fread(*str, 1, (size_t)size, file);
(*str)[read] = 0;
*str = realloc(*str, read + 1);
if(error) *error = (size != (long)read);
}
while(0);
if(file) fclose(file);
return read;
}
Install libxml2 as a NuGet package in Visual studio(I am using Vs 2015 to test this)
Copy and paste the contents under example XML file in a notepad and save the file as example.xml
Copy and past the code under //xml parsing in to Vs
Call the function from main with xml file name as an argument
You will be getting the xml data in configReceive
That's all...
example XML file:
<?xml version="1.0" encoding="utf-8"?>
<config>
<xmlConfig value1="This is a simple XML parsing program in C"/>
<xmlConfig value2="Thank you : Banamali Mishra"/>
<xmlConfig value3="2000000"/>
<xmlConfig value4="80"/>
<xmlConfig value5="10"/>
<xmlConfig value6="1"/>
</config>
Here is the source code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <libxml/xmlreader.h>
#include <libxml/xmlmemory.h>
#include <libxml/parser.h>
char configReceive[6][80] = { " " };
//xml parsing
void ParsingXMLFile(char *filename) {
char *docname;
xmlDocPtr doc;
xmlNodePtr cur;
xmlChar *uri;
char config[6][80] = { "value1", "value2", "value3", "value4", "value5", "value6" };
int count = 0;
int count1 = 0;
docname = filename;
doc = xmlParseFile(docname);
cur = xmlDocGetRootElement(doc);
cur = cur->xmlChildrenNode;
while (cur != NULL) {
if ((!xmlStrcmp(cur->name, (const xmlChar *)"xmlConfig"))) {
uri = xmlGetProp(cur, (xmlChar *)config[count++]);
strcpy(configReceive[count1++], (char *)uri);
xmlFree(uri);
}
cur = cur->next;
}
count = 0;
count1 = 0;
xmlFreeDoc(doc);
}
You can use the stat() function to get the file size. then allocate a buffer using malloc after it reading the file using fread.
the code will be something like that:
struct stat file_status;
char *buf = NULL;
FILE * pFile;
stat("tmp.xml", &file_status);
buf = (char*)malloc(file_status.st_size);
pFile = fopen ("tmp.xml","r");
fread (buf,1,file_status.st_size,pFile);
fclose(pFile);
Here is a full program that reads in a whole XML file (really, any file), into a buffer. It includes about as much error-checking as would be useful.
N.B. everything is done in main(). Turning it into a callable function is left as an exercise for the reader.
(Tested, compiled with GCC 4.3.3. Switches were -Wall -W --pedantic --ansi.)
Comments on this will be addressed in approximately eight hours.
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char *argv[]) {
char *buffer; /* holds the file contents. */
size_t i; /* indexing into buffer. */
size_t buffer_size; /* size of the buffer. */
char *temp; /* for realloc(). */
char c; /* for reading from the input. */
FILE *input; /* our input stream. */
if (argc == 1) {
fprintf(stderr, "Needs a filename argument.\n");
exit(EXIT_FAILURE);
}
else if (argc > 2) {
fprintf(stderr, "Well, you passed in a few filenames, but I'm only using %s\n", argv[1]);
}
if ((input = fopen(argv[1], "r")) == NULL) {
fprintf(stderr, "Error opening input file %s\n", argv[1]);
exit(EXIT_FAILURE);
}
/* Initial allocation of buffer */
i = 0;
buffer_size = BUFSIZ;
if ((buffer = malloc(buffer_size)) == NULL) {
fprintf(stderr, "Error allocating memory (before reading file).\n");
fclose(input);
}
while ((c = fgetc(input)) != EOF) {
/* Enlarge buffer if necessary. */
if (i == buffer_size) {
buffer_size += BUFSIZ;
if ((temp = realloc(buffer, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core while reading file.\n");
fclose(input);
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
}
/* Add input char to the buffer. */
buffer[i++] = c;
}
/* Test if loop terminated from error. */
if (ferror(input)) {
fprintf(stderr, "There was a file input error.\n");
free(buffer);
fclose(input);
exit(EXIT_FAILURE);
}
/* Make the buffer a bona-fide string. */
if (i == buffer_size) {
buffer_size += 1;
if ((temp = realloc(buffer, buffer_size)) == NULL) {
fprintf(stderr, "Ran out of core (and only needed one more byte too ;_;).\n");
fclose(input);
free(buffer);
exit(EXIT_FAILURE);
}
buffer = temp;
}
buffer[i] = '\0';
puts(buffer);
/* Clean up. */
free(buffer);
fclose(input);
return 0;
}
I believe that question was about XML parsing and not about file reading, however OP should really clarify this.
Any way you got plenty example how to read file.
Another option to xml parsing in additional to sgm suggestion will be Expat library
Suggestion: Use memory mapping
This has the potential to cut down on useless copying of the data. The trick is to ask the OS for what you want, instead of doing it. Here's an implementation I made earlier:
mmap.h
#ifndef MMAP_H
#define MMAP_H
#include <sys/types.h>
struct region_t {
void *head;
off_t size;
};
#define OUT_OF_BOUNDS(reg, p) \
(((void *)(p) < (reg)->head) || ((void *)(p) >= ((reg)->head)+(reg)->size))
#define REG_SHOW(reg) \
printf("h: %p, s: %ld (e: %p)\n", reg->head, reg->size, reg->head+reg->size);
struct region_t *do_mmap(const char *fn);
#endif
mmap.c
#include <stdlib.h>
#include <sys/types.h> /* open lseek */
#include <sys/stat.h> /* open */
#include <fcntl.h> /* open */
#include <unistd.h> /* lseek */
#include <sys/mman.h> /* mmap */
#include "mmap.h"
struct region_t *do_mmap(const char *fn)
{
struct region_t *R = calloc(1, sizeof(struct region_t));
if(R != NULL) {
int fd;
fd = open(fn, O_RDONLY);
if(fd != -1) {
R->size = lseek(fd, 0, SEEK_END);
if(R->size != -1) {
R->head = mmap(NULL, R->size, PROT_READ, MAP_PRIVATE, fd, 0);
if(R->head) {
close(fd); /* don't need file-destructor anymore. */
return R;
}
/* no clean up of borked (mmap,) */
}
close(fd); /* clean up of borked (lseek, mmap,) */
}
free(R); /* clean up of borked (open, lseek, mmap,) */
}
return NULL;
}

Resources