Как читать входной символ по символу/цифре по номеру в C?

У меня есть текстовый файл, который может содержать тысячи и тысячи чисел (0-9 --> одна цифра)/символов, например: 13612371029301276312357829031029352131265309182765236728726355263789120938728... (продолжается так)

В C, как мне прочитать их в массив, чтобы каждое число сохранялось отдельно? Я имею в виду после сохранения, массив[0]=1 массив[1]=3 массив[2]=6... и так далее [каждое число читается отдельно, это не большое число, а набор чисел, введенных без любые места]

Думаю, вы уже поняли мою мысль... Как мне их хранить, если в числах нет разделителей??


Вот переформулировка:

У меня есть файл с очень большим количеством цифр: ~ 10 ^ 8 цифр, которые не имеют разделителей:

файл будет выглядеть так: 127389472397413417398410274812371972398748263718238421389410923409234109329413413413241341... и так далее.

Я хотел бы прочитать файл последовательно - цифра за цифрой. Как мне это сделать в C??


person Lazer    schedule 06.09.2009    source источник
comment
Под числом, я думаю, вы имеете в виду цифру.   -  person Chris Lutz    schedule 06.09.2009
comment
люди, которые предлагают использовать строки, скажите, пожалуйста, как мне объявить строку, если размер файла (при условии, что он известен) составляет что-то вроде ~ 10 ^ 8 чисел?   -  person Lazer    schedule 06.09.2009
comment
Вы можете попробовать задать вопрос вроде «Как мне объявить массив размером больше, чем maxint?» или что-то вроде того. Вместо того, чтобы останавливаться на вещах, которые вы уже знаете, например, читая персонажей, задавайте конкретные вопросы о сложных вещах.   -  person Lance Roberts    schedule 06.09.2009


Ответы (8)


Изменить: вывести массив цифр (от (char)0 до char(9)).

#include <sys/stat.h>
#include <stdlib.h>
#include <stdio.h>

char* read_file_into_array(char* filename, size_t *array_size)
{
  char *array;
  struct stat st;
  FILE *f;
  size_t i;

  if (stat(filename, &st) != 0) {
    printf("Error reading %s\n", filename);
    return NULL;
  }
  array = malloc(st.st_size+1);
  if (!array) {
    printf("Error allocating memory\n");
    return NULL;
  }
  f = fopen(filename, "rb");
  if (!f) {
    printf("Error opening file\n");
    return NULL;
  }
  if (fread(array, 1, st.st_size, f) != st.st_size) {
    printf("Error reading file\n");
    return NULL;
  }
  fclose(f);
  /* Put numeric value into each field */
  for(i=0; i<st.st_size; i++)
    if (array[i] >= '0' && array[i] <= '9')
      array[i] = array[i]-'0';
    else /* end of digits */
      break;

  /* Provide size to caller */
  *array_size = i;

  return array;
}
person Martin v. Löwis    schedule 06.09.2009
comment
Обратите внимание, что stat не является переносимым. Я бы использовал seek() и tell() для переносимости. - person Chris Lutz; 06.09.2009
comment
Хороший. Я думаю, он хочет, чтобы массив содержал числовое значение прочитанного символа, а не значение ASCII. - person Liran Orevi; 06.09.2009
comment
могу я спросить, что вы здесь делали? спасибо за код... но мне нужно знать, что вы сделали! как именно эта штука будет работать? - person Lazer; 06.09.2009
comment
@Chris: ну, stat (3) определяется POSIX, поэтому он переносим на переносные системы :-) Он также работает в Windows, поэтому, вероятно, достаточно переносим для OP. - person Martin v. Löwis; 06.09.2009
comment
@Liran: хорошо, я также включил в него преобразование в цифровые значения. - person Martin v. Löwis; 06.09.2009
comment
Я не знал, что stat() работает в Windows. Я мог бы придраться и сказать, что stat(3) не существует, потому что моя справочная страница статистики находится в разделе 2, но на самом деле это не имеет значения. - person Chris Lutz; 06.09.2009
comment
eSKay: можно поконкретнее? Какая первая строка в этом коде вам непонятна? - person Martin v. Löwis; 06.09.2009
comment
Разве назначение array[i] = array[i]; не должно быть на самом деле array[i] = array[i] - '0';? - person Jonathan Leffler; 06.09.2009
comment
Если stat не работает, вы должны { perror(filename); вернуть НУЛЬ; } Сообщения об ошибках должны быть полезными, и они принадлежат stderr. - person William Pursell; 06.09.2009
comment
@Jonathan: спасибо, исправлено. @Уильям: -1. Это придирки, причем не по делу. - person Martin v. Löwis; 06.09.2009

Чтобы получить по одному символу, см. fgetc. Чтобы объединить множество цифр в одно огромное целое число, см., например, GMP. Чего именно вы ДЕЙСТВИТЕЛЬНО хотите достичь?!

person Alex Martelli    schedule 06.09.2009

