2016-03-09 20 views
5

trong C++ id muốn đọc đầu vào vào một chuỗi kiểu c một ký tự cùng một lúc. làm thế nào để bạn làm điều này mà không cần đầu tiên tạo ra một mảng char với một kích thước thiết lập (bạn không biết có bao nhiêu ký tự người dùng sẽ nhập). Và kể từ khi bạn không thể thay đổi kích thước mảng, làm thế nào là điều này được thực hiện? Tôi đã suy nghĩ một cái gì đó dọc theo những dòng này, nhưng điều này không hoạt động.C++ đọc thành chuỗi c-style một char tại một thời điểm?

char words[1]; 
int count = 0; 

char c; 
while(cin.get(c)) 
{ 
    words[count] = c; 
    char temp[count+1]; 
    count++; 
    words = temp; 
    delete[] temp; 
} 
+4

từ mảng là 1 byte dài ...... chuỗi kiểu c phải có, ít nhất, 2 byte: 1 cho ký tự và 2 giây cho kết thúc 'NULL'. – LPs

+2

Chỉ 'xóa' những gì bạn' mới', và chỉ 'xóa []' những gì bạn 'mới []'. Vì bạn không tự động phân bổ 'temp', bạn không nên giải phóng nó. –

Trả lời

6

Vì bạn không thể sử dụng std::vector, tôi cho rằng bạn không thể sử dụng std::string một trong hai. Nếu bạn có thể sử dụng std::string, bạn có thể cung cấp giải pháp theo số the answer by @ilia.

Nếu không có điều đó, lựa chọn duy nhất của bạn là:

  1. Sử dụng một con trỏ trỏ đến cấp phát động bộ nhớ.
  2. Theo dõi kích thước của mảng được phân bổ. Nếu số lượng ký tự được lưu trữ vượt quá kích thước hiện tại, tăng kích thước mảng, cấp phát bộ nhớ mới, sao chép nội dung từ bộ nhớ cũ sang bộ nhớ mới, xóa bộ nhớ cũ, sử dụng bộ nhớ mới.
  3. Xóa bộ nhớ được cấp phát ở cuối hàm.

Đây là những gì tôi đề nghị:

#include <iostream> 

int main() 
{ 
    size_t currentSize = 10; 

    // Always make space for the terminating null character. 
    char* words = new char[currentSize+1]; 
    size_t count = 0; 

    char c; 
    while(std::cin.get(c)) 
    { 
     if (count == currentSize) 
     { 
     // Allocate memory to hold more data. 
     size_t newSize = currentSize*2; 
     char* temp = new char[newSize+1]; 

     // Copy the contents from the old location to the new location. 
     for (size_t i = 0; i < currentSize; ++i) 
     { 
      temp[i] = words[i]; 
     } 

     // Delete the old memory. 
     delete [] words; 

     // Use the new memory 
     words = temp; 
     currentSize = newSize; 
     } 

     words[count] = c; 
     count++; 
    } 

    // Terminate the string with a null character. 
    words[count] = '\0'; 

    std::cout << words << std::endl; 

    // Deallocate the memory. 
    delete [] words; 
} 
2

Bạn đã yêu cầu mảng kiểu C. Stack hoặc phân bổ động sẽ không phục vụ bạn trong trường hợp này. Bạn cần phải thay đổi số của số mảng trong mỗi lần bạn thêm phần tử mới mà không thể tự động. Bạn phải làm việc xung quanh và xóa và dự trữ các mảng mỗi khi một chae mới được đọc. Vì vậy, bạn phải lựa chọn:

  1. Sử dụng std::vector (mà đã được tạo ra cho mục đích này)
  2. Duplicate những gì bên trong std :: vector và viết nó cho mình trong mã của bạn (mà có vẻ khủng khiếp)

std::vector giải pháp:

std::vector<char> words; 
words.reserve(ESTIMATED_COUNT); // if you you do not the estimated count just delete this line 
char c; 
while(cin.get(c)){ 
    words.push_back(c); 
} 
+0

