Thread: Replace vowels in file with *

  1. #1
    Registered User
    Join Date
    Oct 2010
    Posts
    11

    Replace vowels in file with *

    Hi,

    I have to write a program that replaces all vowels in a given file with *. Here's my code:

    Code:
    #include <stdio.h>
    #include <string.h>
    int main(){
    	FILE *fp = fopen("data.txt", "r+");;
    	char c;
    	while ((c = getc(fp)) != EOF){
        		if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'){
    			fp--;
    			putc('*', fp);
    		}
    	}
      	return 0;
    }
    But the program doesn't do anything. Anyone know why it doesn't do anything?

  2. #2
    Registered User claudiu's Avatar
    Join Date
    Feb 2010
    Location
    London, United Kingdom
    Posts
    2,094
    Because decreasing the file pointer is not going to do what you think it does and thus you can't just "replace" the characters in the file. You will have to read the whole file in and spit it out with the necessary changes.
    1. Get rid of gets(). Never ever ever use it again. Replace it with fgets() and use that instead.
    2. Get rid of void main and replace it with int main(void) and return 0 at the end of the function.
    3. Get rid of conio.h and other antiquated DOS crap headers.
    4. Don't cast the return value of malloc, even if you always always always make sure that stdlib.h is included.

  3. #3
    Registered User
    Join Date
    Sep 2008
    Location
    Toronto, Canada
    Posts
    1,834
    No you don't need to read the whoile file. Just use the position functions to move the file pointer.

  4. #4
    Registered User
    Join Date
    Sep 2007
    Posts
    1,012
    In this case, since a single character is being replaced by another single character, writing in-place is possible. Granted, fp-- is not the way to do it, but you can use fseek() to seek backward one character and write out the asterisk. After this, you must call fflush() before your next call to getc().

    Also, c should be an int, not a char. getc() returns an int so that EOF can be distinct from all character values.
    Last edited by cas; 10-26-2010 at 01:19 PM. Reason: Fixed unclear wording.

  5. #5
    Registered User
    Join Date
    Oct 2010
    Posts
    11
    I tried modifying the program in this way:

    Code:
    #include <stdio.h>
    #include <string.h>
    int main(){
    	FILE *fp = fopen("data.txt", "r+");;
    	char c;
            int l = 0;
    	while ((c = getc(fp)) != EOF){
                    if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'){
    			fseek(fp, l, SEEK_SET);
    			putc('*', fp);
    		}
                    l++;
    	}
      	return 0;
    }
    But it still doesn't completely work. It just replaces the first vowel with *.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by perrrson View Post
    Hi,

    I have to write a program that replaces all vowels in a given file with *. Here's my code:
    But the program doesn't do anything. Anyone know why it doesn't do anything?
    First don't mess with your file pointers... they are a pointer to a file "handle" not a position in the file. Second it would only write *s to the file, you also need to save the consonants.

    You might try...
    Code:
    FILE *fpr = fopen("data.txt", "r");
    FILE *fpw = fopen("data2.txt","w");
    char c;
    while ((c = getc(fpr)) != EOF)
         { if (strchr("aeiouyAEIOUY",c))
              putc('*', fpw);
           else
              putc(c,fpw); }
    fclose(fpr); 
    fclose(fpw);
    ... or something similar.
    Last edited by CommonTater; 10-26-2010 at 01:41 PM.

  7. #7
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    Arbitrary seeks with an offset only work predictably for files opened in binary mode. However, you can save the previous position prior to reading a character, test the character, then jump back and overwrite if it's a vowel:
    Code:
    #include <stdio.h>
    #include <ctype.h>
    
    int is_vowel(int ch)
    {
        ch = toupper(ch);
        return ch == 'A' || ch == 'E' || ch == 'I' || ch == 'O' || ch == 'U';
    }
    
    int main(void)
    {
        FILE *fp = fopen("data.txt", "r+");
    
        if (fp != NULL) {
            fpos_t pos;
            int ch;
    
            while (fgetpos(fp, &pos), (ch = getc(fp)) != EOF) {
                if (is_vowel(ch)) {
                    fsetpos(fp, &pos);
                    putc('*', fp);
                    fflush(fp);
                }
            }
    
            fclose(fp);
        }
    }
    My best code is written with the delete key.

  8. #8
    Registered User
    Join Date
    Oct 2010
    Posts
    11
    CommonTater, I need to make the changes in the same file.

  9. #9
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by perrrson View Post
    CommonTater, I need to make the changes in the same file.
    Ok... But, FWIW, I would call that a bad idea as it trashes the original file. If an error occurs you're screwed. In general it's smarter to write a second file, delete the first, rename the second...

    But if that's your assignment you will need a somewhat more complex solution like the one offered by Prelude.

  10. #10
    Registered User
    Join Date
    Oct 2010
    Posts
    11

    I did it

    I finally did it. This program works. The question is solved.

    Code:
    #include <stdio.h>
    #include <string.h>
    int main(){
    	FILE *fp = fopen("data.txt", "r+");;
    	char c;
            while ((c = getc(fp)) != EOF){
                    if (c == 'A' || c == 'E' || c == 'I' || c == 'O' || c == 'U' || c == 'a' || c == 'e' || c == 'i' || c == 'o' || c == 'u'){
    		        fseek(fp, -1, SEEK_CUR);
    			putc('*', fp);
    			fseek(fp, 1, SEEK_CUR);
    		}
           	}
      	return 0;
    }

  11. #11
    Code Goddess Prelude's Avatar
    Join Date
    Sep 2001
    Posts
    9,897
    >I would call that a bad idea as it trashes the original file.
    >In general it's smarter to write a second file, delete the first, rename the second...
    I hate to be the bearer of bad news, but your solution doesn't address your complaint. The original file will contain the new contents, either because the file was actively overwritten, or because it was deleted and replaced.

    >This program works. The question is solved.
    Except the part where your code is actually broken. Let's consider why:
    • getc returns int for a reason. EOF is a negative value, and if vanilla char is unsigned, you've got issues.
    • Your stream wasn't opened in binary mode, so arbitrary seeking isn't guaranteed to work.
    My best code is written with the delete key.

  12. #12
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by Prelude View Post
    >I would call that a bad idea as it trashes the original file.
    >In general it's smarter to write a second file, delete the first, rename the second...
    I hate to be the bearer of bad news, but your solution doesn't address your complaint. The original file will contain the new contents, either because the file was actively overwritten, or because it was deleted and replaced.
    It addresses the problem of an error mid-file... your software can bail without trashing the original file. It may not be much of an issue in this simple exercise but consider the risk when processing hundreds of megabytes of financial data... good habits are best formed early.

    In any case, I got no bone to pick, the OP solved the problem in a way that he seems happy with... neither your solution nor mine.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Newbie homework help
    By fossage in forum C Programming
    Replies: 3
    Last Post: 04-30-2009, 04:27 PM
  2. help with text input
    By Alphawaves in forum C Programming
    Replies: 8
    Last Post: 04-08-2007, 04:54 PM
  3. Replies: 3
    Last Post: 03-04-2005, 02:46 PM
  4. System
    By drdroid in forum C++ Programming
    Replies: 3
    Last Post: 06-28-2002, 10:12 PM
  5. Need a suggestion on a school project..
    By Screwz Luse in forum C Programming
    Replies: 5
    Last Post: 11-27-2001, 02:58 AM