2009-04-10 23 views
10

Tôi đang học C từ k & r làm ngôn ngữ đầu tiên và tôi chỉ muốn hỏi, nếu bạn nghĩ rằng bài tập này đã được giải quyết đúng cách, tôi biết rằng nó có thể không hoàn chỉnh như bạn muốn thích, nhưng tôi muốn xem, vì vậy tôi biết tôi đang học C đúng.K & R Chương 1 - Bài tập 22 giải pháp, bạn nghĩ sao?

Cảm ơn

/* Exercise 1-22. Write a program to "fold" long input lines into two or 
* more shorter lines, after the last non-blank character that occurs 
* before then n-th column of input. Make sure your program does something 
* intelligent with very long lines, and if there are no blanks or tabs 
* before the specified column. 
* 
* ~svr 
* 
* [NOTE: Unfinished, but functional in a generic capacity] 
* Todo: 
* Handling of spaceless lines 
* Handling of lines consisting entirely of whitespace 
*/ 

#include <stdio.h> 
#define FOLD 25 
#define MAX 200 
#define NEWLINE '\n' 
#define BLANK ' ' 
#define DELIM 5 
#define TAB '\t' 

int 
main(void) 
{ 
    int line = 0, 
     space = 0, 
     newls = 0, 
      i = 0, 
      c = 0, 
      j = 0; 

    char array[MAX] = {0}; 

    while((c = getchar()) != EOF) { 
     ++line; 
     if(c == NEWLINE) 
      ++newls; 
     if((FOLD - line) < DELIM) { 
      if(c == BLANK) { 
       if(newls > 0) { 
        c = BLANK; 
        newls = 0; 
       } 
       else 
        c = NEWLINE; 
       line = 0; 
      } 
     } 
     array[i++] = c; 
    } 
    for(line = 0; line < i; line++) { 
     if(array[0] == NEWLINE) 
      ; 
     else 
      printf("%c", array[line]); 
    } 
    return 0; 
} 
+0

Có lẽ bạn nên giải quyết bài tập về nhà của mình ssignments? –

+1

@Phil: tôi nghĩ rằng anh ấy đã làm ... điều đó hoặc khối mã khổng lồ đã được nôi. – Shog9

+0

@Phil, có nhiều tiền lệ cho những người hỏi câu hỏi về bài tập về nhà miễn là họ đã nỗ lực. Và bạn không thực sự biết rằng đó là bài tập về nhà, @svr có thể là tự học. Điều này chắc chắn là tốt hơn so với các chú hề vừa cắt và dán câu hỏi bài tập về nhà của họ đúng nguyên văn. – paxdiablo

Trả lời

0

Một vấn đề rõ ràng là bạn tĩnh phân bổ 'mảng' và không bao giờ kiểm tra các giới hạn chỉ số trong khi truy cập nó. Tràn bộ đệm chờ đợi để xảy ra. Trong thực tế, bạn không bao giờ đặt lại biến i trong vòng lặp đầu tiên, vì vậy tôi hơi bối rối về cách chương trình được cho là hoạt động. Dường như bạn đang lưu trữ đầu vào hoàn chỉnh trong bộ nhớ trước khi in từ đó?

Vì vậy, đề xuất: hợp nhất hai vòng với nhau và in đầu ra cho mỗi dòng mà bạn đã hoàn thành. Sau đó, bạn có thể tái sử dụng mảng cho dòng tiếp theo.

Ồ, và tên biến tốt hơn và một số nhận xét. Tôi không biết 'DELIM' có nghĩa vụ phải làm gì.

0

Dường như (không có kiểm tra) giống như nó có thể hoạt động, nhưng có vẻ phức tạp.

Dưới đây là một số giả cho suy nghĩ đầu tiên của tôi

