Вы пытаетесь сделать несколько вещей с вашим кодом, которые могут быть легко выполнены в последовательности. Как указано в комментарии, неясно, является ли ваша IntegerOne
, которую вы хотите прочитать, значением, которое отделено от оставшихся значений, которые вы хотите прочитать в вашем массиве, или это первый элемент массива. (наличие единственного целого числа в первой строке, содержащего число, которое задает число следующих значений, является общим форматом - который мы предполагаем, что вы имеете в виду)
Прежде всего, избегайте использования Волхвы c -Номера или Закодированные имена файлов в вашем коде. Если вам нужна константа для объявления вашего массива, то либо #define
константа, либо объявите значение const int
. Чтобы открыть имя файла, main()
принимает аргументы, int main (int argc, char **argv)
(где arg c - это счетчик аргументов , указывающий, сколько отдельных строк символов содержится в вашем аргумент-векторе ), который позволяет вам передать имя файла для открытия в качестве первого аргумента вашей программе (или вы можете принять его как ввод для stdin
). Таким образом, у вас есть одно удобное место для изменения размера вашего массива, и вам не нужно перекомпилировать вашу программу просто для чтения из другого файла.
Например, можно определить константу для вашего массива arr
как:
#include <iostream>
#include <iomanip>
#include <fstream>
#define MAXI 30 /* if you need a constant, #define one, or declare const int */
int main (int argc, char **argv) {
...
int arr[MAXI] = {0}; /* array of MAXI (30) integers */
или вместо использования #define
, в C ++ вы можете объявить и инициализировать const int
, например,
const int MAXI = 30;
С этим фоном вне пути, как прочитать первое целочисленное значение из файла в переменную с именем IntegerOne
? (Я думаю, что вы намеревались использовать x
в своем коде). Независимо от того, какое имя вы используете, подход один и тот же. Объявите переменную для хранения целочисленного значения, откройте ваш файл (проверьте, что он открыт для чтения), а затем прочитайте первое значение в вашей переменной (проверка того, что чтение выполнено), например,
int IntegerOne; /* separate variable for IntegerOne */
...
std::ifstream f (argv[1]); /* open file stream */
if (!f.good()) { /* validate file stream state good */
std::cerr << "error: file open failed.\n";
return 1;
}
if (!(f >> IntegerOne)) { /* read/validate 1st value */
std::cerr << "Input file exists but has no values.\n";
return 1;
}
Если у вас есть достигнув этой точки в вашей программе, вы успешно прочитали первое значение из файла в IntegerOne
, и вы можете просто вывести значение для подтверждения:
std::cout << "IntegerOne: " << IntegerOne << '\n'; /* output IntegerOne */
Следующая задача - прочитать значения до размер вашего массива. Вы объявляете свой массив, используя целочисленную константу MAXI
(макс. Число целых чисел), определенную выше:
int arr[MAXI] = {0}; /* array of MAXI (30) integers */
( примечание: полезно инициализировать ваши POA (простые старые массивы) ) до нуля, чтобы предотвратить случайное чтение из элемента, для которого еще не было установлено значение в течение al oop, что вызовет неопределенное поведение )
Для защиты границ массива при проверке При каждом чтении в элементе вашего массива вы можете просто использовать определенную вами константу вместе со счетчиком, чтобы предотвратить запись большего числа целых чисел, чем у вас есть место для вашего массива. Вы проверяете каждое чтение так же, как и с IntegerOne
выше. Соединяя оба условия, вы можете выполнить:
int cnt = 0, /* counter for array values */
...
/* read remaining integers into arr up to MAXI values */
while (cnt < MAXI && f >> arr[cnt])
cnt++;
Теперь вы прочитали свое первое значение в IntegerOne
и все остальные значения в файле в вашем массиве. Вы можете выводить их или использовать их так, как вам нравится, начиная с этого момента. В приведенном ниже примере просто выводятся прочитанные значения или указанные вами сообщения об ошибках (плюс дополнительное сообщение, если указанное имя файла не существует).
Если положить его в целом, вы можете сделать:
#include <iostream>
#include <iomanip>
#include <fstream>
#define MAXI 30 /* if you need a constant, #define one, or declare const int */
int main (int argc, char **argv) {
if (argc < 2) { /* validate at least 1 argument for filename */
std::cerr << "usage: " << argv[0] << " filename\n";
return 1;
}
int IntegerOne, /* separate variable for IntegerOne */
cnt = 0, /* counter for array values */
arr[MAXI] = {0}; /* array of MAXI (30) integers */
std::ifstream f (argv[1]); /* open file stream */
if (!f.good()) { /* validate file stream state good */
std::cerr << "error: file open failed.\n";
return 1;
}
if (!(f >> IntegerOne)) { /* read/validate 1st value */
std::cerr << "Input file exists but has no values.\n";
return 1;
}
std::cout << "IntegerOne: " << IntegerOne << '\n'; /* output IntegerOne */
/* read remaining integers into arr up to MAXI values */
while (cnt < MAXI && f >> arr[cnt])
cnt++;
/* output array, 10 values per line */
for (int i = 0; i < cnt; i++) {
if (i && i % 10 == 0)
std::cout << '\n';
std::cout << std::setw(5) << arr[i];
}
if (cnt) /* conditionally output final newline if array values printed */
std::cout << '\n';
}
Всякий раз, когда вы пишете код, который должен удовлетворять нескольким условиям, go тестируйте эти условия для проверки правильности работы вашего кода.
Пример использования / Вывод
Не существует файл:
$ ./bin/read1stvalue+array goldfish
error: file open failed.
Пустой файл:
$ ./bin/read1stvalue+array dat/empty.txt
Input file exists but has no values.
Файл с однозначным значением 321
:
$ ./bin/read1stvalue+array dat/oneint.txt
IntegerOne: 321
Файл с 10 целочисленными значениями после 1-го значения в файле, например,
$ cat dat/int_cnt+10_by-5.txt
10
702 344 138 77 294
27 67 978 727 301
Чтение вышеуказанного файла, вывод значений массива 10 на строку:
$ ./bin/read1stvalue+array dat/int_cnt+10_by-5.txt
IntegerOne: 10
702 344 138 77 294 27 67 978 727 301
Файл с 30 целочисленными значениями после 1-го значения в файле, например,
$ cat dat/int_cnt+30_by-5.txt
30
393 936 97 365 928
257 645 987 221 22
237 853 584 905 819
910 576 730 859 495
13 818 281 908 582
421 156 177 831 646
Чтение вышеуказанного файла, вывод значений массива 10 на строку:
$ ./bin/read1stvalue+array dat/int_cnt+30_by-5.txt
IntegerOne: 30
393 936 97 365 928 257 645 987 221 22
237 853 584 905 819 910 576 730 859 495
13 818 281 908 582 421 156 177 831 646
Файл с 50 целочисленными значениями после 1-го значения в файле, например,
$ cat dat/int_cnt+50_by-5.txt
50
302 697 190 743 391
709 699 824 839 976
817 246 695 833 918
2 712 422 737 326
706 170 394 720 903
798 291 683 682 971
70 216 668 260 960
59 969 891 883 40
867 700 519 795 766
437 29 710 91 767
Чтение выше файла , вывод значений массива 10 на строку:
$ ./bin/read1stvalue+array dat/int_cnt+50_by-5.txt
IntegerOne: 50
302 697 190 743 391 709 699 824 839 976
817 246 695 833 918 2 712 422 737 326
706 170 394 720 903 798 291 683 682 971
( note в массиве сохраняются только первые 30 значений)
Использовать контейнеры STL вместо простых старых массивов
Пока нет ничего плохого в том, чтобы знать, как обращаться с простыми старыми массивами - их использование на десятилетия унаследовано от C ++, новый код должен использовать контейнеры, предоставляемые стандартной библиотекой шаблонов, которые обеспечивают автоматическое управление памятью c, возможность чтобы добавить дополнительные элементы, если необходимо, et c .. std::vector
можно использовать для замены любого старого старого массива. Найдите минутку, чтобы посмотреть, как она используется, и примеры, предоставленные для каждой функции-члена по адресу std :: vector . (они действительно делают жизнь намного проще)
Дайте мне знать, если у вас есть дополнительные вопросы.