Я предполагаю, что вам нужны не символы, а реальные значения, и в этом случае я бы сделал это так:

  1. Определите, сколько чисел вам нужно прочитать (если в файле все числа, это просто размер файла).
  2. Создайте массив символов такого размера.
  3. читать содержимое файла в массив символов.
  4. используйте цикл for для настройки всех значений их числового аналога (т.е. сделайте array[i] = array[i] - '0' в цикле)

Наслаждайтесь своим новым массивом со всеми числами, хранящимися в массиве в виде числовых значений.

person Cellfish    schedule 06.09.2009
comment
размер файла не всегда может быть известен :( - person Lazer; 06.09.2009
comment
и если размер известен, я знаю, что могу прочитать его как строку... но я не могу объявить строку такого размера (размер == огромный). Что ты посоветуешь? маллок? malloc терпит неудачу, если файл, скажем, ~ 10 ^ 8 чисел!! - person Lazer; 06.09.2009
comment
Если вам нужно все это в памяти, вам придется объявить массив такого размера. Если он слишком велик, чтобы поместиться в памяти, вам нужно выяснить, как вы можете обрабатывать данные по частям и загружать их фрагментами такого размера, как описано. - person jerryjvl; 06.09.2009
comment
Правильно. Как говорит Jerryjvl, вы должны решить, сколько чисел читать. Либо весь файл, либо его часть. Если бы вы более конкретно указали, чего хотите достичь, нам было бы легче дать вам совет. - person Cellfish; 06.09.2009

РЕДАКТИРОВАТЬ: Что вы имеете в виду, «какие функции я использую для таких больших входных данных?» Те же самые, которые вы используете для любых входов. Несколько ответов дали вам несколько очень хороших функций. fgetc() считывает символы по одному из дескриптора файла - общий прием для преобразования цифры (хранящейся как char) в числовое значение — x - '0', где x — символ цифры. malloc() может создать динамически выделяемый массив любого размера, который вы хотите для вам, но вам придется free(), когда вы Выполнено. Чтобы узнать размер файла, используйте stat() в большинстве Unix-подобных систем. , или для более переносимого подхода используйте fseek() и ftell(), чтобы найти его. Это все стандартные и довольно распространенные функции, и я не знаю, в чем ваша проблема, если вы знаете C и знаете эти функции.

person Chris Lutz    schedule 06.09.2009
comment
Боюсь, на этот раз ваши чувства неверны.. просто скажите мне, какие функции вы используете для таких больших входных данных? справедливо? а) это не домашнее задание. б) я никогда не говорил вам писать какой-либо код, вы говорите мне, какую функцию использовать, это не совсем заставляет мое приложение работать. Теперь вы можете помочь? - person Lazer; 06.09.2009

Просто прочитайте это как строку. Строки в C в основном представляют собой массивы символов.

person Aziz    schedule 06.09.2009
comment
Я знаю, что могу прочитать это как строку... но я не могу объявить строку такого размера (размер == огромный). Что ты посоветуешь? маллок? malloc терпит неудачу, если файл, скажем, ~ 10 ^ 8 чисел!! - person Lazer; 06.09.2009
comment
Вам нужно, чтобы все данные были в памяти одновременно? вы можете прочитать сегмент и обработать его, затем прочитать следующий сегмент .. и т. д. - person Aziz; 06.09.2009
comment
можете ли вы объяснить, какой тип обработки вы выполняете с этими данными, чтобы узнать, можно ли разделить их на более мелкие фрагменты? - person Aziz; 06.09.2009
comment
да, мне нужно это в памяти ... я не могу точно сказать ... как сделать некоторую статистику по данным - person Lazer; 06.09.2009

Если вы хотите получить значение первого числа, вы просто делаете

int firstNumber = myString[0] - '0';

Чтобы получить пятый, который вы делаете

int number5 = myString[4] - '0';

person toto    schedule 06.09.2009

Согласно этой публикации, вы можете выделить действительно большие объемы памяти с помощью malloc.

Но если файл действительно огромен и вы не можете выделить такую ​​большую память, вы можете просто использовать API сопоставления файлов, если используется ОС Windows.

С File Mapping вы можете просто сопоставить файл с памятью. После этого у вас просто есть указатель (например, char*), который указывает на данные файла.

person Isaac    schedule 06.09.2009

Чтобы создать строку большого размера, вам нужно создать список ссылок. Список ссылок — это набор структур, где последний раздел является указателем на другую структуру. Это позволит вам хранить более крупные строки, которые будут находиться как в памяти, так и на жестком диске, поэтому у вас не будет нехватки места из-за проблем с памятью.

person Paul    schedule 04.12.2011
comment
Связанный список (не список ссылок) является одним из возможных решений. Однако наличие одного узла для каждого символа потребовало бы тонны накладных расходов. Возможно, каждый узел может содержать N цифр. Однако связанный список не имеет особых свойств, связанных с памятью/пространством на жестком диске. Простое malloc() создание группы больших блоков также может привести к использованию виртуальной памяти, превышающей физическую память системы. - person Jonathon Reinhart; 05.11.2012