const int MAXLINE = ?? — maximum line length parameter 
int chrIdx = 0 — index of the current character being considered 
int cand = -1 — "candidate index", Set to a potential break character 
char linebuf[bufsiz] 
int lineIdx = 0 — index into the output line 
char buffer[bufsiz] — a character buffer 
read input into buffer 
for ix = 0 to bufsiz -1 
do  
    if buffer[ix] == ' ' then 
     cand = ix 
    fi 
    linebuf[lineIdx] = buffer[ix] 
    lineIdx += 1 
    if lineIdx >= MAXLINE then 
     linebuf[cand] = NULL — end the string 
     print linebuf 
     do something to move remnants to front of line (memmove?) 
    fi 
od 

Đó là muộn và tôi chỉ có một vành đai, vì vậy có thể có sai sót, nhưng nó cho thấy những ý tưởng chung - tải một bộ đệm, và sao chép nội dung của đệm vào một bộ đệm dòng, theo dõi các điểm phá vỡ có thể. Khi bạn đến gần kết thúc, hãy sử dụng điểm ngắt.

7

tôi chắc chắn rằng bạn trên đường đua rigth, nhưng một số gợi ý để có thể đọc:

  • bình luận cụ của bạn
  • tên biến đúng cách và ít nhất cho một mô tả nếu bạn từ chối
  • thể là hậu quả , một số dòng đơn nếu bạn sử dụng và một số bạn không sử dụng. (IMHO, luôn luôn sử dụng {} do đó, nó dễ đọc hơn)
  • câu lệnh if trong cuối cùng cho vòng lặp có thể được tốt hơn, như

    if(array[0] != NEWLINE) 
    { 
     printf("%c", array[line]); 
    } 
+0

@Mafti: Tôi sẽ làm theo tất cả các đề xuất của bạn; đó là một bản nháp đầu tiên, chỉ để xem tôi có bị treo nó một cách thanh lịch hay không. Bạn nói đúng về chuỗi vòng lặp cuối cùng, có lẽ tôi đã biết tốt hơn để viết nó như vậy. Cảm ơn –

2

Đó là không IMHO tốt.

Trước tiên, nó không làm những gì bạn được yêu cầu. Bạn được cho là sẽ tìm thấy ô trống cuối cùng sau một đường không trống trước ranh giới đường dây đầu ra. Chương trình của bạn thậm chí không cố gắng làm điều đó từ xa, có vẻ như cố gắng tìm kiếm ô trống đầu tiên sau (ký tự - 5) ký tự (số 5 xuất phát từ đâu? Nếu tất cả các từ có 9 chữ cái?). Tuy nhiên nó cũng không làm điều đó, vì thao tác của bạn với biến newls. Ngoài ra, điều này:

for(line = 0; line < i; line++) { 
    if(array[0] == NEWLINE) 
     ; 
    else 
     printf("%c", array[line]); 
} 

có thể là sai, bởi vì bạn kiểm tra điều kiện không bao giờ thay đổi trong suốt vòng lặp.

Và, cuối cùng nhưng không kém, lưu trữ toàn bộ tập tin trong một bộ đệm kích thước cố định là không tốt, vì hai lý do:

  • bộ đệm là ràng buộc để tràn trên các tập tin lớn
  • ngay cả khi nó sẽ không bao giờ tràn, mọi người vẫn không thích bạn để lưu trữ ví dụ. một tệp gigabyte trong bộ nhớ chỉ để cắt nó thành các khối gồm 25 ký tự

Tôi nghĩ bạn nên bắt đầu lại, suy nghĩ lại thuật toán của bạn (bao gồm các trường hợp góc) và chỉ sau đó mới bắt đầu viết mã. Tôi đề nghị bạn:

  • quá trình tập tin line-by-line (có nghĩa là dòng đầu ra)
  • cửa hàng dòng trong một bộ đệm đủ lớn để giữ dòng đầu ra lớn nhất
  • tìm kiếm cho nhân vật bạn sẽ đột nhập vào bộ đệm
  • rồi in (gợi ý: bạn có thể chấm dứt chuỗi bằng '\ 0' và in với printf("%s", ...)), sao chép những gì bạn không in vào đầu bộ đệm, tiếp tục từ đó
Các vấn đề liên quan