Help with for loop

Hi.. I have this code which delete a specific line from a file and it's working but before asking the user to delete a line I choose to print the content of that file and to display for each line a number. I made a loop, but there is a small problem, that the loop prints one last number because the file ends with a new line.

Here the code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#include <stdio.h>
#include <windows.h>
#include <conio.h>
#include <string.h>
#define MAX 256

int main()
{
    int tmp, status;
    unsigned options;
    FILE *fptr1, *fptr2;
    char ch;
    char fname[MAX];
    char str[MAX], temp[] = "temp.txt";
    int lno, ctr = 0;

    do
    {
        system("cls");
        printf("\n\t\t\t* Delete a line from file *");
        printf("\n\n\n\tChoose an option");
        printf("\n\n\n   1.  Delete a line from a file");
        printf("\n   2.  Exit program");
        printf("\n\n   Select: ");
        status = scanf("%d", &options);

        while((tmp = getchar()) != EOF && tmp != '\n');
        if(!status)
        {
            printf("\n\n   Invalid option.. choose 1 or 2");
            Sleep(1500);
            options = 0;
            continue;
        }
        else if(options == 1)
        {
            system("cls");
            printf("\n\t\t\t* Delete a line from file *");
            printf("\n\n\n\n   Enter file name: ");

            scanf("%s", fname);
            fptr1 = fopen(fname, "r");
            printf("\n\n");

            while(1)
            {
                if(!fptr1)
                {
                    printf("\n\n   Could not open file");
                    Sleep(500);
                    printf("\n\n   %s", strerror(errno));
                    Sleep(1000);
                    system("cls");
                    break;
                }

                ch = getc(fptr1);
                for(int lNo = 0; ch != EOF;)
                {
                    ch = 0;
                    printf(" %i. ", ++lNo);
                    while(ch != EOF && ch != '\n')
                    {
                        printf("%c", ch);
                        ch = getc(fptr1);
                    }
                    printf("\n\n");
                }

                fptr2 = fopen(temp, "w");
                if(!fptr2)
                {
                    printf("\n\n   Unable to open a temporary file to write\n");
                    Sleep(2000);
                    fclose(fptr1);
                    break;
                }

                printf("\n\n   Enter the line you want to delete: ");
                scanf("%d", &lno);

                rewind(fptr1);
                ctr = 0;
                while(!feof(fptr1))
                {
                    strcpy(str, "\0");
                    fgets(str, MAX, fptr1);
                    if(!feof(fptr1))
                    {
                        ctr++;
                        if(ctr != lno)
                        {
                            fprintf(fptr2, "%s", str);
                        }
                    }
                }
                fclose(fptr1);
                fclose(fptr2);
                remove(fname);
                rename(temp, fname);

                printf("\n\n   The line was successfully deleted");
                printf("\n\n   The contend of the file now is:\n\n");

                fptr1 = fopen(fname, "r");
                printf("\n\n");
                for(lno = 0; fgets(fname, MAX, fptr1) != NULL;)
                {
                    printf(" %i.  %s\n", ++lno, fname);
                }

                Sleep(1000);
                printf("\n\n   Press any key to return menu..");
                getch();
                fclose(fptr1);
                break;
            }
        }
        else if(options == 2)
        {
            printf("\n\n\n\n\n\t\t\t\t   Exit");
            Sleep(1500);
            system("cls");
            break;
        }
        else
        {
            printf("\n\n   Invalid option.. choose 1 or 2");
            Sleep(1500);
        }
    }while(options != 2);

    return 0;
}
Last edited on
How do I tell that is a new line after it reach EOF ?

1
2
3
4
5
6
7
8
9
10
11
12
ch = getc(fptr1);
                for(int lNo = 0; ch != EOF;)
                {
                    ch = 0;
                    printf(" %i. ", ++lNo);
                    while(ch != EOF && ch != '\n')
                    {
                        printf("%c", ch);
                        ch = getc(fptr1);
                    }
                    printf("\n\n");
                }



Output:

1
2
3
4
5
6
7
 1. George Bush

 2. George Washington

 3. George Brawn

 4.


And that 4. would be the new line that is in at the end of the file..
I already tried this:

1
2
3
4
5
6
7
8
printf("\n\n   The contend of the file now is:\n\n");

                fptr1 = fopen(fname, "r");
                printf("\n\n");
                for(lno = 0; fgets(fname, MAX, fptr1) != NULL;)
                {
                    printf(" %i.  %s\n", ++lno, fname);
                }


