2017-03-09 73 views
0

所以我必須做這樣的練習:From STDIN take a string of text of any size, and then change every lowercase character to uppercase and vice versa and print it to a file or STDOUT。第二部分非常簡單。但是現在我怎麼能說一個字或者任何長度的短語呢?例如,當我以前做過的時候,我總是有一個長度爲500左右的緩衝區,但現在必須輸入任意長度的輸入。我怎樣才能做到這一點?裝配中未知尺寸的緩衝區

我必須在32位Linux機器的AT&T語法中執行此操作。

這是我現在的代碼:(不更改爲大寫/小寫)

SYSCALL32 = 0x80 
READ = 3 
WRITE = 4 
STDIN = 0 
STDOUT = 1 
EXIT = 1 
BUF_SIZE = 10 


.data 
    TEXT_SIZE: .long 0 
    BUFOR: .space BUF_SIZE 
    BUFOR1: .space BUF_SIZE 

.globl _start 
.text 

_start: 
reading: 
    movl $READ, %eax 
    movl $STDIN, %ebx 
    movl $BUFOR, %ecx 
    movl $BUF_SIZE, %edx 
    int $SYSCALL32 
    movl %eax, TEXT_SIZE 


    movl $WRITE, %eax 
    movl $STDOUT, %ebx 
    movl $BUFOR, %ecx 
    movl TEXT_SIZE, %edx 
    int $SYSCALL32 
    jmp reading 

所以在這裏我讀過的輸入長度254BUFOR,但如果輸入是什麼樣子的260個字節?

+0

你可以閱讀的500個字節的塊輸入文件,觀察一下你不需要知道整個輸入即可開始工作。 – fuz

+0

好吧,我讀了500字節,但接下來,我在哪裏存儲它或什麼? – Frynio

+0

使用一個靜態緩衝區,並按照需要讀取文件結尾的次數進行加載。像'while(!eof()){num_read = read(500);處理(num_read); }' – Tommylee2k

回答

1

這個簡單的解決辦法是在塊讀,直到最後一個讀取的字節是CR(進入被按下):

SYSCALL32 = 0x80 
READ = 3 
WRITE = 4 
STDIN = 0 
STDOUT = 1 
EXIT = 1 
BUF_SIZE = 10 

.data 
TEXT_SIZE: .long 0 
BUFOR: .space BUF_SIZE 
BUFOR1: .space BUF_SIZE 

.globl _start 
.text 

_start: 
reading: 
    movl $READ, %eax 
    movl $STDIN, %ebx 
    movl $BUFOR, %ecx 
    movl $BUF_SIZE, %edx 
    int $SYSCALL32 
    movl %eax, TEXT_SIZE 

    ; add the code for uppercase <-> lowercase here  

    movl $WRITE, %eax 
    movl $STDOUT, %ebx 
    movl $BUFOR, %ecx 
    movl TEXT_SIZE, %edx 
    int $SYSCALL32 

    movl $BUFOR, %esi  ; last byte read = $BUFOR + 
    addl TEXT_SIZE, %esi  ; TEXT_SIZE 
    mov -1(%esi), %ah  ; -1 
    cmp $0x0a, %ah   ; it if's not CR, keep on reading 
    jnz reading 

movl $EXIT, %eax    ; otherwise return to OS 
int $SYSCALL32 
ret 
0

明智的做法是讀入固定大小的緩衝區,處理數據並寫出來;只要read返回非零值就繼續執行。這實際上並不會以任何方式限制輸入字符串的長度,因爲系統提供了一些緩衝區並阻止寫入生成輸入的進程,直到進程讀取它爲止。

這將在C是這樣的:

unsigned char buf[512]; 
int readsz = 0; 
while(readsz = read(0, buf, sizeof(buf))) { 
    /* ... invert case ... */ 
    write(1, buf, readsz); 
} 

如果不是您分配確實需要一些莫名其妙的原因完全在內存中讀取整個字符串第一,你必須動態分配內存使用來自libc的malloc,並在循環的每次迭代中繼續使用realloc -ing,如果緩衝區已完成(您也可以使用sbrk做類似的事情,但它更復雜)。這將是這樣的:

int capacity = 512; 
int size = 0; 
int readsz = 0; 
char *buf = malloc(capacity); 
if(buf==0) abort(); /* not enough memory */ 
while(readsz = read(0, buf+size, capacity-size)) { 
    size+=readsz; 
    if(size==capacity) { 
     capacity *= 2; 
     char *nbuf = realloc(buf, capacity); 
     if(nbuf==0) abort(); /* not enough memory */ 
     buf = nbuf; 
    } 
} 
/* now the valid data in buffer is size; do your thing and write it out */ 
/* ... invert case ... */ 
write(1, buf, size); 

但是,這再次,這是有史以來最愚蠢的方式來解決這個問題。使用固定大小的緩衝區。


所以在這裏我讀過的輸入,長度254 BUFOR,但如果輸入是什麼樣子的260個字節長?

read會返回您的第一個254字節,並保留其餘的標準輸入緩衝區;它會在您的下一個read呼叫中提供它們。只要read返回與0不同的任何東西,就必須循環。當您得到0時,意味着標準輸入在另一端被關閉,您可以停止讀取並退出。

+0

我不能使用C庫,所以'malloc'不能使用 – Frynio

+0

@Frynio:你可以使用'brk'系統調用,但它更復雜,而且它很愚蠢;使用固定大小的緩衝區交替讀寫。 –

+0

我已經更新了有問題的代碼,我想我實際上正在這樣做,但現在它甚至可以讀取30字節到10字節緩衝區中 – Frynio