Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 589
  • Last Modified:

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.

0
sneak_186
Asked:
sneak_186
  • 4
  • 4
  • 2
2 Solutions
 
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
 
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
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
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

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 4
  • 4
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now