which is already in the end of the code, but the problem is that if I put this for loop instead of the other one , it has a strange behavior, it print the content but after it past this and ask to delete a specific line, nothing is changing ,... I mean the line will not erase and the file will remain the same. I try to rewind the file pointer but I get the same problem... what is am I NOT doing.. ?
Last edited on
Some general observations.

1. When your function gets over 100+ lines long, it's really time to start thinking about breaking it down into sub-functions. If you can't see the { } braces of the whole function on-screen at the same time, that's a good hint to start thinking about what you're doing before you bloat it any further.

For example, you read the input file twice, but you do so in two different ways.
This should be a function for sure, which you can independently verify as working.

2. Sleep(1500); and system("cls");
No, just don't do it.
OK, don't do it yet.
While you're trying to get something to work, maintaining eye candy is just a massive waste of your time. It just saps away at your productivity and keeps you from focussing on the problem.

When you're done, it won't take more than a few minutes to add them back in the places that matter.
A simple way to print a file with line numbers:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main()
{
  FILE *src = fopen("temp.txt", "r");
  if (src == NULL)
  {
    perror("Unable to open file temp.txt: ");
    return 1;
  }
  char line[81] = {0};
  int count = 1;
  while (fgets(line, sizeof(line) - 1, src) != NULL)
  {
    if (line[0] != '\n');
      printf("%d. %s\n", count++, line);
  }
}

Output:
1. George Bush

2. George Washington

3. George Brawn
How do I tell that is a new line after it reach EOF ?


If you're reached EOF, it's too late to do much. You need to know at the point you display the line number whether you need to or not depending upon what has gone previously. Assuming there are no intentional blank lines in the file, then for reading the file one char at a time and not printing blank lines consider something like:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
#include <stdio.h>

void displayFile(FILE* fptr1)
{
	rewind(fptr1);

	for (int lNo = 0, ch = 0, out = 0; (ch = getc(fptr1)) != EOF; printf(out ? "\n\n" : "")) {
		if (ch != '\n')
			printf("%i. ", ++lNo);

		for (out = 0; ch != EOF && ch != '\n'; ch = getc(fptr1), out = 1)
			printf("%c", ch);
	}
}

int main()
{
	FILE* fptr1 = fopen("data1.txt", "r");

	if (fptr1 == NULL)
		return puts("Bad file") > 0;

	displayFile(fptr1);
}

Last edited on
Thank you guys for showing me different ways to print a file with line numbers ..but
I don't get it why the code isn't working if I change this:

1
2
3
4
5
6
7
8
9
10
11
12
ch = getc(fptr1);
for(int lNo = 0; ch != EOF;)
{
     ch = 0;
     printf(" %i. ", ++lNo);
     while(ch != EOF && ch != '\n')
            {
                 printf("%c", ch);
                 ch = getc(fptr1);
            }
     printf("\n\n");
}


with this:

1
2
3
4
5
6
fptr1 = fopen(fname, "r");
printf("\n\n");
for(lno = 0; fgets(fname, MAX, fptr1) != NULL;)
{
     printf(" %i.  %s\n", ++lno, fname);
}


at line 57.

what else I'm missing..?
rewind the fptr1?.... set the fpointer to the beginning of the file SEEK_SET, or why the program after printing the list with the numbers stop working ?

The program stops here:

1
2
printf("\n\n   Enter the line you want to delete: ");
scanf("%d", &lno);


I input the line number and then stops.
Last edited on
At line 57, fptr1 is already open - so why are you trying to open it again? Delete the superfluous second fopen().

Also I showed at http://www.cplusplus.com/forum/beginner/272766/ how to change a line in a file. Deleting a line is very similar - when you come to the line you want to delete, instead of writing the new line you just don't write the line to delete. You don't need those feof()!
Last edited on
I have a second code similar to the first one and shorter as I created 2 functions deleteLine() and printFile() and no more sleep() and system("cls"), as salem c observations.

Now..what is wrong with it ? First it prints the content and after asking to remove a line number the program goes ahead and says File contents after removing line n is.... No lines is printing, file remain unchanged and the delete-line.tmp is till there not removed..

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
#include <stdio.h>
#include <stdlib.h>

#define MAX 256
#define BUFFER_SIZE 1000

/* Function declarations */
void deleteLine(FILE *srcFile, FILE *tempFile, const int line);
void printFile(FILE *fptr, char path[MAX]);


