Я начал изучать C, переменные, функции, память и структуры были в порядке, но теперь я застрял на очень простых упражнениях с файлами.
Пример
У меня есть файл с именем и оценкой в каждой строке. Что-то вроде
asdfgh 1.5
asdfg h 2
a 0.5
Я научился читать каждую строку и могу написать программу, которая считывает каждую строку и выводит количество строк и т. д., но сейчас я хочу научиться изолировать числа, чтобы сравнивать их позже. Например, чтобы получить максимум или среднее значение, это не имеет значения. Что-то вроде
The max number is 2
Я использую fgets и sscanf, но на данный момент я очень запутался во всех учебниках, которые я уже смотрел.
Любой простой пример или учебник, которым можно поделиться?
Я читаю о strtok, он кажется полезным для того, что я хочу, но я не понимаю теорию, чтобы применить его для того, что я хочу, и видео, которые я смотрел, еще больше меня запутали.
Я могу открыть файл, прочитать файл и прочитать каждую строку до конца файла, но сохранение символов с числами в нем, чтобы позже сравнить их, - это та часть, которую я не получаю
#include <stdio.h>
#include <string.h>
char name[1000];
float number = 0;
int lines = 0;
char line[1000];
do {
fgets(line, 1000, stdin);
lines++
} while (line[0] != '\n');
return 0;
Если число всегда находится в последней позиции и за ним не следуют пробелы, вы можете использовать strrchr()
, чтобы найти его начало, а затем atof()
или strtod()
, чтобы преобразовать строку в число.
Ваш код неполный, плюс он на самом деле не использует sscanf. Было бы полезно иметь ваш фактический код и объяснение того, какие конкретные проблемы у вас возникают с ним.
Если число действительно может быть любым токеном в строке, используйте fgets
, чтобы получить строку. Затем зациклитесь на strtok(...," \t\n")
и посмотрите на первый символ токена. Если это цифра (например, isdigit
), то расшифруйте ее с помощью strtol
.
В сторону: пожалуйста, не превращайте этот вопрос в «зыбучий песок» в ответ на комментарии. Опубликуйте фактический код, который вы использовали, а не догадки. Я имел в виду while
, а не do...while
.
Спасибо всем за вашу помощь, я думаю, мне нужно больше изучить теорию, прежде чем начинать делать упражнения. Я подумал, что просмотр решения этого упражнения может помочь мне лучше понять все это, но я думаю, что здесь отсутствует теория, поскольку, по-видимому, даже этот небольшой код, который я написал, неверен. Я собираюсь изучить strrhr(), как вы предложили. Спасибо за ваши ответы :)
Вы можете использовать strcspn, чтобы найти первую цифру.
#include <string.h>
#include <stdio.h>
int main(void) {
char s[] = "hello world 123";
size_t n = strcspn(s, "1234567890");
printf("%s\n", &s[n]);
return 0;
}
Отпечатки:
123
Если у нас есть указатель на эту подстроку, мы можем использовать strtod, чтобы преобразовать ее в double
.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void) {
char s[] = "hello world 123";
size_t n = strcspn(s, "1234567890");
printf("%lf\n", strtod(&s[n], NULL));
return 0;
}
Отпечатки:
123
Конечно, вам, вероятно, также следует проверить ошибки, чтобы определить, была ли найдена числовая цифра.
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
int main(void) {
char s[] = "hello world";
size_t n = strcspn(s, "1234567890");
if (!s[n]) {
printf("Numeric digit not found.\n");
return 1;
}
printf("%lf\n", strtod(&s[n], NULL));
return 0;
}
Спасибо. Я собираюсь изучить это, так как я не знал о strtol() или strtod(), но это простой и понятный код. Я думаю, что могу «поиграть» с этим, чтобы узнать больше о файлах. Спасибо :)
Крис, рассмотрите такие входные данные, как ".123"
, "-456"
. Этот ответ сообщает 123
и 456
.
Я согласен. Ваше решение более надежное. Тем не менее, я думаю, что ответ, который я дал, может иметь некоторую ценность, поэтому не буду его удалять. УФ для вас, однако.
Числа могут начинаться с '0'-'9'
, '+'
, '-'
, '.'
, 'I'
, 'i'
(бесконечность), 'N'
, 'n'
(NAN), пробелов и других значений, специфичных для реализации, таких как ','
. Возможно, даже ` в будущем. *1
Вместо того, чтобы искать только первый числовой символ, используйте strtod()
несколько раз и позвольте этой функции проверить текст как число.
const char *s = line;
char *endptr; // Location to store end of conversion.
bool found = false;
double d;
for (; *s; s++) {
errno = 0;
d = strtod(s, &endptr);
if (s == endptr) continue; // No conversion.
// If following is not a space nor a null character ...
if (!isspace((unsigned char) *endptr) && *endptr) continue;
// You may want to test for range or skip this.
if (errno == ERANGE) continue;
found = true;
break;
}
if (found) {
printf("Found %g at <%.*s>\n", d, (int)(endptr - s), s);
}
*1 В следующей версии языка C могут быть добавлены новые функции, такие как разделитель цифр ', двоичный ввод и т. д. Используя стандартные функции для проверки, ваш код готов к будущему — это сокращает объем обслуживания и поддерживает актуальность кода.
Пожалуйста, используйте идиоматику
while(fgets(line, 1000, stdin) != NULL)
. Тест наline[0]
может никогда не быть'\n'
.