Thread: Simple text file editor - Having some problems - C program

  1. #1
    Registered User
    Join Date
    May 2007
    Posts
    12

    Question Simple text file editor - Having some problems - C program

    Hi there,

    I'm having some problems with my latest programming attempt.

    ----------------------------------------------------------------------------------------------------------------
    So you know what I'm talking about, the question is:
    "Write a simple editor.

    The editor should first ask the user for the name of a file to edit.
    You may assume that the file already exists.

    Files will be restricted to exactly 23 lines of text, with no line longer than 70 characters.

    The editor should display the text in the file starting at the top of the screen.

    The 24'th line is used by the user to give commands to the editor. The prompt should be Command:

    The only commands that are available are:

    D number which will delete the line with that number. All lines after that one will move up one.
    The new 23rd line at the bottom will be empty.

    I number Will insert the text typed on the 25'th line before the line with that number
    All lines will move down one to accommodate the new line.
    The old 23'rd line will be discarded.

    R number Will replace, with the text typed on the 25'th line, the line with that number

    S Will save away the changes, by writing the text back to disk.

    Q Will quit the program

    eg

    Command: I 6
    this new line will be placed between line 5 and line 6 of the file

    After each command the screen should be cleared using the clrscr() function (in <conio.h>).
    The text should then be displayed again.

    Line numbers given by the user will, in true computer science style, start from 0 and go to 22.
    "
    ---------------------------------------------------------------------------------------------------------------


    The code I have written is as follows:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h> 
    
    char text[23][80];
    
    int main() {
    	int i, num; 
    	char c[80];
    	char temp[80];
    	FILE *g;
    	
    	printf("Enter file name:\n");
    	gets(c);  
    	g = fopen(c, "r"); 
    	
    	if(g == NULL) {
    		printf("Error: File did not open");
    		exit(0);
    	}
    	while(fgets (text[i], 80, g) !=NULL) {   
    		i++;
    		/* started getting the microsoft send/dontsend error here */
    	}
    	fclose(g);
    	system("cls");  
    	
    	for(i=0; i<23; i++) {
    		printf("%s", text[i]);
    	}
    	printf("Command:");
    	sscanf(temp, "%c %d", &c, &num); 
    	
    	while(temp != "Q") { 
    		if(temp == "R") {
    			fgets(text[num],80,stdin);
    		}
    		if(temp == "D") {
    			for(i=21; i<num; i++) {  /*"loop from num to 21"...should it be a while loop?? */
    				strcpy(text[i], text[i+1]);
    				/* "\n" (line 22) ??? */ 
    			}
    		}
    		if(temp == "I") {
    			for(i=22; i>num; i--) {
    				strcpy(text[i], text[i-1]);
    			}
    		}
    		if(temp == "S") {
    			for(i=0; i<23; i++) {
    				fprintf(g, text[i]);
    			}
    		}	
    	} 	     		
    }

    When I run the program in my GCC compiler, the program runs. Then it prompts me "Enter file name" (so far so good) Then when I enter in my file name (the one I am using is a text file called junk.txt - basicly a list of movies numbered 0 to 22) it comes up with the microsoft "send/don't send" error. then crashes. The program runs further if I delete everything in my junk.txt file... ie a blank txt file. If I do this, it will prompt me to enter a "Command:".

    When I debug my program, it stops me at this line, so I'm thinking, this might be the problem:
    Code:
    while(fgets (text[i], 80, g) !=NULL) {
    Any guidance on where to go from here would be appreciated.
    Thanks

  2. #2
    Deathray Engineer MacGyver's Avatar
    Join Date
    Mar 2007
    Posts
    3,210
    Yes, that line will be a problem. Where are you reading the data to? text[i], naturally, but what is index i at the time that line is run?

  3. #3
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    What happens when i = 24 and you try to access text[24]?
    Your classic memory access violation. Put test conditions to make sure i stays within bounds (or dynamically allocate more space when you need it).

    If commented what you should change below:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <conio.h>
    #include <string.h> 
    
    char text[23][80];  // you have 23 strings max, each of 80 chars max
    
    int main() {
    	int i, num; 
    	char c[80]; // you have 80 chars max
    	char temp[80]; // ditto
    	FILE *g;
    	
    	printf("Enter file name:\n");
    	gets(c);  // what happens if the user enters more than 79 chars? crash
                          // always use fgets here: fgets(c, sizeof(c), stdin)
    	g = fopen(c, "r"); 
    	
    	if(g == NULL) {
    		printf("Error: File did not open");
    		exit(0);
    	}
    	while(fgets (text[i], 80, g) !=NULL) {   //perform check to make sure 0 <= i < 80
    		i++; // use ++i, more effecient
    		/* started getting the microsoft send/dontsend error here */
    	}
    	fclose(g);
    	system("cls");  
    	
    	for(i=0; i<23; i++) { // ++i
    		printf("&#37;s", text[i]);
    	}
    	printf("Command:");
    	sscanf(temp, "%c %d", &c, &num);  //c, or &c[0], not &c (c is an array of chars, a.k.a pointer-to-char)
    	
    	while(temp != "Q") {  // NOT the way to compare strings, use strcmp()
    		if(temp == "R") { // ditto
    			fgets(text[num],80,stdin); //again, is num in bounds?
    		}
    		if(temp == "D") {// strcmp()
    			for(i=21; i<num; i++) {  /*"loop from num to 21"...should it be a while loop?? */
     //++i, for loop is fine, but you may want i=num; i < 21
    				strcpy(text[i], text[i+1]);
    				/* "\n" (line 22) ??? */ 
    			}
    		}
    		if(temp == "I") {// strcmp()
    			for(i=22; i>num; i--) { // --i
    				strcpy(text[i], text[i-1]);
    			}
    		}
    		if(temp == "S") {// strcmp()
    			for(i=0; i<23; i++) {// ++i
    				fprintf(g, text[i]);
    			}
    		}	
    	} 	     		
    }
    Since I noticed you are comparing your strings using equalities, maybe you want to read your intro book on C a bit more...
    Last edited by @nthony; 05-30-2007 at 12:29 AM.

  4. #4
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Quote Originally Posted by @nthony
    i++; // use ++i, more effecient
    Really?

  5. #5
    Registered Abuser
    Join Date
    Jun 2006
    Location
    Toronto
    Posts
    591
    I can't tell if that was sarcastic or not... but for the sake of humouring:
    i++ tells the compiler to "use" the value of i and then increment it
    ++i tells the compiler to increment i then "use" its value.
    The difference is, in the former, a temporary variable must be setup for i to hold the original value, then i is incremented and the original value is used in the expression. Whereas in the latter, i is incremented as is, and used in teh expression. Code wise, here is how "a = b + i++" would work:
    Code:
    i_temp is created and set to the value of i (name is really anonymous)
    i is incremented
    b + i_temp is evaluated and stored into a
    now with "a = b + ++i":
    Code:
    i is incremented
    b + i is evaluated and stored into a
    You save yourself extra memory and time. And these effects are double-fold when working with object oriented programs (i.e C++) as allocation of temp vars is much more involved. Especially if you're using i as an auto-incrementer in a for loop (n times faster/more effecient).
    I think there's more about it in the FAQs somewhere though.
    Last edited by laserlight; 05-30-2007 at 01:19 AM. Reason: Fixed a closing code bbcode tag.

  6. #6
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    nah, wasn't sarcastic. Thanks for that

    I've just always read there is 'no real difference' and your free to use any one as you wish.

  7. #7
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    I've just always read there is 'no real difference' and your free to use any one as you wish.
    With an optimising compiler, there should be no real difference in this case.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  8. #8
    Registered User
    Join Date
    May 2007
    Posts
    12
    Ok, thanks for the suggestions to fix my program.
    Initialising i=0 solved the send/don't send error.
    I was particularly silly not to use the strcpy function, so thanks for pointing that out to me! hehe

    Now when I run my program, I can input the file, get the text from junk.txt to list in the screen, then it will prompt me for a "command:" this is where my next problem is - It will not let me input anything, even though I have a sscanf there :S
    So I'm guessing I still have a problem with my sscanf line: (I have updated it, to how I think you meant it should look anthony)
    Code:
    sscanf(temp, "&#37;c %d", c, &num);
    What have I done wrong? How come it won't let me input anything even with this function in place?

    Thanks again!

  9. #9
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    sscanf() parses a string, you have to read the string from stdin yourself first however.

    You want:
    Code:
    fgets(temp, sizeof(temp), stdin);
    sscanf(temp, "&#37;c %d", c, &num);

  10. #10
    Registered User
    Join Date
    May 2007
    Posts
    12
    Quote Originally Posted by zacs7 View Post
    sscanf() parses a string, you have to read the string from stdin yourself first however.

    You want:
    Code:
    fgets(temp, sizeof(temp), stdin);
    sscanf(temp, "%c %d", c, &num);
    That did the trick as far as letting me input text into command. But after I input text, eg Command: "I 6" ... nothing happens, I hit enter and it just stops. According to my program, I should be able to input a line of text to insert after I enter the command, but it just stops.
    I thought my if statement for "Insert (I)" would pick this up:
    Code:
    if(strcmp(temp, "I") ==0) {
    			for(i=22; i>num; i--) {
    				strcpy(text[i], text[i-1]);

    I keep going through it, but I can't see what the heck I've done wrong.
    Thanks

  11. #11
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    no, a strcmp() of "I 6" and "I" won't work since they don't match. Consider comparing 'c' to I, such that
    Code:
    if(c == 'I')
    {
        /* blah */
    Also add some error checking to sscanf(), Hint: It returns the amount of 'parameters' it was able to read.

  12. #12
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Just remember it's case sensitive!,

    consider, (isupper from ctype.h)
    Code:
    if(toupper(c) == 'I')
    {
         /* blah */
    If you want to match 'i' and 'I'.

  13. #13
    Registered User
    Join Date
    May 2007
    Posts
    12
    Quote Originally Posted by zacs7 View Post
    no, a strcmp() of "I 6" and "I" won't work since they don't match. Consider comparing 'c' to I, such that
    Code:
    if(c == 'I')
    {
        /* blah */
    Also add some error checking to sscanf(), Hint: It returns the amount of 'parameters' it was able to read.

    In an earlier post, I was told to replace what I had in my original code with a strcmp, which I did, and now you're telling me not to use the strcmp - I'm getting conflicting responses here Anyways, when I tried using:
    Code:
    if(c == 'I')
    {
        /* blah */
    it returned errors: :50: error: ISO C++ forbids comparison between pointer and integer

    Can anyone help?

  14. #14
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    Code:
    char c;
    if(toupper(c) == 'I')
    {
         /* blah */
    My bad, c isn't needed as a char array anyway, unless your command is more than 1 character...

    Anyway, You should use strcmp() if you want to compare strings, BUT you "I\0" is certainly not equal to "I 6\0" where '6' is your parameter (num)...

    Consider, If you enter "I 6"
    Comparing "I" to "I 6" isn't going to work, the string isn't "I" it's "I <num>"

    Basically:
    Code:
    if(strcmp("I 6", "I") == 0) {
    And they don't match...

  15. #15
    Registered User
    Join Date
    May 2007
    Posts
    12
    I understand what you mean, about how they won't match, because of the number there, but how do I go about fixing that? I continue using strcmp? What do I add to it? Sorry, I'm very confused now

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. A development process
    By Noir in forum C Programming
    Replies: 37
    Last Post: 07-10-2011, 10:39 PM
  2. Formatting the contents of a text file
    By dagorsul in forum C++ Programming
    Replies: 2
    Last Post: 04-29-2008, 12:36 PM
  3. A bunch of Linker Errors...
    By Junior89 in forum Windows Programming
    Replies: 4
    Last Post: 01-06-2006, 02:59 PM
  4. Unknown Memory Leak in Init() Function
    By CodeHacker in forum Windows Programming
    Replies: 3
    Last Post: 07-09-2004, 09:54 AM
  5. problems reading from a text file
    By korbitz in forum C Programming
    Replies: 4
    Last Post: 12-21-2001, 06:11 PM