int main()
{
    FILE *srcFile;
    FILE *tempFile;

    char path[MAX];
    int line;

    /* Input file path and line number */
    printf("Enter file path: ");
    scanf("%s", path);

    /* Try to open file */
    srcFile  = fopen(path, "r");
    tempFile = fopen("delete-line.tmp", "w");

    /* Exit if file not opened successfully */
    if (srcFile == NULL || tempFile == NULL)
    {
        printf("\nUnable to open file.\n");
        printf("Please check you have read/write previleges.\n");

        exit(EXIT_FAILURE);
    }

    printf("\nFile contents before removing line.\n\n");
    printFile(srcFile, path);

    // Move src file pointer to beginning
    rewind(srcFile);

    printf("\n\nEnter line number to remove: ");
    scanf("%d", &line);

    // Delete given line from file.
    deleteLine(srcFile, tempFile, line);


    /* Close all open files */
    fclose(srcFile);
    fclose(tempFile);


    /* Delete src file and rename temp file as src */
    remove(path);
    rename("delete-line.tmp", path);

    printf("\n\n\nFile contents after removing line %d.\n\n", line);

    // Open source file and print its contents
    srcFile = fopen(path, "r");
    printFile(srcFile, path);
    fclose(srcFile);

    return 0;
}
/**
 * Print contents of a file.
 */
void printFile(FILE *fptr, char path[MAX])
{
    printf("\n\n");
    for(int lno = 0; fgets(path, MAX, fptr) != NULL;)
    {
        printf(" %i.  %s\n", ++lno, path);
    }
}
/**
 * Function to delete a given line from file.
 */
void deleteLine(FILE *srcFile, FILE *tempFile, const int line)
{
    char buffer[BUFFER_SIZE];
    int count = 1;

    while ((fgets(buffer, BUFFER_SIZE, srcFile)) != NULL)
    {
        /* If current line is not the line user wanted to remove */
        if (line != count)
            fputs(buffer, tempFile);

        count++;
    }
}


I think something is not clearly in my brain... I can't figure out why this isn't working :\
Last edited on
Now I removed my function:

1
2
3
4
5
6
7
8
void printFile(FILE *fptr, char path[MAX])
{
    printf("\n\n");
    for(int lno = 0; fgets(path, MAX, fptr) != NULL;)
    {
        printf(" %i.  %s\n", ++lno, path);
    }
}


and changed with your function seeplus:

1
2
3
4
5
6
7
8
9
10
11
12
void displayFile(FILE* fptr1)
{
	rewind(fptr1);

	for (int lNo = 0, ch = 0, out = 0; (ch = getc(fptr1)) != EOF; printf(out ? "\n\n" : "")) {
		if (ch != '\n')
			printf("%i. ", ++lNo);

		for (out = 0; ch != EOF && ch != '\n'; ch = getc(fptr1), out = 1)
			printf("%c", ch);
	}
}


Now everything is working..

Now I can see that the problem is with the char path[MAX].
why is that ?
Last edited on
Why are you passing path to printFile? Why not use a local defined char array? Because printFile() uses path for a temporary buffer, when you come to use it again at lines 56, 57 and 62, path doesn't contain the name of the file, but whatever was last read by fgets()! The remove(), rename() and fopen() at those lines fail - but you aren't checking for success so you don't know they're failed! Always check that a function call has succeeded!

Okay seeplus that's a good explanation thank you once again. I'll go and make some changes..
Okay.. change that to a local char array, and it works perfectly..
Well don't know what to say... I guess I have to thank you again seeplus :)
that the loop prints one last number because the file ends with a new line.


1
2
3
4
5
6
7
8
void printFile(FILE *fptr, char path[MAX])
{
    printf("\n\n");
    for(int lno = 0; fgets(path, MAX, fptr) != NULL;)
    {
        printf(" %i.  %s\n", ++lno, path);
    }
}


Note that this will print the extra empty line with a line number - as per your original issue.

Consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <stdio.h>

void displayFile(FILE* fptr)
{
	rewind(fptr);

	for (int lNo = 0, ch = 0, out = 0; (ch = getc(fptr)) != EOF; printf(out ? "\n\n" : "")) {
		if (ch != '\n')
			printf(" %i. ", ++lNo);

		for (out = 0; ch != EOF && ch != '\n'; ch = getc(fptr), out = 1)
			printf("%c", ch);
	}
}


void printFile(FILE* fptr)
{
	char path[300];

	rewind(fptr);
	printf("\n\n");

	for (int lno = 0; fgets(path, sizeof(path), fptr) != NULL;)
		printf(" %i.  %s\n", ++lno, path);
}

