I am opening a file for writing and changing it a bit. I have changed all uppercase characters to lowercase. I have also deleted all characters that are not alphabetic, but I can't delete apostrophes that occur after and before another alphabetic character (i.e. the word "there's" or "don't" would be a word with this condition). Here's my code thus far:

#include <stdio.h>
#include <string.h>
#include <ctype.h>

int fgetc(FILE *fp);

char *strcat(char *file1, const char *file2);

int isalpha(int c);

int main ()
{
    char file1[1000];//Array for first file
    char file2[1000];//Array for second file
    int character;
    char c;
    
    //Ask for file to load and store it into a variable        
    printf ("Enter a filename to load: ");
    scanf ("%s" , &file1);
    
    //Opening file to write
    FILE *fp;
    fp = fopen(file1, "w");
     
    printf ("\nFile successfully loaded!\n\n");
    
    //Reading each character of the file until EOF   
    while ((character = fgetc(fp)) != EOF)//read each char from file until end of file
    {   
        fscanf(fp, "%c ", c);
        if (isalpha(c)) //if c equals a alphabetic character, make it lower case
        {
            c = tolower(c);
        }
        else //c is not an alphabetic character
        {
            if (c != 0x27)//if c is not equal to single quote
            {
                c = 0x20;//make it equal to white space
            }
            else //c is a single quote
            {
                //How do I make the single quote be counted if there is an
                //alphabetic character to the left and to the right of it?
            }           
        }
        
    }
    
    //Changes the name of the existing file to have .tmp appended to it
    file2 = strcat(file1, ".tmp");
    
    //Displays an error if file couldn't be found    
    else 
    {
        printf ("Error, reading file!\n");
    }
    
    //Closes writeable file    
    fclose(fp);
    
    //Opens file that is appended with ".tmp" 
    fp = fopen (file2, "r");
    
    
    
    
    fclose(fp); 
    
system("PAUSE");
return 0;
}

I have checked everywhere for it, but to no avail. I thought about doing something like, if c-1 and c+1 are alphanumeric then it's fine or return 1, else return 0, but I'm certain I'm doing something wrong there. Any help is appreciated

Recommended Answers

All 11 Replies

What about 'till (for until) and nothin'? If those are also valid then your condition might easily be simply to check if the apostrophe is adjacent to a letter on either the left or the right.

You are testing each character as you read it, so you will need two extra variables: a boolean to tell you if the last valid character read was a letter or not: int isLastALetter; and the next character from the file char nextChar; You can pluck the next character from file and replace it thusly:

nextChar = fgetc(fp);  // get next char
// is nextChar a letter?
ungetc( nextChar, fp );  // "un-get" next char

Another option (what I would have done) is read each line into a string and then scan the string and do the c-1 and c+1 stuff you were thinking of.

Hope this helps.

else //c is a single quote
            {
                //How do I make the single quote be counted if there is an
                //alphabetic character to the left and to the right of it?
            }

Probably you want to set a flag that says "I have a quote".
And you have to remember the previous character so you can check it.
Then when you read the next character, you need to check everything and output the quote if necessary before outputting the next character.

What about 'till (for until) and nothin'? If those are also valid then your condition might easily be simply to check if the apostrophe is adjacent to a letter on either the left or the right.

I suppose the OP is trying to remove apostrophes from sentences as in 'Here's an important string' and leave alone any that is found in sentences like "Don't do nothin' 'till I figure things out". In which case, according to your algorithm logic, the apostrophes in both sentences are in the same boat.

scanf ("%s" , &file1);

Don't use scanf to obtain an string input from user. Instead use fgets as in fgets( file, sizeof file, stdin );

What about 'till (for until) and nothin'? If those are also valid then your condition might easily be simply to check if the apostrophe is adjacent to a letter on either the left or the right.

I suppose the OP is trying to remove apostrophes from sentences as in 'Here's an important string' and leave alone any that is found in sentences like "Don't do nothin' 'till I figure things out". In which case, according to your algorithm logic, the apostrophes in both sentences are in the same boat.

In my opinion, maybe we should help the OP do what they've been asked and not overly complicate the problem. There's always more stuff to consider, but at the learning stage, one level of complication should be enough to start with. :icon_wink:

Good point. He did say that there needed to be an alphabetic letter both to the left and to the right.

Both WaltP and I have a similar vein of thought. If you encounter an apostrophe character, check to see if the last character was an alphabetic character. If it was, either (set a flag for use in the next loop) or (use fgetc() and ungetc() ) to check to see if the next character was also an alphabetic. If it was, then save the apostrophe else get rid of it.

Good luck.

I'm going to work on it this evening and hopefully everything will compile and work. We'll see and thanks for the help guys.

I thought I responded to this... Darn...

... or (use fgetc() and ungetc() ) to check to see if the next character was also an alphabetic.

I don't recommend this. I dislike the idea of diddling with the input stream like that. To me, ungetc() is along the same line as goto and gets() -- they exist but you don't want to use them.

Yeah, actually I agree. I just didn't want to overload him with the overhead of remembering too much information at once per loop.

In fact, I still think the best solution is to load an entire line at once and play with the character string in memory. That way you don't have to remember anything from loop to loop and you can avoid weird stuff like ungetc().

>I dislike the idea of diddling with the input stream like that.
Any time you go back and forth in a track that should be one-way, it feels wrong. My problem is that ungetc is restricted enough to be frustrating and flexible enough to be virtually useless. However, there are times when put-back simplifies your logic enough to warrant using ungetc.

For example, try to write a portable parse_int function that reads directly from the stream but leaves the stream in an unchanged state on any conversion failure. The problem child is a sign followed by an illegal digit (ie. "-invalid"). You can use ungetc to portably put the 'i' back, but you aren't guaranteed a second consecutive put-back for the '-'.

Another example is error checking the last extracted character. One might assume that trying to put back a different character from the one extracted would cause ungetc to fail, but that's not required. This also limits the usefulness of ungetc.

For situations where ungetc would be useful, it's not portable. For situations where ungetc would be useful and portable, you can easily replace it with better logic.

>is along the same line as goto and gets()
I'm not sure I like you lumping goto with gets. goto is abusable, but there's nothing wrong with it. gets is completely unsafe and impossible to fix. There's quite a difference there.

>is along the same line as goto and gets()
I'm not sure I like you lumping goto with gets. goto is abusable, but there's nothing wrong with it. gets is completely unsafe and impossible to fix. There's quite a difference there.

I'm using a different criteria than dangerous. All three are bad coding techniques. One is dangerous. one is haphazard, one promotes disgusting code. All to be avoided.

>One is dangerous. one is haphazard, one promotes disgusting code. All to be avoided.
Other opinions exist.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.