Nhưng anh ta yêu cầu chuỗi kiểu c, mặc dù tôi thích sử dụng 'std :: vector', và chúng ta có thể sử dụng' std :: vector 'là một bản trình bày khác của' char * ' – deepmax

+0

@deepmax Tôi vừa nhận thấy cảm ơn –

+0

sử dụng véc-tơ sẽ đẹp, nhưng trong lớp tôi đang dùng, chúng tôi không bao gồm véc-tơ để nó sẽ không được phép trên bất kỳ bài tập nào. –

1

bạn có hai cách, trước hết là sử dụng một mảng kích thước bằng không, sau mỗi đầu vào bạn xóa các mảng và alloca te một cái mới lớn hơn +1, sau đó lưu trữ đầu vào. Điều này sử dụng ít bộ nhớ hơn nhưng không hiệu quả. (Trong C, bạn có thể sử dụng realloc để cải thiện hiệu quả)

Thứ hai là sử dụng bộ đệm, ví dụ bạn lưu trữ đầu vào đọc trong mảng kích thước cố định và khi nó đầy, bạn nối thêm bộ đệm vào cuối mảng chính (bằng cách xóa và phân bổ lại).

Nhân tiện, bạn có thể sử dụng std::vector giúp tăng kích thước của chính nó một cách tự động và hiệu quả.

+0

Tùy chọn đầu tiên có thể hơi sắp xếp hợp lý bằng cách sử dụng 'realloc'. – Henrik

+0

@Henrik: Trong C có, nhưng trong C++ tôi không chắc liệu 'realloc' có được hỗ trợ hay không. – deepmax

+0

Có, từ 'cstdlib' – Henrik

2
#include <iostream> 
#include <string> 
using namespace std; 

int main() 
{ 
    string s1; 
    char c; 
    while (cin.get(c)) 
    { 
     if (c == '\n') 
      continue; 
     s1 += c; 
     cout << "s1 is: " << s1.c_str() << endl; //s1.c_str() returns c style string 
    } 
} 
+0

Nó không phải là một chuỗi c-style – deepmax

+0

s1.c_str() trả về chuỗi kiểu c – ilia

1

Nếu bạn đang thiết lập về việc sử dụng chuỗi c-style thì:

char* words; 
int count = 0; 

char c; 
while(cin.get(c)) 
{ 
    // Create a new array and store the value at the end. 
    char* temp = new char[++count]; 
    temp[count - 1] = c; 

    // Copy over the previous values. Notice the -1. 
    // You could also replace this FOR loop with a memcpy(). 
    for(int i = 0; i < count - 1; i++) 
     temp[i] = words[i]; 

    // Delete the data in the old memory location. 
    delete[] words; 

    // Point to the newly updated memory location. 
    words = temp; 
} 

tôi sẽ làm những gì Humam Helfawi đề xuất và sử dụng std::vector<char> kể từ khi bạn đang sử dụng C++, nó sẽ làm cho cuộc sống của bạn dễ dàng hơn. Việc thực hiện ở trên về cơ bản là phiên bản vector ít thanh lịch hơn. Nếu bạn không biết kích thước trước khi tay thì bạn sẽ phải thay đổi kích thước bộ nhớ.

0

Bạn cần phải phân bổ một bộ đệm chuỗi các kích thước tùy ý. Sau đó, nếu số ký tự tối đa đạt được khi phụ thêm, bạn cần phóng to bộ đệm bằng realloc.

Để tránh gọi realloc ở mỗi ký tự, không tối ưu, nên sử dụng chiến lược tăng trưởng, chẳng hạn như tăng gấp đôi kích thước ở mỗi phân bổ. Thậm chí còn có nhiều chiến lược tăng trưởng tinh chỉnh hơn, phụ thuộc vào nền tảng.

Sau đó, ở cuối, bạn có thể sử dụng realloc để cắt bộ đệm thành số byte chính xác được nối thêm, nếu cần.

Các vấn đề liên quan