• C

Using fgets() and isalpha() to ignore certain lines in a file.

Hi,

I'm trying to write a C program that takes user input of a file path (ie. a text file
containing any number of lines) and then prints only the lines with JUST alphabetical
characters. Below is the process i've coded to do this, but nothing prints to screen
when i test it. I've tried different variations of this, with varying results, but to no avail.

--------------------------------------------
void process_file (char *path) {
    FILE *thefile;
    char buf[128];
   
    thefile = fopen (path, "r");
    if (thefile != NULL) {
        while (fgets(buffer, 128, thefile) != NULL) {
            int i;
            int j = 0;
            for (i = 0; i < sizeof(buffer); i++) {
                if (isalpha(buffer[i])) {
                    j++;
                }
            }

            if (j == sizeof(buffer)) {
                    printf("%s\n", buffer);
                   
                }
        }
        fclose(thefile);
    }
    else {
    fprintf(stderr, "error reading file", path);
        exit(1);
    }
}
------------------------------------------------

In addition to this, can someone enlighten me on  the most effective way to code
further filtering of the results, so if a user were to provide a command line argument
(say *ee* for example), the program would return only those lines with an "ee" in them.
Any help at all would be appreciated.

Cheers.

sneak_186Asked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

ozoCommented:
sizeof(buffer) is always 128
try
     while (fgets(buffer, 128, thefile) != NULL) {
            int i;
            int j = 0;
            for (i = 0; buffer[i]; i++) {
                if (!isalpha(buffer[i])) {
                    j++;
                }
            }

            if ( !j ) {
                    printf("%s\n", buffer);
                   
                }
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
PaulCaswellCommented:
You have two problems.

1. You declare buf[128]  and then read into buffer.

2. The fgets call will read a line of characters but the last two will be \n\0 (a return code followed by a NULL terminator for the string.

Change:

          for (i = 0; i < sizeof(buffer); i++) {

to stop at a '\0' in buffer[i] (or buf)

and here:

                if (isalpha(buffer[i])) {

you need to allow '\r' and '\n'.

Paul
0
sneak_186Author Commented:
Thanks for the speedy reply.
I've managed to get the first part working with a variation of the code ozo supplied.
What I did was change the for loop and if statement to count the number of invalid
characters (using !isalpha()) instead of the number of alpha characters, as I was
trying to do before. Thanks to Paul too for pointing out the errors I had.

Now on to the filtering. I previously managed to code a filter procedure that checks
whether a single char is present in a string, but how do I go about checking whether
a (smaller) string is present in another string.

This is my coding so far:

----------------------------------------

/*
Take two strings (line and filter) and if filter is found anywhere
in line, then print line, otherwise do nothing.
*/
void check_line (char *line, char *filter) {
    int linesize, filtersize;
    int fpos, lpos;
    for (lpos = 0; lpos < linesize; lpos++) {
        for (fpos = 0; fpos < filtersize; fpos++) {
            if (filter[fpos] == line[lpos]) {
                if (filter[fpos+1] == line[lpos+1]) {
                    printf("%s", line);
                }
            }
        }

    }
}

-------------------------------------------------
0
Choose an Exciting Career in Cybersecurity

Help prevent cyber-threats and provide solutions to safeguard our global digital economy. Earn your MS in Cybersecurity. WGU’s MSCSIA degree program was designed in collaboration with national intelligence organizations and IT industry leaders.

ozoCommented:
#include <string.h>

char * strstr(const char *big, const char *little);
0
PaulCaswellCommented:
Two points (again :-):

    int linesize, filtersize;

should probably be:

    int linesize = strlen(line), filtersize = strlen(filter);

secondly Instead of:

       for (fpos = 0; fpos < filtersize; fpos++) {
            if (filter[fpos] == line[lpos]) {
                if (filter[fpos+1] == line[lpos+1]) {
                    printf("%s", line);
                }
            }
        }

use something like if (strncmp(&line[pos], filter, filtersize) == 0)

Paul
0
sneak_186Author Commented:
OK, i get that... but how do I make the '*' (or another char.... i'll use '@' for example)
character represent ANY character... so if the user enters the filter @xpe@t,
then "expert", for example, would be one of the results. And if they entered expe*, then
"expert" would be a result then too.
0
sneak_186Author Commented:
Ok, i managed to work it out.... i think. More testing.
0
PaulCaswellCommented:
Here's a wild card file name matcher I got from elsewhere in EE. I have tinkered with it a bit.

// Simple Wild card matching from Chef-Hunter at EE.
bool WildCmp(const char* search, const char* in, char * match)
{
      // Record the match character.
      *match = *search;
      // End of search string?
      if(*search == '\0')
      {
            // Good if both finished?
            return (*in == '\0');
      }
      // End of in string but not search string?
      if(*in == '\0')
      {
            // If search was a '*'
            if(*search == '*')
            {
                  // Yes! The rest must match.
                  return WildCmp(search+1,in,match);
            }
            // Not a '*, not complete match.
            return false;
      }
      // Check for actual match.
      if(toupper(*search) == toupper(*in) )
      {
            return WildCmp(search+1, in+1, match+1);
      }
      // Check for '?' match.
      if(*search == '?')
      {
            return WildCmp(search+1, in+1, match+1);
      }
      // Check for '*'
      if(*search == '*')
      {
            return WildCmp(search+1, in, match+1)      // Match nothing.
                  || WildCmp(search+1, in+1, match+1)      // Or the next character.
                  || WildCmp(search, in+1, match+1);      // Or the one after.
      }
      // Failed.
      return false;
}

Please DO NOT use this if this is homework or coursework. It is far too sophisticated for a student to have invented.

Paul
0
sneak_186Author Commented:
Thanks for all the help guys. I've split the points between ozo and Paul.
Don't worry Paul... i can't even look at the 'simple' wildcard match code without going dizzy,
let alone work out how to use it. I managed to code the filter part using a couple of for loops.

Cheers.
0
PaulCaswellCommented:
>>I managed to code the filter part using a couple of for loops.
Well done! Its not a simple process.

>>...going dizzy
It takes some brain work :-) Some day when we have time I'll walk through it for you, but later in your course when you've done recursion perhaps.

Paul
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
C

From novice to tech pro — start learning today.

Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.