Read lines in text file from a certain line 'C'

Hello again.. I have one question, How can I read lines from a text file from a certain position? What I mean is if I have a text file like this:

"RuneWords.txt" (just an example)

+50 to Life
25% Chance of Crushing Blow
7% Mana Stolen Per Hit
+2 to Light Radius

40% Better Chance of Getting Magic Items
All Resistances +20
+30 to All Stats
-5 to Defence
4 Mana After each Kill

20% Chance of Open wounds
+100 to Life
+30% Enhance Defence
10% Chance to Cast Level 15 Iron Maide(Skill from Necromancer)

.
..
... etc



and in my program let's say I have something like this:

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

typedef struct
{
   CHAR RuneWords[30];
}runewords;

runewords list[] =
{
   {"Death"},
   {"Pride"},
   {"Ice"},
   {"Honor"},
   .,
   ..,
   ...,
};


So.. when I put all these elements in a List View and select one of them let's say "Pride" which is the second one, I want to list the properties from the text file "RuneWords.txt" from line 6 which is this:

"RuneWords.txt" (just an example)

+50 to Life
25% Chance of Crushing Blow
7% Mana Stolen Per Hit
+2 to Light Radius

40% Better Chance of Getting Magic Items // <-Start read from here..
All Resistances +20
+30 to All Stats
-5 to Defence
4 Mana After each Kill // <- End read here..


20% Chance of Open wounds
+100 to Life
+30% Enhance Defence
10% Chance to Cast Level 15 Iron Maide(Skill from Necromancer)

.
..
... etc



How do I do that ?!
Last edited on
Maybe something like this:

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
#include <stdio.h>
#include <stdlib.h>

int main()
{
    FILE *fin = fopen("RuneWords.txt", "r");
    if (!fin)
    {
        printf("Cannot open input file\n");
        exit(EXIT_FAILURE);
    }

    int n = 0;
    printf("Enter n: ");
    scanf("%d", &n);

    char line[500];
    for (int i = 0; i < n; ++i)
        while (fgets(line, sizeof line, fin))
            if (line[0] == '\n')
                break;

    while (fgets(line, sizeof line, fin))
    {
        if (line[0] == '\n')
            break;
        printf("%s", line);
    }

    fclose(fin);

    return 0;
}

Yes.. the code make sense, but how can I tell the program I just choose
Pride
from the list and he goes to line 6? DO I have to put some flags, or put numbers after each new line so it can read from text that what I choose correspond to that number and read down until it seen a new line ?
"Pride" is element number 1 in the array.
So in my code, n would be 1.
Ah.. oka the signal arrived now.. :) Cool.. ty dutch, I understand the logic now.. thanks alot !!!
Still can I ask you just one more question .?

I'm trying to update your code in to a win32 API program, saying this means that I want to print the lines I just show you below in to an edit read only control, with the help of the list box.

I have the list box, and the data to show, which is now functional... well in other words I just want to print from the text file when I choose an item from the list box.

what I have until now is this:

RuneWords.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#define IDC_RUNEWORDS   1000
#define ARRAYSIZE(sel) (sizeof(sel) / sizeof(sel[0]))

typedef struct
{
    CHAR RuneWord[30];
}RuneWords;

RuneWords rwList[] =
{
    {TEXT("Leaf")},
    {TEXT("Lore")},
    {TEXT("Nadir")},
    //..there are too many let's say just 3 for now
};


