Read one string at a time from a file in C - c

How do I read input one string at a time to call another function in C. I thought this would work, but my output hangs:
#define BUFFMT "%255"
#define LINE_LEN 256
#define START_COUNT 1
// filename is declared in the main file elsewhere. I know the file opens since I tried an //old method I use to read one line at time using fgets, but I didn't know how to do one //string at a time. Thanks.
FILE *OpenFile(const char *fileName)
{
FILE *fptr;
if ((fptr = fopen(fileName, "r")) == NULL) {
fprintf(stderr, "Error opening file %s, exiting...", fileName);
exit(EXIT_FAILURE);
}
return fptr;
}
LIST *CreateList(FILE *fp)
{
char buf[LINE_LEN];
while (scanf(BUFFMT"s", buf) != EOF) {
printf("%s: \n", buf);
}
}

scanf() is going to read from the terminal, so it's going to hang waiting for you to type in your input. Use fscanf(fp, BUFFMT"s", buf) instead.

Try this instead of your scanf:
fgets (buf, sizeof (buf), fp)

Have you tried using fgets()
fgets()
fgets() reads up to size-1 characters
from stream and stores them in buffer.
fgets() stores the null character
('\0') after the last character read
into the buffer and returns 'buffer'
if everything works fine, or NULL on
error or end of file.

Related

C - Print lines from file with getline()

I am trying to write a simple C program that loads a text-file, prints the first line to screen, waits for the user to press enter and then prints the next line, and so on.
As only argument it accepts a text-file that is loaded as a stream "database". I use the getline()-function for this, according to this example. It compiles fine, successfully loads the text-file, but the program never enters the while-loop and then exits.
#include <stdio.h>
#include <stdlib.h>
FILE *database = NULL; // input file
int main(int argc, char *argv[])
{
/* assuming the user obeyed syntax and gave input-file as first argument*/
char *input = argv[1];
/* Initializing input/database file */
database = fopen(input, "r");
if(database == NULL)
{
fprintf(stderr, "Something went wrong with reading the database/input file. Does it exist?\n");
exit(EXIT_FAILURE);
}
printf("INFO: database file %s loaded.\n", input);
/* Crucial part printing line after line */
char *line = NULL;
size_t len = 0;
ssize_t read;
while((read = getline(&line, &len, database)) != -1)
{
printf("INFO: Retrieved line of length %zu :\n", read);
printf("%s \n", line);
char confirm; // wait for user keystroke to proceed
scanf("%c", &confirm);
// no need to do anything with "confirm"
}
/* tidy up */
free(line);
fclose(database);
exit(EXIT_SUCCESS);
}
I tried it with fgets() -- I can also post that code --, but same thing there: it never enters the while-loop.
It might be something very obvious; I am new to programming.
I use the gcc-compiler on Kali Linux.
Change your scanf with fgetline using stdin as your file parameter.
You should step through this in a debugger, to make sure your claim that it never enters the while loop is correct.
If it truly never enters the while loop, it is necessarily because getline() has returned -1. Either the file is truly empty, or you have an error reading the file.
man getline says:
On success, getline() and getdelim() return the number of
characters
read, including the delimiter character, but not including the termi‐
nating null byte ('\0'). This value can be used to handle embedded
null bytes in the line read.
Both functions return -1 on failure to read a line (including end-of-
file condition). In the event of an error, errno is set to indicate
the cause.
Therefore, you should enhance your code to check for stream errors and deal with errno -- you should do this even when your code works, because EOF is not the only reason for the function
to return -1.
int len = getline(&line, &len, database);
if(len == -1 && ferror(database)) {
perror("Error reading database");
}
You can write more detailed code to deal with errno in more explicit ways.
Unfortunately handling this thoroughly can make your code a bit more verbose -- welcome to C!

How to write and read more than one word in C string

I'm doing program and in this program i have two processes, server and client. Server have to read string from input and then write into FIFO file. Client have to read strings from FIFO file and then wrote into .txt file.
This are only function responsible for server and client. File FIFO and fork'ing is doing in main function.
void server(void)
{
FILE *fp1, *fp2;
char string[100];
while(1)
{
fp1 = fopen("FIFO1", "w");
fprintf(stdout, "Type string: ");
scanf("%s", string);
fputs(string, fp1);
fclose(fp1);
sleep(1);
}
}
void client(void)
{
FILE *fp,*fp1;
char string[100];
while(1)
{
fp = fopen("FIFO1", "r");
fgets(string, 100, fp);
fclose(fp);
fp1 = fopen("file.txt", "a");
fprintf(fp1,"%d_file: I get: %s\n", getpid(), string);
fclose(fp1);
}
}
And my problem is when i type a string like "stack overflow", when i have two word, in my file.txt i get to lines:
8965_file: I get: stack
8965_file: I get: overflow
Is there any way to write this in one line ? Like this:
8965_file: I get: stack overflow
It's because of scanf() which stops reading when a white space occurs for the "%s" specifier, change it to "%99[^\n]" or use fgets() instead but keep in mind that fgets() will read the '\n' and fputs() will add one so you might end up with more lines than you want.
Hint: For an array use fgets(string, sizeof(string), fp); to make your code easier to maintain.
You can use gets(string) to get more than one word instead of using scanf().
Reference Link : www.keizerkong.com/c/c_string.html

