Hỏi bài về pascal (câu lệnh for to do)

em ko hiểu hết được đoạn code

for i:=1 to n do
for j:=1 to n do
if a[i] mod 2=1 then 
begin
t:=a[i];
a[i]:=a[j];
a[j];=t;
end;

bài sắp kếp số lẻ lên dầu dãy

ở đây là a[j] := t; nhé, viết sai lệnh gán rồi.

bài này người ta dùng 2 vòng for, vòng ngoài để duyệt từng vị trí bắt đầu từ đầu mảng, vòng trong để tìm ra số lẻ và nhét vào vị trí đang xét ở vòng ngoài, sau mỗi lần vòng trong chạy hết thì số lẻ đã được đẩy dần dần vào các vị trí đầu mảng.

cho em hỏi ngu phát là khi vòng ngoài chạy và thỏa mãn điều kiện (mod2=1) thì nó lại đổi chỗ cho số j thứ nhất chứ tức là a[1]

Không sao đâu, chưa hiểu thì phải hỏi chứ giấu thì làm sao mà tiến bộ được.
Nó đổi chỗ cho a[i] chứ không phải chỉ đổi chỗ cho số thứ nhất. i sẽ chạy từ số thứ nhất đến hết.
nhưng mà đoạn code này không ổn lắm. phải cho j chạy từ i+1 đến n. còn i thì chạy đến n-1 thôi. lệnh if thì xét a[j] mod 2=1 chứ không phai a[i].
với lại khi tìm được 1 số lẻ nào đó và đưa nó về vị trí của i rồi thì nên thoát khỏi vòng lặp trong và để i tăng lên, tìm số lẻ khác đưa về.

for i:=1 to n-1 do
    for j:=i+1 to n do
        if a[j] mod 2 = 1 then
        begin
            t := a[i];
            a[i] := a[j];
            a[j] := t;
            break;
        end;
5 Likes

:)) “end.” chứ : “end;” à.

bắt bẻ không đúng lúc rồi bạn.
end; ở đây để kết thúc cho khối lệnh trong if
nếu muốn end. thì phải là kết thúc cho cái begin thân chương trình.
nhưng không thấy begin thân chương trình nên đây chỉ là 1 đoạn code được trích ra. làm sao mà end. được.

1 Like

em cảm ơn anh. em hỏi bài khác : xóa các số trùng nhau trong mảng
code:

j:=0;
for k:=1 to n do
for i:=1 to n-j do
if (a[i]=a[k]) then (i<>k)
begin
t:=a[n-j];
a[n-j]:=a[i];
a[i]:=t;
j:=j+1;
end;

đoạn code trên sai nhưng em nghĩ mãi mà ko biết nó sai ở đâu

bạn cho code vào markdown cho dễ nhìn.

chỗ này chắc ý bạn là
if (a[i]=a[k]) and (i<>k) then

nhưng mình vẫn chưa hiểu ý tưởng thuật toán của bạn. mình mới thấy bạn đổi chỗ các phần tử nhưng không thấy là xoá đi phần tử nào.

ý của em là cho một vòng chạy nữa

for i:=1 to n-j do 
write(' ',a[i]);

em không biết phần mềm markdown ở đâu ^^

không phải down đâu bạn, bạn xem hướng dẫn post code theo định dạng ở bài viết này nè.
http://daynhauhoc.com/t/cach-post-code-dung-markdown-trong-category-programming

chỗ này mình chưa hiểu ý bạn lắm.

i = 1 -> n - j
write()

j = số phần tử trùng.
Vậy đoạn pascal trên in ra số phần tử còn lại.

Thuật toán bạn ấy dùng là với mỗi phần tử a[k]. Tìm phần tử a[i] trùng với nó.
Sau đó đổi chỗ phần tử trùng tại vị trí i với vị trí cuối mảng.
Cuồi cùng tăng j lên.

1 Like

à, mình hiểu rồi. :smile:
thế cũng không ổn lắm.

vì cái này nên nó sẽ xếp tiếp xuống cuối những phần tử có số bị trùng với số đã bị chuyển xuống cuối. vậy nên các phần tử mà có số bị trùng thì sẽ không được in ra.

anh thử code hộ em được ko, nghĩ mãi thì em vẫn thấy em hợp lí

Bạn thử thế này xem:

j:=0;
for k:=1 to n-j do
for i:=1 to n-j do
if (a[i]=a[k]) and (i<>k) then
begin
t:=a[n-j];
a[n-j]:=a[i];
a[i]:=t;
j:=j+1;
end;
for i:=1 to n-j do 
write(' ',a[i]);
1 Like

anh ơi ko được, nó ko in ra dãy số

Sao bạn k học C ngôn ngữ trong sáng dễ hiểu, mà thi tin cũng cho xài C, muốn giúp bạn mà thấy pascal ngán quá @@ đó là 1 nỗi ám ảnh lớn của mình hê hê.

vòng lặp có điều kiện thì dùng while mới đc, hình như for nó không có tác dụng.
mình sửa lại và test rồi đây:

j:=0;
k:=1;
while (k<=n-j) do
begin
    i:=1;
    while (i<=n-j) do
    begin
        if (a[i]=a[k]) and (i<>k) then
        begin
            t:=a[n-j];
            a[n-j]:=a[i];
            a[i]:=t;
            j:=j+1;
        end;
        i:=i+1;
    end;
    k := k+1;
end;
for i:=1 to n-j do 
write(' ',a[i]);

để hiểu kĩ mấy cái lệnh lập trình thật ko dễ. Em cảm ơn anh!!!

1 Like
83% thành viên diễn đàn không hỏi bài tập, còn bạn thì sao?