in the main cpp
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
#include <windows.h>
#include <stdio.h>
#include "RuneWords.h"

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch(msg)
        {
            case WM_CREATE:
		    {
		        runeWordsDesc = CreateWindowA("edit", NULL,
                                     WS_VISIBLE | WS_CHILD | ES_READONLY |
                                     WS_VSCROLL | ES_MULTILINE | ES_AUTOVSCROLL,
                                     565, 370, 195, 226, hwnd, NULL, NULL, NULL);

                        runeWordsList = CreateWindowA("listbox", NULL,
                                     WS_VISIBLE | WS_CHILD | LBS_STANDARD | LBS_NOTIFY,
                                     40, 370, 180, 230, hwnd, (HMENU)IDC_RUNEWORDS, NULL, NULL);
                        runeWordsList = GetDlgItem(hwnd, IDC_RUNEWORDS);

                        for(unsigned int i = 0; i < ARRAYSIZE(rwList); i++)
                        {
                            int pos = (int)SendMessage(runeWordsList, LB_ADDSTRING, 0, (LPARAM)rwList[i].RuneWord);

                            SendMessage(runeWordsList, LB_SETITEMDATA, pos, (LPARAM)i);
                        }
                        SetFocus(runeWordsList);
                  }break;

            case WM_COMMAND:
            {
                switch(LOWORD(wParam))
		{
			case IDC_RUNEWORDS:
			{
				switch(HIWORD(wParam))
				{
					case LBN_SELCHANGE:
					{
						runeWordsList = GetDlgItem(hwnd, IDC_RUNEWORDS);

						int lbitem = (int)SendMessage(runeWordsList, LB_GETCURSEL, 0, 0);
						int i = (int)SendMessage(runeWordsList, LB_GETITEMDATA, lbitem, 0);

						FILE *file = NULL;
						char buffer[1000] = "RuneWords.txt";

						file = fopen(Buffer, "r");
						if (!file)
						{
							printf("Cannot open input file\n");
							exit(EXIT_FAILURE);
						}

						for (int j = 0; j < i; ++j)
						{
							while(fgets(buffer, sizeof buffer, file) != NULL)
							{
								if(buffer[0] == '\n')
								{
									break;
								}
							}
						}

						while (fgets(buffer, sizeof buffer, file) != NULL)
						{
							if (buffer[0] == '\n')
							{
								break;
							}

							SendMessage(runeWordsDesc, WM_SETTEXT, 0, (LPARAM)buffer);
						}

						fclose(file);
					}
				}
			}break;
		}
		return(0);
            }break;

            case WM_CLOSE:
            {
                DestroyWindow(hwnd);
            }break;

            case WM_DESTROY:
            {
                PostQuitMessage(0);
            }break;

            default:
                return(DefWindowProcA(hwnd, msg, wParam, lParam));
    }

    return (0);
}


I only get the last line from what should it be..
Last edited on
The WM_SETTEXT message doesn't append to the text in the text box.
It sets it to the value you pass in the LPARAM.
So you need to build up that value and set it once, after the loop, something like:

1
2
3
4
5
6
7
8
9
10
						char text[1000] = {0};
						while (fgets(buffer, sizeof buffer, file) != NULL)
						{
							if (buffer[0] == '\n')
							{
								break;
							}
							strncat(text, buffer, sizeof text);
						}
						SendMessage(runeWordsDesc, WM_SETTEXT, 0, (LPARAM)text);

BTW, I wouldn't waste 1000 bytes on the file name, just do this:

 
FILE *file = fopen("RuneWords.txt", "r");

Last edited on
Ohh.. I understand , working very nice.. I was close .. I didn't think about strncat() function, I was just thinking to strcpy() at some point, but as always I was not smart enough to remember this one. :|
And about the waste of bytes you mention, for a text file with.. let's say 500 lines cose I think this will be the limit of what i have to write in file, how big has to be the buffer to cover ?

EDIT: However is weird how the text is show in the edit window.. seems like is writing it without the new line,.. I mean is writing all on the same line @@

However this made me happy.. ty so much
dutch
I was going crazy reading the code over and over.. Cheers !! :)
Last edited on
I just meant that there's no reason to waste bytes for the filename.

For text It's reasonable to use 1000 bytes.

The buffer only needs to hold a single line, so it may be big enough at 100.
It just needs to be larger than the largest line you expect.

Ahhh ok understood , I will write this, seems I wasn't present to this lesson.. :|

BTW I just EDIT my post, how do i add the new line, because the fgets is reading it but when output doesn't seems to put it back.
Does strncat appends the strings without new line ?
The newlines are probably in the string, but they may not work in the text box.
It's possible that instead of '\n' you need '\r' '\n' (which is a Windows thing).
I don't know since I'm not a windows kinda guy, but try replacing the strncat with:

1
2
3
4
strncat(text, buffer, sizeof text);
char *p = strchr(text, '\n');
if (p) *p = '\0'; // remove the newline
strncat(text, "\r\n", sizeof text); // replace it with \r\n 

Okay dutch I solved I just added this line after the first
strncat() Function
:

 
strncat(text, "\r\n", sizeof(text));


Works perfectly.. :)

Thank you so much man..
Registered users can post here. Sign in or register to post.