fgets() not working after fscanf()

I am using fscanf to read in the date and then fgets to read the note.
However after the first iteration, fscanf returns a value of -1.
I used GDB to debug the program step by step. It works fine until the first use of fgets. When I try print out the line read by fgets on the first iteration, it gives me this:
(gdb) print line
$6 = "\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000\000\000\000q\352\261\a\370\366\377\267.N=\366\000\000\000\000\003\000\000\000\370xC\000\000\000\000\000\000\000\000\000\001\000\000\000\227\b\000\000\070\367\377\267H\364\377\267\362\202\004\bdoD\000\354\201\004\b\001\000\000\000\304oC\000p\363\377\277\260zC\000D\363\377\277\n!B\000\064\363\377\277\354\201\004\b(\363\377\277TzC\000\000\000\000\000\070\367\377\267\001\000\000\000\000\000\000\000\001\000\000\000\370xC\000\001\000\000\000\000\000\312\000\000\000\000\000\377\260\360\000\001\000\000\000\277\000\000\000\364\317\000\000\344\261\\\000\000\000\000\000p\363\377\277|\233\004\b\350\362\377\277 \204\004\b\005\000\000\000|\233\004\b\030\363\377\277"
It looks like fgets reads the remaining entries and then stores them all in a single string.
I am not sure why it is doing this.
Here is the main code:
int main(int argc, char* argv[]) {
FILE* file;
int numEntries, i = 0;
int index = atoi(argv[1]);
char line[SIZE];
JournalEntry *entry;
/*argument provided is the entry user wants to be displayed*/
if (argc > 2) {
perror("Error: Too many arguments provided");
}
file = fopen("journalentries.txt", "r");
if (file == NULL) {
perror("Error in opening file");
}
if (fscanf(file, "%d", &numEntries) != 1) {
perror("Unable to read number of entries");
}
entry = (JournalEntry*)malloc(numEntries * sizeof(JournalEntry));
if (entry == NULL) {
perror("Malloc failed");
}
for (i = 0; i < numEntries; i++) {
if (fscanf(file, "%d/%d/%d", &entry[i].day, &entry[i].month, &entry[i].year) != 3) {
perror("Unable to read date of entry");
}
if (fgets(line, sizeof(line), file) == NULL) {
perror("Unable to read text of entry");
}
}
printf("%d-%02d-%02d %s: ", entry[index].year, entry[index].month, entry[index].day, entry[index].text);
if(ferror(file)) {
perror("Error with file");
}
fclose(file);
free(entry);
return 0;
}
The file that I have to read:
The very first line contains the number of entries to be read
4
12/04/2010
test
18/04/2010
test2
03/05/2010
test3
05/08/2009
test4
The struct JournalEntry located in the header file:
typedef struct {
int day;
int month;
int year;
char text[250];
} JournalEntry;
It looks like fgets reads the remaining entries and then stores them all in a single string.
Yes, '\r' is not line terminator. So when fscanf stops parsing at the first invalid character, and leaves them in the buffer, then fgets will read them until end of line. And since there are no valid line terminators in the file, that is until end of file.
You should probably fix the file to have valid (Unix?) line endings, for example with suitable text editor which can do it. But that is another question, which has been asked before (like here), and depends on details not included in your question.
Additionally, you need dual check for fscanf return value. Use perror only if return value is -1, otherwise error message will not be related to the error at all. If return value is >=0 but different from what you wanted, then print custom error message "invalid input syntax" or whatever (and possibly use fgets to read rest of the line out of the buffer).
Also, to reliably mix scanf and fgets, I you need to add space in the fscanf format string, so it will read up any whitespace at the end of the line (also at the start of next line and any empty lines, so be careful if that matters), like this:
int items_read = scanf("%d ", &intvalue);
As stated in another answer, it's probably best to read lines with fgets only, then parse them with sscanf line-by-line.
Don't mix fscanf() and fgets(), since the former might leave stuff in the stream's buffer.
For a line-oriented format, read only full lines using fgets(), then use e.g. sscanf() to parse what you've read.
The string you see when running GDB really ends at the first null character:
"\rtest\r18/04/2010\rtest2\r03/05/2010\rtest3\r05/08/2009\rtest4\r\n\000"
The other data after is ignored (when using ordinary str-functions);

print binary file

