fgets
zwraca Ci str
(EDIT: str
było ze strony z opisem API, w Twoim przypadku chodzi o result
) czy coś innego?
No… fgets
zwraca to, co podane w API.
EDIT: nie jestem pewien jak się funkcje z libki standardowej zachowają przy jakiś bardziej egzotycznym kodowaniu plików. Jakie są dane wejściowe?
Hm... Plik inFp
ma ponad 6,5 miliona linijek, więc całego Ci nie podam… Linijka nr 61 wygląda tak:
<text xml:space="preserve">#REDIRECT [[Computer accessibility]]
Ale GDB, jak napisałem, mówi, że jest pusta (tak przynajmniej sądzę z tego, co wyświetlił).
I co na to wszystko valgrind?
Nie wiem, nie znam człowieka… Mówisz, że powinienem go użyć? Może się przydać? Wolałbym pozostać przy GDB jak długo się da…
Sprawa nr 2: na pewno nic Ci się nie dzieje z tym line
po drodze? Tzn. problem pojawia się nawet jeżeli zrobisz tak:
FILE *inFp = fopen(argv[1], "r");
for (int i = 0; i < linesCount; ++i)
{
char *line = silvGetLine(inFp);
free(line);
}
Tzn. wybacz, że tak dopytuję, ale obecność "..." wskazuje, że tam się po drodze wiele może dziać ;)
Dzieje się, są cztery wywołania funkcji, które pobierają line
jako argument. Jeśli to pomoże, a nie zaciemni obraz, to proszę – cały program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <math.h>
// There is the assumption that sizeof(char) == 1
int silvLinesCount(FILE *fp);
char *silvGetLine(FILE *fp);
char *silvConcat(char *s1, char *s2);
char *silvItos(int i);
char *silvSubstr(char *s, int from, int to);
bool silvStrEq(char *s1, char *s2);
int silvMin(int i1, int i2);
int main(int argc, char *argv[])
{
printf("debug: 'main' is running...\n");
if (argc < 3)
{
fprintf(stderr, "Error: main: there are less arguments than 2");
return -1;
}
// The input file
FILE *inFp = fopen(argv[1], "r");
// size_t n = 0;
// size_t readCharactersNumber;
bool isContent = NULL;
FILE *outFp = NULL;
int fileNumber = 0;
int linesCount = silvLinesCount(inFp);
// printf("debug: \tlinesCount == %d\n", linesCount);
// while ((readCharactersNumber = getline(&line, &n, inFp)) != -1)
for (int i = 0; i < linesCount; ++i)
{
char *line = silvGetLine(inFp);
char *filenameSuffix = NULL;
char *outFilePath = NULL;
char *expectedStart = " <text xml";
char *actualStart = silvSubstr(
line,
0,
silvMin(strlen(line), strlen(expectedStart)));
// printf("\tdebug: actualStart == %s\n", actualStart);
char *expectedEnd = "</text>";
char *actualEnd = strlen(line) > strlen(expectedEnd)
? silvSubstr(
line,
strlen(line) - strlen(expectedEnd),
strlen(line))
: line;
// printf("\tdebug: actualEnd == %s\n", actualEnd);
if (silvStrEq(actualStart, expectedStart))
{
isContent = true;
++fileNumber;
filenameSuffix = silvItos(fileNumber);
outFilePath = silvConcat(argv[2], filenameSuffix);
outFp = fopen(outFilePath, "a");
}
// if (isContent == true)
// {
// fputs(line, outFp);
// }
if (silvStrEq(actualEnd, expectedEnd))
{
isContent = false;
fclose(outFp);
}
free(actualStart);
free(actualEnd);
free(line);
free(filenameSuffix);
free(outFilePath);
// printf("\rLines read: %d, files created: %d...", i, fileNumber);
}
fclose(inFp);
return 0;
}
int silvLinesCount(FILE *fp)
{
printf("debug: 'silvLinesCount' is running...\n");
if (fp == NULL)
{
fprintf(stderr, "Error: silvLinesCount: fp == NULL");
}
char c;
int lineCount = 0;
while ((c = fgetc(fp)) != EOF)
{
if (c == '\n')
{
++lineCount;
}
}
fseek(fp, 0, SEEK_SET);
return lineCount;
}
// Needs a corresponding call for "free" by the user
char *silvGetLine(FILE *fp)
{
printf("debug: 'silvGetLine' is running...\n");
if (fp == NULL)
{
fprintf(stderr, "Error: silvGetLine: fp == NULL");
}
char c;
int lineSize = 0;
while ((c = getc(fp)) != EOF && c != '\n')
{
++lineSize;
}
char *result = malloc(lineSize + 1); // +1 for NULL character
fseek(fp, -lineSize, SEEK_CUR);
fgets(result, lineSize + 1, fp); // +1 because fgets reads "count - 1" bytes
return result;
}
// Needs a corresponding call for "free" by the user
char *silvConcat(char *s1, char *s2)
{
printf("debug: 'silvConcat' is running...\n");
if (s1 == NULL || s2 == NULL)
{
fprintf(stderr, "Error: silvConcat: either s1 == NULL or s2 == NULL");
}
char *result = malloc(strlen(s1) + strlen(s2) + 1); // +1 for NULL character
memcpy(result, s1, strlen(s1));
memcpy(result + strlen(s1), s2, strlen(s2));
memcpy(result + strlen(s1) + strlen(s2), "\0", 1); // +1 for NULL character
return result;
}
// Needs a corresponding call for "free" by the user
char *silvItos(int i)
{
printf("debug: 'silvItos' is running...\n");
if (i < 0)
{
fprintf(stderr, "Error: silvItos: i < 0");
}
int charactersNumber = (int)(floor(log10(i)) + 1); // +1 cause there's floor
char *result = malloc(charactersNumber + 1); // +1 for NULL character
sprintf(result, "%d", i);
if (result == NULL)
{
fprintf(
stderr,
"Warning: silvItos: something went wrong, result == NULL");
}
return result;
}
// Needs a corresponding call for "free" by the user
char *silvSubstr(char *s, int from, int to)
{
printf("debug: 'silvSubstr' is running...\n");
if (s == NULL)
{
fprintf(stderr, "Error: silvSubstr: s == NULL");
}
if (from > to)
{
fprintf(stderr, "Error: silvSubstr: from > to");
}
int substrSize = to - from;
char *result = malloc(substrSize + 1); // +1 for NULL character
memcpy(result, s + from, substrSize);
memcpy(result + substrSize, "\0", 1);
return result;
}
bool silvStrEq(char *s1, char *s2)
{
printf("debug: 'silvStrEq' is running...\n");
if (s1 == NULL || s2 == NULL)
{
fprintf(stderr, "Error: silvStrEq: either s1 == NULL or s2 == NULL");
}
if (strcmp(s1, s2) == 0)
{
return true;
}
else
{
return false;
}
}
int silvMin(int i1, int i2)
{
printf("debug: 'silvMin' is running...\n");
if (i1 <= i2)
{
return i1;
}
else
{
return i2;
}
}