Thread: Trouble writing characters to a file.

  1. #1
    Registered User
    Join Date
    Aug 2008
    Posts
    3

    Trouble writing characters to a file.

    I've been learning the C programming language for 2 days now (I'm fairly experienced with Javascript) and I have a problem with this code:

    Code:
    #include <stdio.h>
    FILE *file1;
    main() 
    {
    char thisChar;
    file1 = fopen("file1.txt","a");
    printf("Type a character to print to the file. Type a slash / to exit: ");
    labl:
    scanf("%c",&thisChar);
    if(thisChar=='/') {
     goto the_end; }
    else {
    fputc(thisChar,file1);
    }
    goto labl;
    
    the_end:
    }
    When I open file1.txt, every character which has been written to the file appears on a separate line. I want them to appear on a single line. What's going on? Any help much appreciated. I'm finding C very challenging, but I hope to eventually be fairly good at it.
    Chris

  2. #2
    The Richness... Richie T's Avatar
    Join Date
    Jan 2006
    Location
    Ireland
    Posts
    469
    When you type a character, you press enter and then type another, you press enter again and so on in this manner. The problem is that when you press enter, that is represented as a newline character - it gets left in the program's input buffer and the next time scanf is called, it gets read into thisChar.

    There are a number of solutions:

    1. Just call scanf() again after you write to the file to read in the extra newline character, or use getchar() immediately after the call to scanf(). I don't recommend using getchar() and scanf() together since it can cause confusion, but I think it would be clearer than using a second scanf().
    2. Use getchar() instead of scanf() altogether, and enter the characters all at once (instead of hitting enter after each). This is a good option if you want the program to work for an arbitrary number of characters entered.
    3. Read in the characters as a string using fgets(). The only problem with this approach is that it will require you to set a limit on the number of characters to be entered. See my signature for an example of using fgets(). Then to write to the file you would use fputs() or fprintf().

    Now onto the problems you didn't ask about:

    1. The main() function must return int - in fact you should probably use int main (void). This is more important than it seems and is a big issue for many people on the board. Learn it now, or you can expect to be told repeatedly to change. If you want an explanation, see the appropriate link in my signature.
    2. You should use a more consistant style of indentation to make your code more readable. This is very important when asking for help, as many people won't ready code if it is not indented consistantly. There are many styles to choose from, pick one and stick with it throughout an indivual project at the very least. Read this.
    3. The use of goto is not recommended. There is no reason why you can't achieve your goal using a while loop instead. Read this tutorial on loops. The problem with goto is that it tends to hide the operation of the code from others, and in a large piece of code, even the author can get confused. For and while loops are much more expressive ways to control program flow.
    No No's:
    fflush (stdin); gets (); void main ();


    Goodies:
    Example of fgets (); The FAQ, C/C++ Reference


    My Gear:
    OS - Windows XP
    IDE - MS Visual C++ 2008 Express Edition


    ASCII stupid question, get a stupid ANSI

  3. #3
    Registered User
    Join Date
    Oct 2001
    Posts
    2,129
    When you press enter, that goes into your scanf like the character does. Then it gets spit out to the file. To avoid this, add an if statement checking for \n.

    Indent your code and use loops instead of goto there.

    edit: beaten.

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Doesn't Javascript have loops?

    Two gotos in so few lines, not good.

    &#37;c reads newlines (which will be written to the file).
    So try typing in say
    hello world/


    *edit* 3rd Place!?
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  5. #5
    Registered User
    Join Date
    Aug 2008
    Posts
    3
    Thank you all very much
    I use Goto because I've also tried PureBasic before, which has a similiar function (Gosub)
    I'll try and improve my code so that several characters can be written to the file at once (which was my eventual aim after all).
    Chris

    ---
    EDIT:

    I've managed to come up with this code, which is much better. I learnt a fair bit and tried to apply it to this code.
    I'm not sure why I'm putting int in front of main(void), but if it's good practice, I'd rather do it.

    Code:
    #include <stdio.h> 
    
    FILE *file2;
    int main(void)
    {
      char thisChar[10];
      file2 = fopen("file2.txt","a");
      
        printf ("Please enter a line of text, max &#37;d characters\n", 8);
        fgets(thisChar, sizeof(thisChar)+1, stdin);
        fputs (thisChar,file2);
        printf ("%s has been written to the file.\n",thisChar);
    
    }
    Last edited by themusician31; 08-09-2008 at 01:41 PM.

  6. #6
    Hurry Slowly vart's Avatar
    Join Date
    Oct 2006
    Location
    Rishon LeZion, Israel
    Posts
    6,788
    sizeof(thisChar)+1
    bad idea to lie to fgets - you just asking for buffer overrun

    also no reason to make file2 global

    and as I remember - puts adds new line char at the end, while fgets does not removes one from the input

    so you will write new line char twice...

    You also are missing checks for return values of fopen and fgets before using its results
    All problems in computer science can be solved by another level of indirection,
    except for the problem of too many layers of indirection.
    – David J. Wheeler

  7. #7
    Registered User
    Join Date
    Aug 2008
    Posts
    3
    This is what my code looks like now:

    Code:
    #include <stdio.h> 
    
    
    int main()
    {
      FILE *file1;
      char thisChar[15];
      char *p;
      file1 = fopen("file1.txt","a");
      
      printf ("Please enter a line of text, max %d characters\n",sizeof(thisChar));
      
          fgets(thisChar, sizeof(thisChar)+1, stdin);
          if ((p = strchr(thisChar, '\n')) != NULL) {
          *p = '\0'; }
          fprintf(file1,"%s",thisChar);
          printf ("Written to the file.\n",thisChar);
    }
    BTW, is there a disadvantage to making file1 global?
    If I DO set the size of fgets to 'sizeof(thisChar)', it only allows 14 characters, whereas the size of thisChar when declared is 15. I already knew this would happen as I had read it on another site - it said it will allow one less than the value declared in the second parameter of fgets().
    Chris

  8. #8
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > BTW, is there a disadvantage to making file1 global?
    Too many global variables result in an unreadable, and unmaintainable mess.
    Like a lot of things in C, they're occasionally very useful, but over-use makes things worse rather than better.

    > If I DO set the size of fgets to 'sizeof(thisChar)', it only allows 14 characters, whereas the size of thisChar when declared is 15
    So make the array bigger.
    In particular, if you type in "hello", then what is in the buffer is "hello\n\0".
    Adjust the buffer size to allow for the \n\0 to be stored as well.

    Do NOT tell fgets() that it has more space than there is available, that's just plain wrong.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Replies: 8
    Last Post: 12-06-2008, 02:43 PM
  2. Post...
    By maxorator in forum C++ Programming
    Replies: 12
    Last Post: 10-11-2005, 08:39 AM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. simulate Grep command in Unix using C
    By laxmi in forum C Programming
    Replies: 6
    Last Post: 05-10-2002, 04:10 PM

Tags for this Thread