Say you have a file dog.txt
The
quick
brown
fox
jumps
over
the
lazy
dog
You can print the lines like this
#include <stdio.h>
int
main (void)
{
char buf[10];
FILE *fp = fopen ("dog.txt", "r");
while (fgets (buf, sizeof buf, fp))
printf ("%s", buf);
return 0;
}
But what if each "line" was separated by a null character (\0), instead of a newline (\n)? How would you print each "line" ?
The difference between "text" file handling and any other file handling is that the "text" functions assume certain things (for example, that \n is a separator). If that's not the case for you, you obviously cannot use the "text" manipulation functions. You do fread, and parse the content yourself.
If the file is not a text file (that is, if it contains non-printable ASCII characters), treat it as binary.
Rather than reading a "line" at a time (which is a text file concept), read in a buffer at a time (e.g. 1024 characters at a time).
Output each character that you read one at a time, unless you encounter whatever line delimiter the file uses (e.g. the "null" character in your question). When that character is encountered, output a newline instead.
You open a file in binary mode by including the "b" flag, e.g.
FILE *fp = fopen("dog.txt", "rb");
Use fread to read data one buffer at a time.
n = fread(buffer, sizeof(char), BUFFER_SIZE, source);
This is a trimmed down version of
WhozCraig’s
deleted answer
If all you want to do is dump data from the input file to stdout, replacing any imbedded null-chars (0) with newlines, then just do that. read-ahead buffering and such is honestly overkill for the simplicity of this problem, and besides, the fopen/fread/etc.. family already buffers for you.
Note: this assumes exactly what the OP specified, the this is otherwise a reagular "text" file save for the oddity that imbedded null-chars (0)'s should be treated as newlines in the output stream:
#include <stdio.h>
#include <errno.h>
int main(int argc, char* argv[])
{
FILE *fp = NULL;
fp = fopen(argv[1], "rb");
do
{ // pull next char, break on EOF, subst '\n' on 0.
int ch = fgetc(fp);
if (EOF == ch)
break;
if (0 == ch)
ch = '\n';
fputc(ch, stdout);
} while (true);
fclose(fp);
return EXIT_SUCCESS;
}

C Language: popen() with fread()?

I've been stuck on this for a few days and it's getting really frustrating.
I'm using popen() to call a command line process and get its output and store it in a C string. I was using fgets() but it seems that breaks after a new line, so I'm using fread(). The only problem is that the returned C string is sometimes messed up.
Here's my code:
const char *cmd = "date";//This the shell command
char buf[BUFSIZ];//Output of the command
FILE *ptr;
int c;
if ((ptr = popen(cmd, "r")) != NULL)
while(fread(buf, sizeof(buf),1, ptr))
while ((c = getchar()) != EOF)
printf("output = %s", buf);
(void) pclose(ptr);
The final C string sometimes has weird characters in it that shouldn't be there, or sometimes no string is even available. Can anybody please help? ):
Edit: Here is what I was doing when using fgets() The Shell command can be anything that outputs text though. Not just "date."
if ((ptr = popen(cmd, "r")) != NULL)while (fgets(buf, BUFSIZ, ptr) != NULL)printf("output = %s", buf);(void) pclose(ptr);
fread doesn't insert a NUL terminator after what it reads. You need to check the return value to know how much it read, and only print that much. If you read with fread, you typically want to write the data with fwrite, something on this order:
long bytes;
while ((bytes=fread(buf, sizeof(buf), 1, ptr))>0)
fwrite(buf, bytes, 1, stdout);
Well, fgets is the right way to do it.
FILE *ptr;
if (NULL == (ptr = popen(cmd, "r"))) {
/* ... */
}
while(fgets(buf, sizeof(buf), ptr) != NULL) {
/* There is stuff in 'buf' */
}
I think the reason fgets wasn't working for you is that you were doing something wrong.
Now, here's why I think you are running into trouble with your current code:
You are not checking how much fread actually returned
You are reading with getchar and discarding stuff
You don't have a NUL terminator in the buffer
Get this right and it will all be better: fread might legally read less than you told it to.
The output from date doesn't include the '\0' (NUL) character you need to properly terminate the string. Keep track of the number of characters read and put in the NUL yourself.
Though really, you should be using fgets, getline or similar text-oriented functions to read from a program such as date. getline is especially easy (and safe since it does some memory management for you):
FILE *fp = popen("date", "r");
char *ln = NULL;
size_t len = 0;
while (getline(&ln, &len, fp) != -1)
fputs(ln, stdout);
free(ln);
pclose(fp);
Below is the correct way to use fread for process output with popen:
const char *cmd = "date";
char buf[BUFSIZ];
FILE *ptr;
if ((ptr = popen(cmd, "r")) != NULL) {
/* Read one byte at a time, up to BUFSIZ - 1 bytes, the last byte will be used for null termination. */
size_t byte_count = fread(buf, 1, BUFSIZ - 1, ptr);
/* Apply null termination so that the read bytes can be treated as a string. */
buf[byte_count] = 0;
printf("%s\n", buf);
}
(void) pclose(ptr);
As you can see, the primary problem is to correctly deal with null termination. The two size parameter of fread is also important, you have to let it read character by character. Note that in the case of popen, fread will only return 0 if the process has exited without giving any output. It will not return 0 if it takes a long time for the process to print anything.
If the output is larger than BUFSIZ, you can wrap fread with a while loop.

Resources