int main()
{
	FILE* fptr1 = fopen("data1.txt", "r");

	if (fptr1 == NULL)
		return puts("Bad file") > 0;

	printFile(fptr1);
	displayFile(fptr1);
}


which for my test data displays:




1.  bnm bnm bnm bnm 124567890

2.  asdf rewq zxcv mnbv 1234567890

3.  dfgh dfgh dfgh dfgh 129876540

4.

1. bnm bnm bnm bnm 124567890

2. asdf rewq zxcv mnbv 1234567890

3. dfgh dfgh dfgh dfgh 129876540



To not display the 'blank line' when reading a line at a time, you can test that the first char read into the array is not a \n.

1
2
3
4
5
6
7
8
9
10
void printFile(FILE* fptr)
{
	char path[300];

	rewind(fptr);

	for (int lno = 0; fgets(path, sizeof(path), fptr) != NULL;)
		if (path[0] != '\n')
			printf(" %i.  %s\n", ++lno, path);
}


If you don't know the maximum length for a line, then using displayFile() does this without having to specify the maximum length of a line.
Last edited on
If you don't know the maximum length for a line, then using displayFile() does this without having to specify the maximum length of a line.


Ahaaaa.. got it now.

Thanks to you I learn something again...

I will soon post another problem that I have in my code to finish it. It works now entirely, but I wish it would work in the way I was think when I create it. Shortly in my program I already post how do I modify a file.. and you gave me the right response. Well it's working 100% and I like it, ..but , but, but I wish instead to substitute one single line input like this:

1
2
3
printf("\n\n\n   Update the old info with the following:");
printf("\n\n\n   New Info:     ");
fgets(data2, 255, stdin);


with this kinda input:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
printf("\n\n Update the old info:");
printf("\n\n\n\tName:       ");
scanf("%49s", info.name);
printf("\n\n\tLast name:  ");
scanf("%49s", info.lastname);
printf("\n\n\tCity:       ");
scanf("%49s", info.city);
printf("\n\n\tCountry:    ");
scanf("%49s", info.country);
printf("\n\n\tPhone:      ");
scanf("%19s", info.tel);
fprintf(fptr2, "%s %s %s %s %s\n",
	info.name, info.lastname, info.city, info.country, info.tel);
fgets(newLn, MAX, stdin);


But the results are not as I expect it to be... As I try to modify and to understand how to write the code, when I opened the text file the line I was choose to replace, was successfully but was placed in the first line, and sometimes the line I wanted to replace was a empty line and when I opened the records.txt was like this:

Output:
1
2
3
4
George Bush
John Wayne

Tracy Chapman


Line 3 was the one I wanted to replace instead I found an empty line.
Well before I post this issue.. I'll try to put my brain on work, and find the problem my self

Thanks seeplus...

Until next post as always Cheers.. :)
Consider that fgets() doesn't remove the \n from the input when it is read.

The fgets function reads a string from the input stream argument and stores it in str. fgets reads characters from the current stream position to and including the first newline character, to the end of the stream, or until the number of characters read is equal to numChars - 1, whichever comes first. The result stored in str is appended with a null character. The newline character, if read, is included in the string.
I'm working on it right now, well in that case I won' t use fgets() I'll use other functions..
For an alternative to fgets(), consider:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <stdio.h>

int fgetline(char* buff, int num, FILE* fs)
{
	int ch = 0, read = 0;

	for (; read < num - 1 && (ch = fgetc(fs)) != EOF && ch != '\n'; ++read)
		*buff++ = (char)ch;

	*buff = 0;

	while (ch != EOF && ch != '\n')
		ch = fgetc(fs);

	return ch == EOF && read == 0 ? EOF : read;
}


int main()
{
	FILE* fs = fopen("data1.txt", "r");

	if (fs == NULL) {
		puts("Cannot open file data1.txt\n");
		return 1;
	}

	char buff[6];

	while (fgetline(buff, sizeof(buff), fs) != EOF)
		puts(buff);
}


This 'overcomes' 3 limitations of fgets(). It doesn't include the terminating \n in the returned buffer, it returns the number of chars read (or EOF) so you don't need to do a strlen() to find this and if the line is longer then the specified number of chars, it will only return the number of chars in the buffer allowed but will read the file up to the terminating \n or EOF. This way, a whole line will be 'consumed' by the a call to fgetline() irrespective of the size of the buffer.

For a data file of:


123456
bnm
asdf rewq zxcv mnbv 1234567890
dfghi

cxz


it displays:


12345
bnm
asdf
dfghi

cxz


which is usually what is wanted :)
Last edited on
Registered users can post here. Sign in or register to post.