2011-12-22 2 views
0

내 운영자와 함께 몇 가지 문제가 >>C++ IStream을 연산자 >>

istream& operator>> (istream& is, Matrix& M) { 

    char first; 

    is>>first; 


    for(int i = 0;i<M.rows();i++) { 

     for(int j = 0;j<M.cols();j++) { 

      is>>M[i][j]; 
      cout<<M[i][j]; 

     } 

     is>>first; 

    } 

    return is; 
} 

나는 그들이에 의존하지 않도록 루프에 대한 변경을 원하기 때문에 나는 IStream을 연산자의 크기로 원하는 즉 전송 된 행렬은 크기 1의 행렬과 스트림 [1 2 3 4; 4 5 6 7; 1 2 3 4]을 전송 한 다음 크기 (3 * 4)의 새 행렬을 구성해야합니다. 할당 연산자를 사용하여 행렬 M에 할당 할 수 있습니다.

즉, 스트림의 형식은 "[ 1 2 3; 2 3 4; 4 5 6]"이고; 새로운 행을 의미합니다. 몇 개의 행과 열이 있는지 알고 싶습니다.

답변

0

문제는 스트림 추출 연산자가 수정할 수있는 이미 생성 된 개체를 필요로한다는 것입니다. 동적으로 크기를 조정할 수 있도록 행렬 클래스를 수정해야합니다.

0

"istream 연산자의 크기"를 결정할 수 없습니다. 스트림이기 때문에 첫 번째 행렬 요소를 읽을 때 아무도 마지막 요소가 이미 있음을 보장 할 수 없습니다. 처음에는 전체 문자열을 읽은 다음 구문 분석하고 입력 행렬의 크기에 대한 정보를 추출해야합니다. 그런 다음 stringstream을 통해이 문자열을 입력하여 코드를 사용할 수 있습니다. 물론 매트릭스의 크기를 동적으로 변경할 수 있어야합니다.

2

당신은이 같은 모든 행을 얻을 수 있습니다 : 다음 지금 당신이 rows의 각 행에 문자열이

vector<string> rows; 
string line; 

is.ignore(INT_MAX, '['); // ignores all characters until it passes a [ 

while (std::getline(is, line, ';')) 
    rows.push_back(line); // put each row in rows 

rows.back().erase(rows.back().find(']')); // erase the ending ] 

for (size_t i = 0; i < rows.size(); ++i) { 
    vector<int> items; 
    istringstream strstm(rows[i]); 

    std::copy(istream_iterator<int>(strstm), istream_iterator<int>(), back_inserter(items)); 

    // now items is full of the entries, resize the matrix to hold items.size() 
    // many items and insert each one into it, or whatever 
} 
+0

내가 얻을이 오류를 : 변수 '표준을 :: istringstream strstm은'초기화하지만 불완전한 유형 – shizzle

+0

을 가지고 @ shizzle :'#include '이 필요합니다. –

1

첫째, 물론, 당신은 일를 지정해야합니다 너보다 더 엄격한 비트 있습니다. "[ 11 12 13; 21 22; 31 32 33 ]"과 같이 무엇을해야합니까? 예 : 누락 된 값에 0.0을 삽입하거나 failbit을 설정 하시겠습니까?

그 외에도 std::vector을 사용하여 입력을 수집하면 비트가 더 쉽게됩니다. 예를 들어 다음과 같은 뭔가가 : 물론

template< typename T > 
char getRow(std::istream& source, std::vector<T>& dest) 
{ 
    dest.clear(); 
    char separator; 
    source >> separator; 
    while (source && separator != ';' && separator != ']') { 
     source.unget(); 
     T tmp; 
     source >> tmp; 
     if (source) { 
      dest.push_back(tmp); 
      source >> separator; 
     } 
    } 
    if (source && dest.empty()) { 
     dest.setstate(std::ios_base::failbit); 
    } 
    return source ? separator : '\0'; 
} 

template< typename T > 
char getFirstRow(std::istream& source, 
        std::vector<std::vector<T> >& dest) 
{ 
    dest.clear(); 
    std::vector<T> row; 
    char separator = getRow(source, row); 
    if (source) { 
     if (row.empty()) { 
      dest.setstate(std::ios_base::failbit); 
     } else { 
      dest.push_back(row); 
     } 
    } 
    return source ? separator : '\0'; 
} 

template< typename T > 
char getFollowingRow(std::istream& source, 
       std::vector<std::vector<T> >& dest) 
{ 
    std::vector<T> row; 
    char separator = getRow(source, row); 
    if (source) { 
     if (row.size() != dest.front().size()) { 
      dest.setstate(std::ios_base::failbit) ; 
     } else { 
      dest.push_back(row); 
     } 
    } 
    return source ? separator : '\0'; 
} 

template< typename T > 
std::istream& 
operator>>(std::istream& source, Matrix<T>& dest) 
{ 
    char separator; 
    source >> separator; 
    if (separator != '[') { 
     source.setstate(std::ios_base::failbit); 
    } else { 
     std::vector<std::vector<T> > results; 
     separator = getFirstRow(source, results); 
     while (separator == ';') { 
      separator = getFollowingRow(source, results); 
     } 
     if (separator != ']') { 
      source.setstate(std::ios_base::failbit); 
     } 
     if (source) { 
      dest.assign(results); 
     } 
    } 
    return source; 
} 

, 이것은 Matrix<T>::assign 기능은 치수를 설정 수 있어야합니다 것을 의미한다. 그리고 사용하려면 Matrix<T>에 이라는 기본 생성자가 필요합니다. 이는 실제로 Matrix<T>::assign까지 실제 구성을 "연기"합니다.

기타 : iostreams의 오류보고에 대해서는 의 제한적인 가능성으로 다소 제한되어 있습니다. 특히, 우리는 과 같은 입력과 "[11 12 13; 21"과 같은 것을 구별하고 싶습니다. (파일 조건의 진정한 끝 ). 그러나 "21" 뒤에 구분 기호를 읽으려는 시도는 eofbit으로 설정되며 이에 대한 조치는 없습니다. (사실, 우리는 경우 설정, std::ios_base::xalloc()를 사용하여, 를 새로운 상태 워드를 만들 수 있고, 경우에만, 시작시 '['의 읽기 eofbit 세트와 함께 실패합니다.하지만이 을 확인하는 매우이 Unstandard 방법을 필요로 클라이언트 코드의 오류로 인해 유지 관리 문제로 끝나는 무한 스트림 이 생성됩니다.)

마지막으로, 두 개의 메타 주석 : 이것이 복잡해 보인다면 ... 그렇습니다. 입력 은 다양한 오류가 있기 때문에 거의 항상 복잡합니다. 확인해야하는 조건은 입니다. 둘째, 각각의 개별 작업 (일종의)을 간단하게 유지하는 기능의 사용에 유의하십시오. 그것은 거의 항상 가난한 프로그램, 예를 들어, Matrix 같은 것들에 수학적 알고리즘을 적용하는 경우를 제외 기능의 중첩 루프를 가지고 의이 — 같은 일을 분해하지 초보자의 자주 실수. 이 경우 구문 분석은 수학적 알고리즘이 아니며 전체 처리에서 각 행의 처리를 분리하려고합니다. 이 경우 의 경우 첫 번째 행 의 처리를 오류 사례가 다르기 때문에 다른 행과 구분하는 것이 유용합니다. (첫 번째 행 나중에 행이 이전 행과 같은 길이 이 있어야합니다, 0보다 더 큰 길이를 가질 수 있습니다.)