C - как получить fscanf (), чтобы определить, является ли прочитанное только цифрами, а не символами - PullRequest
1 голос
/ 11 апреля 2010

Представьте, что у меня есть csv, и каждое значение является целым числом. поэтому первое значение - INTEGER 100.

Я хочу, чтобы fscanf () прочитал эту строку и либо сказал мне, что это ТОЛЬКО целое число, либо нет. Таким образом, он пройдет 100, но не будет 100t. То, что я пытался получить работу, это "% d", где запятая является разделителем моего CSV. так что вся функция

fscanf(fp, "%d,", &count)

К сожалению, это не дает сбоя на «100t», работает на «100» и «t». так что он просто не различает 100 и 100t (за всеми этими числами следуют запятые, конечно

Ответы [ 6 ]

7 голосов
/ 11 апреля 2010

Используйте strtol вместо.

5 голосов
/ 11 апреля 2010

fscanf на самом деле гораздо удобнее в использовании, чем подразумевали бы некоторые другие ответы, но большинство людей не очень хорошо это знают и не знают, как использовать все его возможности.

Полезные пункты: прежде всего, используйте возвращаемое значение из fscanf - он сообщает, сколько элементов было преобразовано. Во-вторых, преобразование «набор сканирования» может быть чрезвычайно полезным. Рассмотрим следующее (я использовал sscanf, чтобы не требовать внешнего файла, но fscanf отличается только источником, из которого он читает):

#include <stdio.h>

int main() { 
    int i;
    char *test[] = {
        "100,",    // should succeed.
        "100t,",   // should fail.
        "t"        // should also fail.
    };

    for (i=0; i<3; i++) {
        int count;
        char ch[2];
        if (2 == sscanf(test[i], "%d%[,]", &count, &ch))
            fprintf(stderr, "Conversion of \"%s\" succeeded.\n", test[i]);
        else
            fprintf(stderr, "Conversion of \"%s\" failed.\n", test[i]);
    }
    return 0;
}
5 голосов
/ 11 апреля 2010

Вы не.

Проблема в том, что fscanf() не очень полезен. Лучший способ справиться с этим - прочитать всю строку (или значительный фрагмент строки), а затем проанализировать строку. Вот пример:

int value;
char *extra;
char buffer[100];

// read in some data from the buffer
fgets(buffer, sizeof buffer, stdin);

// parse out a digit, if we can
i = strtol(buffer, &extra, 0);

На этом этапе вы можете проверить extra, чтобы увидеть, есть ли какие-либо дополнительные символы, что означает, что строка не была чисто числом, или если extra указывает на начало buffer, что означает, что не было номер для разбора.

1 голос
/ 11 апреля 2010

А как же

fscanf(fp, "%d%c", &count, &aChar)

если aChar! = ',' &&! = '\ N', то у вас нет только целого числа

0 голосов
/ 11 апреля 2010

Семейство функций scanf() не очень хорошо обнаруживает ошибки такого рода. Это не невозможно (см. Ответ Джерри Коффина, который работает, но IMO трудно обобщить), но IMO не настолько надежен. Лучше всего использовать fgets() для чтения ввода как текста, использовать токены с strtok() или аналогичным, а затем использовать strtol() или strtod() для преобразования токенов в числовые значения:

char buffer[LINE_SIZE];
while (fgets(buffer, sizeof buffer, inFile))
{
  char *token;
  char *newline = strchr(buffer, '\n');
  if (newline) 
    *newline = 0;
  token = strtok(buffer, ",");
  while (token)
  {
    char *chk;
    int value = (int) strtol(token, &chk, 10);
    if (!isspace(*chk) && *chk != 0)
    {
      printf("%s is not a valid integer\n", token);
    }
    else
    {
      printf("successfully read integer value %d\n", val);
    }
    token = strtok(NULL, ",");
  }
}

if (feof(inFile))
{
  printf("Hit end-of-file\n");
}
else
{
  printf("Error during read\n");
}
0 голосов
/ 11 апреля 2010

scanf-функции на входе, который не контролируется на 100%, может быть проблемой, чтобы избавиться от ошибок, лучше прочитать строку, используя fgets (), а затем использовать strtok (), чтобы разбить строку на токены, которые затем могут быть преобразованный.

использование atoi на одном токене, таком как "100t", даст 0, тогда как "100" даст 100

...