Вы работаете по правильному пути, но есть несколько вещей, к которым вы должны подходить по-разному, если вы хотите, чтобы все работало правильно. Если вы не получите ничего из этого ответа, узнайте, что вы не можете использовать любую функцию ввода или синтаксического анализа без проверки возврата (которая применяется практически к каждой используемой вами функции, кроме операции кода последующее не зависит от результата - как, например, просто печать значений) Кроме того, вы никогда не используете while (!feof(fpointer))
, например, смотрите: Почему while (! feof (file)) всегда неверно?
Теперь, как подойти к проблеме. Во-первых, если вам нужна константа для размера вашего массива, тогда #define
константа или используйте глобальный enum
. Например, для моих буферов sect
, inisect
, key
, inikey
и val
я бы определил SPLTC
, а затем для моего строчного буфера я определил MAXC
, например,
#define SPLTC 128 /* if you need a constant, #define one (or more) */
#define MAXC 256
В зависимости от того, требуется ли вам -ansi
или c89 / 90-совместимость, объявляйте переменные перед любыми операциями, например,
int main (int argc, char **argv) {
char buf[MAXC], sect[SPLTC], inisect[SPLTC], key[SPLTC], inikey[SPLTC], val[SPLTC];
FILE *fp = NULL;
Тогда первое, что вы сделаете, это проверьте , что в командной строке было предоставлено достаточное количество аргументов:
if (argc < 3) { /* validate 2 arguments provided */
fprintf (stderr,
"error: insufficient number of arguments\n"
"usage: %s file.ini section.key\n", argv[0]);
return 1;
}
Затем вы откроете свой файл и подтвердите , что это открыть для чтения:
/* open/validate file open for reading */
if ((fp = fopen (argv[1], "r")) == NULL) {
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
perror ("fopen");
return 1;
}
Затем разделите ваш section.key
аргумент argv[2]
на sect
и key
и подтвердите разделение:
/* split section.key into sect & key */
if (sscanf (argv[2], " %127[^.]. %127s", sect, key) != 2) {
fputs ("error: invalid section.key\n", stderr);
return 1;
}
Теперь введите ваше чтение l oop, чтобы найти свой раздел в файле (вы всегда управляете l oop с помощью return самой функции чтения):
while (fgets (buf, MAXC, fp)) { /* read each line */
if (buf[0] == '[') { /* is first char '[]'? */
if (sscanf (buf, " [%127[^]]", inisect) == 1) { /* parse section */
if (strcmp (sect, inisect) == 0) /* does it match 2nd arg? */
break; /* if so break loop */
}
}
}
Как проверить, что раздел найден? Вы можете оставить флаг-переменную, как вы сделали с right_section
, или ... подумать, где бы вы были в файле, если бы ваш раздел не был найден? Вы бы на EOF
. Так что теперь вы можете правильно проверить feof(fp)
, например,
if (feof (fp)) { /* if file stream at EOF, section not found */
fprintf (stderr, "error: EOF encountered before section '%s' found.\n",
sect);
return 1;
}
Если вы не вышли из-за того, что не нашли свой раздел (то есть вы достигли этой точки в коде), просто прочитайте каждую строку проверка разделение на inikey
и val
(если проверка не пройдена - вы прочитали все пары ключ / val в этом разделе без совпадения) Если вы найдете совпадение ключей во время чтения раздела успеха у вас есть inikey
и val
. Если вы заполнили l oop без совпадения, вы можете проверить, выдаете ли вы ошибку, и если вы наберете EOF
без совпадения, вы можете снова проверить feof(fp)
после l oop, например,
while (fgets (buf, MAXC, fp)) { /* continue reading lines */
/* parse key & val from line */
if (sscanf (buf, " %127s = %127s", inikey, val) != 2) { /* if not key & val */
fprintf (stderr, "error: end of section '%s' reached "
"with no matching key found.\n", sect);
return 1;
}
if (strcmp (key, inikey) == 0) { /* does key match? */
printf ("section : %s\n key : %s\n val : %s\n", sect, key, val);
break;
}
}
if (feof (fp)) { /* if file stream at EOF, key not found */
fprintf (stderr, "error: EOF encountered before key '%s' found.\n",
argv[3]);
return 1;
}
Вот и все. Если вы введете его целиком, у вас будет:
#include <stdio.h>
#include <string.h>
#define SPLTC 128 /* if you need a constant, #define one (or more) */
#define MAXC 256
int main (int argc, char **argv) {
char buf[MAXC], sect[SPLTC], inisect[SPLTC], key[SPLTC], inikey[SPLTC], val[SPLTC];
FILE *fp = NULL;
if (argc < 3) { /* validate 2 arguments provided */
fprintf (stderr,
"error: insufficient number of arguments\n"
"usage: %s file.ini section.key\n", argv[0]);
return 1;
}
/* open/validate file open for reading */
if ((fp = fopen (argv[1], "r")) == NULL) {
fprintf (stderr, "error: file open failed '%s'\n", argv[1]);
perror ("fopen");
return 1;
}
/* split section.key into sect & key */
if (sscanf (argv[2], " %127[^.]. %127s", sect, key) != 2) {
fputs ("error: invalid section.key\n", stderr);
return 1;
}
while (fgets (buf, MAXC, fp)) { /* read each line */
if (buf[0] == '[') { /* is first char '[]'? */
if (sscanf (buf, " [%127[^]]", inisect) == 1) { /* parse section */
if (strcmp (sect, inisect) == 0) /* does it match 2nd arg? */
break; /* if so break loop */
}
}
}
if (feof (fp)) { /* if file stream at EOF, section not found */
fprintf (stderr, "error: EOF encountered before section '%s' found.\n",
sect);
return 1;
}
while (fgets (buf, MAXC, fp)) { /* continue reading lines */
/* parse key & val from line */
if (sscanf (buf, " %127s = %127s", inikey, val) != 2) { /* if not key & val */
fprintf (stderr, "error: end of section '%s' reached "
"with no matching key found.\n", sect);
return 1;
}
if (strcmp (key, inikey) == 0) { /* does key match? */
printf ("section : %s\n key : %s\n val : %s\n", sect, key, val);
break;
}
}
if (feof (fp)) { /* if file stream at EOF, key not found */
fprintf (stderr, "error: EOF encountered before key '%s' found.\n",
argv[3]);
return 1;
}
}
Пример использования / вывода
Поиск допустимых комбинаций раздела / клавиш:
$ ./bin/readini dat/test.ini section2.key3
section : section2
key : key3
val : vaule3
$ /bin/readini dat/test.ini section2.key5
section : section2
key : key5
val : value5
$ ./bin/readini dat/test.ini section1.key2
section : section1
key : key2
val : value2
Попытки чтобы найти недопустимые сочетания клавиш / секций.
$ ./bin/readini dat/test.ini section1.key3
error: end of section 'section1' reached with no matching key found.
$ ./bin/readini dat/test.ini section2.key8
error: EOF encountered before key 'key8' found.
Просмотрите все и сообщите мне, если у вас есть дополнительные вопросы.