논리는 다음과 같습니다.
read first integer from the text file into IntegerOne
if end-of-file on intInput.dat
display error message “Input file exists but has no values”
end program execution
텍스트 파일에는 값이 없거나 여러 값이있을 수 있습니다. 값이 없으면 오류 메시지를 표시하고 값이 여러 개인 경우 첫 번째 값만 읽고 값을 IntegerOne에 저장하고 싶습니다.
값 배열을 읽고 싶다면 다음과 같이 할 수 있습니다.
int main() {
int arr[30];
ifstream is("InputFile.txt");
int cnt = 0;
int x;
while (cnt < arr[30] && is >> x)
{
arr[cnt++] = x;
}
cout << "The integers are:" << "\n";
for (int i = 0; i < cnt; i++) {
cout << arr[i] << ' ';
}
is.close();
}
하지만 첫 번째 값만 읽는 방법을 정확히 모르겠습니다. "arr [30]"을 "arr [1]"로 변경해야합니까? 나중에 두 번째 값만 읽어야하고 (존재하는지 확인해야하므로) 주저하고 있습니다. 모든 의견을 주시면 감사하겠습니다!
당신은 코드로 순서대로 쉽게 할 수있는 몇 가지 일을하려고합니다. 주석에서 질문했듯이 IntegerOne
읽으려는 나머지 값이 배열로 읽으려는 나머지 값과 다른 값인지 또는 첫 번째 배열 요소 인지 여부는 명확하지 않습니다 . (다음에 나오는 값의 수를 지정하는 숫자를 포함하는 첫 번째 줄에 하나의 개별 정수가있는 것은 일반적인 형식입니다. 이것이 의미하는 바라고 가정합니다)
먼저 코드에 Magic-Numbers 또는 Hardcoded Filenames 를 사용하지 마십시오 . 배열을 선언하는 데 상수가 필요한 경우 상수 #define
또는 const int
값을 선언하십시오 . 파일 이름을 열려면 main()
인수를 사용합니다. int main (int argc, char **argv)
여기서 argc는 프로그램에 대한 첫 번째 인수로 열 파일 이름을 전달할 수있는 인수 (argument-vector에 있는 개별 문자열 수를 알려주 는 인수 개수입니다 ) ) 에서 입력으로 사용할 수 있습니다 . 이렇게하면 배열 크기를 변경할 수있는 편리한 위치가 하나 있고 다른 파일에서 읽기 위해 프로그램을 다시 컴파일 할 필요가 없습니다.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 (일반 이전 배열)를 모두 0으로 초기화하는 것이 유용합니다. )
배열의 요소에 대한 각 읽기의 유효성을 검사하는 동안 배열 경계를 보호하려면 카운터와 함께 정의한 상수를 사용하여 배열에 대한 공간보다 더 많은 정수를 쓰는 것을 방지 할 수 있습니다. 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';
}
여러 조건을 충족해야하는 코드를 작성할 때마다 해당 조건을 테스트하여 코드가 의도 한대로 작동하는지 확인하십시오.
사용 / 출력 예시
존재하지 않는 파일 :
$ ./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 개의 정수 값이있는 파일, 예 :
$ 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 개의 정수 값이있는 파일, 예 :
$ 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 개의 정수 값이있는 파일, 예 :
$ 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
( 참고 만 제 30 값은 어레이에 저장된다)
일반 오래된 배열 대신 STL 컨테이너 사용
평범한 오래된 배열을 처리하는 방법을 아는 것은 잘못된 것이 아니지만,이를 사용하는 레거시 C ++는 수십 년 동안 사용할 수 있지만 새 코드는 자동 메모리 관리, 추가 기능을 제공하는 표준 템플릿 라이브러리에서 제공하는 컨테이너를 사용해야합니다. 필요한 경우 추가 요소 등을 std::vector
사용하여 일반 이전 배열을 대체 할 수 있습니다. std :: vector의 각 멤버 함수에 대해 제공된 예제와 사용 방법을 잠시 살펴보십시오 . (그들은 정말로 삶을 훨씬 쉽게 만듭니다)
추가 질문이 있으면 알려주세요.
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다