Filtering lines using fscanf - c

I am trying to read a file of the form
A number,number
A number,number
[space] B number,number
etc
where I want to read only the lines that do start with a space (ie, in the example above, the last line only). I wrote this loop:
while ((g = fscanf(fp," %c %x,%d\n",&a,&b,&c) != EOF){
printf("%c %x,%d\n",a,b,c);
}
but despite the space I put at the beginning of the string, it still outputs all the lines. I know I can filter them inside the loop, but is it possible to specify it in the fscanf?

OP: it possible to specify it in the fscanf?
A: Yes, but its ugly. Use the best tool for the job.
Use fgets(), then scan with sscanf().
char buf[100];
char a;
unsigned b;
int c;
while (fgets(buf, sizeof buf, fp) != NULL) {
// Thank-you #Chris Dodd
if ((buf[0] == ' ') && (sscanf(buf, " %c%x,%d", &a,&b,&c) == 3)) {
printf("%c %x,%d\n",a,b,c);
}
}

One way to achieve what you want is to use getc and check for space , if space is found call ungetc and read the line using fgets else read the line and skip it

Related

using fscanf to not read in logn blank lines after reading in a sentence

while((fscanf(datafile, " %127[^;] %[^\n]", name, movie)) == 2) {
printf("%s\n", movie);
for(i=0; i<=strlen(movie); i++) {
if(movie[i]!='\0'){
printf("%c", movie[i]);
} else {
printf("44 %d", i);
break;
}
}
printf("%d\n", strlen(movie));
break;
insert_tree(tree, name, movie);
}
i have this code
fscanf reads in all the strings after semicolon but it also reads in long blank spaces after a sentence has ended in the file
how can i make this stop at just the right point??
Can't. To read a line including spaces, yet stop when the lines ends with spaces requires knowing that the trailing spaces exist without reading them.
Instead, read the line and post-process it.
char buf[127+1+1];
fgets(buf, sizeof buf, stdin);
buf[strcspn(buf, "\n")] = '\0'; // Drop potential \n
// get rid of trailing ' '
/// This is inefficient, but shown for simplicity - certainly OP can do better.
char *p;
while ((p = strrchr(buf, ' ')) != NULL) *p = '\0';
Firstly, never use scanf or fscanf. Read a line from the file and then use sscanf on that. This way your code won't go berserk on input errors and throw away large amounts of data. It'll also generally simplify your format string.
As to the long blank spaces, I'd suggest you just looked for the last non-blank space in the strings and terminated the string there. Sadly you'll have to do this by hand as there's no standard library function.
It'd be helpful to know the format of these lines. If it's just 'name;movie' (and you're guaranteed not to have ; in the name or the movie part) you could use strchr to find the separator

How to take inputs for strings one by one in C

I have to take inputs like below, and print the same (only the sentences):
2
I can't believe this is a sentence.
aarghhh... i don't see this getting printed.
Digit 2 shows the number of lines to be followed (2 lines after this here).
I used all the options scanf and fgets with various regex used.
int main() {
int t;
char str[200];
scanf ("%d", &t);
while (t > 0){
/*
Tried below three, but not getting appropriate outputs
The output from the printf(), should have been:
I can't believe this is a sentence.
aarghhh... i don't see this getting printed.
*/
scanf ("%[^\n]", str);
//scanf("%200[0-9a-zA-Z ]s", str);
//fgets(str, 200, stdin);
printf ("%s\n", str);
t--;
}
}
I am sorry, i have searched all related posts, but I am not able to find any answer to this:
All versions of scanf() produce no results, and fgets() prints only the first sentence.
Thanks in advance.
You should just use fgets(). Remember that it will keep the linefeed, so you might want to remove that manually after reading the line:
if(scanf("%d", &t) == 1)
{
while(t > 0)
{
if(fgets(str, sizeof str, stdin) != NULL)
{
const size_t len = strlen(str);
str[len - 1] = '\0';
printf("You said '%s'\n", str);
--t;
}
else
printf("Read failed, weird.\n");
}
}
To make it easier let's say the input is "2\none\ntwo\n".
When you start your program, before the first scanf() the input buffer has all of it and points to the beginning
2\none\ntwo
^
After the first scanf(), the "2" is consumed leaving the input buffer as
2\none\ntwo
^^
And now you attempt to read everything but a newline ... but the first thing in the buffer is a newline, so nothing gets read.
Suggestion: always use fgets() to read full lines, and then parse the input as you think is better.
To use regex in C you must include regex.h. In this case, you do not need regex. Where you have "%[^\n]", replace it with "%s". Make sure that you include stdio.h.

fscanf problems, taking a char a time

When I try to use fscanf to read a text file that contains
PIZZA CHIPS BURGERS as one of the lines. I am trying to add them to a variable, but instead it only takes one letter at a time.
if (infile) {
while (fscanf(infile, "%c", &cit) > 0) {
printf("%c\n",cit);
How do I make it take the word PIZZA instead of P I Z Z A?
char word[256];
if (infile)
{
while (fscanf(infile, "%255s", word) == 1)
printf("Word: %s\n", word);
}
Note that if you want a whole line read in at a time, spaces and all, then you'll use fgets():
char line[4096];
if (infile)
{
while (fgets(line, sizeof(line), infile) != 0)
printf("Line: %s", line);
}
NB: fgets() keeps the newline unless the line is so long that it has to be truncated, so the printf() format doesn't need a newline of its own. Generally, it is easier to control input if you use fgets() and sscanf() than if you use just scanf() or fscanf(). In particular, you can usually give better error diagnostics because you have all of what the user typed. You can also try alternative formats if that's necessary.

ANSI C - how to read from stdin word by word?

Code:
#include <stdio.h>
int main(void) {
char i[50];
while(scanf("%s ", i)){
printf("You've written: %s \n", i);
}
printf("you have finished writing\n");
return 0;
}
One problem is that the code doesn't do as it is expected to. If I typed in:
abc def ghi.
It would output:
You've written: abc
You've written: def
How can I fix it? The goal is to read every single word from stdin until it reaches "ENTER" or a "." (dot).
#cnicutar is pretty close, but you apparently only want to start reading at something other than white-space, and want to stop reading a single word when you get to whitespace, so for you scanset, you probably want something more like:
while(scanf(" %49[^ \t.\n]%*c", i)) {
In this, the initial space skips across any leading white space. The scan-set then reads until it gets to a space, tab, new-line or period. The %*c then reads (but throws away) the next character (normally the one that stopped the scan).
This can, however, throw away a character when/if you reach the end of the buffer, so you may want to use %c, and supply a character to read into instead. That will let you recover from a single word longer than the buffer you supplied.
How about:
scanf("%49[ ^\n.]", str)
Or something like that.
Ditch scanf altogether and go with fgets:
while (fgets(i, sizeof i, stdin))
{
printf("you've written: %s\n", i);
}
with the following caveats:
If there's room in the target buffer, fgets will store the trailing newline as part of the input;
If you want to stop reading on finding a ., you'll have to add some logic to look for it in the input string, such as the following:
int foundDot = 0;
while (fgets(i, sizeof i, stdin) && !foundDot)
{
char *dot = strchr(i, '.');
char *newline = strchr(i, '\n');
if (dot != NULL)
{
foundDot = 1;
*dot = 0; // overwrite the '.' character with the 0 terminator
}
if (newline != NULL)
{
*newline = 0; // overwrite newline character with 0 terminator
}
/**
* Assuming you don't want to print a blank line if you find a dot
* all by itself.
*/
if (strlen(i) > 0)
printf("you've written: %s\n", i);
}
The easiest way to do this is with flex. Otherwise you are repeating a bunch of difficult, complex work, and are likely to make mistakes.
Also, read lex and yacc, 2nd edition.

Ignoring whitespaces while reading input files in C

I'm trying to write code that registers the first word of every line as a command, but I want to be able to read the word regardless of there being spaces or not in front of it. I'm currently using fgets() and strncmp the first x characters of each line to do this, but it doesn't work for an arbitrary amount of whitespace. I have tried using sscanf() inside the fgets() loop to store the first word of each line to a variable but it seems to be skipping through lines and reading them incorrectly. I would rather not post the code as it is quite lengthy but it is basically this:
while( fgets(Line, BUFFER, input) != NULL )
{
if(strncmp(Line, "Word", 4) != NULL)
//DO SOMETHING
}
There are many strncmps and I would like for each of them to ignore an arbitrary amount of preceding spaces.
You can use isspace to skip over whitespace:
#include <ctype.h>
while( fgets(Line, BUFFER, input) != NULL )
{
char *p = Line;
while (isspace(*p)) // skip whitespace
p++;
if(strncmp(p, "Word", 4) != NULL)
//DO SOMETHING
}

Resources