Trang 1 trên tổng số 2 12 Cuối cùngCuối cùng
Từ 1 tới 10 trên tổng số 11 kết quả

Đề tài: Đổi cơ số trong lập trình C

  1. #1
    Ngày gia nhập
    12 2007
    Bài viết
    224

    Mặc định Đổi cơ số trong lập trình C

    Em đang làm bài nì mà ko hiểu mấy chỗ in đậm . Mong các anh giúp :
    C Code:
    1. #include <stdio.h>
    2. #include <string.h>
    3.  
    4. char *doics(char *number, int n, int m)
    5. {
    6.   [COLOR="black"][B]static char ketqua[17];[/B][/COLOR]
    7.   char chuso[16] = "0123456789ABCDEF";
    8.   int i = 0, giatri = 0, len;
    9.  
    10.   len = strlen(number);
    11.   while(i<len) {
    12.     [B]giatri = giatri * n + (strchr(chuso, number[i]) - &chuso);[/B]
    13.     i++;
    14.   }
    15.   i=16;
    16.   ketqua[17] = 0;
    17.   do {
    18.     ketqua[i] = chuso[giatri % m];
    19.     giatri /= m;
    20.     i--;
    21.   } while (giatri > 0);
    22.   return [B](ketqua + i  + 1);[/B]
    23. }
    24.  
    25. void main()
    26. {
    27.   unsigned n, m;
    28.   char number[17], *ketqua;
    29.  
    30.   do {
    31.     printf("\nNhap gia tri N (2 - 16) : ");
    32.     scanf("%d", &n);
    33.   } while (n<2 || n>16);
    34.   getchar();
    35.   printf("Gia tri thuoc he %d : ", n);
    36.   gets(number);
    37.   do {
    38.     printf("Nhap gia tri M (2 - 16) : ");
    39.     scanf("%d", &m);
    40.   } while (m<2 || m>16);
    41.   printf("Gia tri %s o co so %u co gia tri o co so %u la : ", number, n, m);
    42.   ketqua = doics(number, n, m);
    43.   puts(ketqua);
    44.   getch();
    45. }

  2. #2
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Bạn check kết quả chưa nhỉ ?
    C++ Code:
    1. char chuso[16] = "0123456789ABCDEF";
    Cái này "chuso" trỏ tới chuỗi tự do thì sao subscript là 16 được, phải là
    C++ Code:
    1.  char chuso[17] =  "0123456789ABCDEF";
    Không biết C có khác C++ chỗ này không, mình không dám chắc nhưng complier mình nó complain chỗ này.
    Còn hàm này là của C, mình google nó ra :
    C++ Code:
    1. const char * strchr ( const char * str, int character );
    Nó trả về con trỏ trỏ tới sự có mặt đầu tiên của character trong chuỗi str, nếu không có thì nó trả về NULL.
    Mà mình cũng hiểu sao character lại có kiểu int, trong khi ví dụ của nó lại là
    C++ Code:
    1. /* strchr example */
    2. #include <stdio.h>
    3. #include <string.h>
    4.  
    5. int main ()
    6. {
    7.   char str[] = "This is a sample string";
    8.   char * pch;
    9.   printf ("Looking for the 's' character in \"%s\"...\n",str);
    10.   pch=strchr(str,'s');
    11.   while (pch!=NULL)
    12.   {
    13.     printf ("found at %d\n",pch-str+1);
    14.     pch=strchr(pch+1,'s');
    15.   }
    16.   return 0;
    17. }
    Còn về dòng này,
    C++ Code:
    1. giatri = giatri * n + (strchr(chuso, number[i]) - &chuso);
    Chỗ chữ số, mình phải sữa lại "chuso" không có cái tham chiếu trước đó thì mới run được, không biết bạn có nhầm chỗ này không ?
    Bạn có thể ghi ra yêu cầu rõ 1 tí được không, mình chẳng hiểu cái đề bài này muốn làm cái gì nên không biết giải thích sao nữa ?
    C++ Code:
    1.  return (ketqua + i  + 1)
    Chỗ này là trả về con trỏ thôi, con trỏ cũng là số, nên (+ i + 1) cũng chẳng sao.

    Hic, sorry bạn do đọc không kĩ, cái kiểu int của thằng "character" nó sẽ được chuyển lại thành char(64+i).
    Bây h quay lại câu lệnh đầu tiên của bạn :
    C++ Code:
    1.  static char ketqua[17];
    Cái này mãng ketqua khai báo là static thì nó sẽ tồn tại cho đến khi main kết thúc, tương tự như bạn khai báo :
    C++ Code:
    1. #include <stdio.h>
    2. #include <string.h>
    3. char ketqua[17]; //Bỏ static đi đặt nó ở đây để nó thành biến toàn cục
    4. char *doics(char *number, int n, int m)
    5. {
    6.  
    7.   char chuso[16] = "0123456789ABCDEF";
    8.   int i = 0, giatri = 0, len;
    9.   .....
    Bây giờ tới dòng này :
    C++ Code:
    1.  giatri = giatri * n + (strchr(chuso, number[i]) - chuso);
    thằng strschr sẽ trả về con trỏ trỏ tới vị trí mà thằng number[i] có mặt trong chuỗi "chuso", mà khai báo :
    C++ Code:
    1.  char chuso[16] = "0123456789ABCDEF";
    thì tên của mãng chính là con trỏ hằng, mà con trỏ này đang trỏ tới chuso[0].
    Bây h ví dụ ta có dòng lệnh :
    C++ Code:
    1.  strchr(chuso, 'A')
    thì chữ A nó xuất hiện ở vị trí thứ 10 trong mãng đó vậy nó sẽ trả về con trỏ :
    C++ Code:
    1.  *(chuso + 10)
    sau đó :
    C++ Code:
    1.  (strchr(chuso, number[i]) - chuso)
    thì tức là chỗ này sẽ cho ra giá trị mà nó xuất hiện trong chuỗi đó..Vậy bây h câu lệnh sau rõ ràng là tính toán giữa các số thôi, mà cụ thể với ví dụ mình nêu ở trên thì :
    (strchr(chuso, 'A') - chuso); = sẽ cho ra 10.
    Mình code ra cho bạn thấy luôn :
    C++ Code:
    1. #include <iostream>
    2. #include <string>
    3.  
    4. int main(){
    5.  
    6.   char chuso[17] = "0123456789ABCDEF";
    7.  
    8.   int i = strchr(chuso, 'A') - chuso;
    9.   std::cout << "i = " << i;
    10. }
    Còn phần còn lại tính toán với i*n gì gì đó thì mình chịu, do chẳng biết code bạn muốn tính cái gì nữa :(


    Còn dòng cuối cùng :
    C++ Code:
    1. return (ketqua + i  + 1);
    Bạn xem ví dụ này sẽ hiểu ngay :
    C++ Code:
    1. #include <iostream>
    2.  
    3. int main(){
    4.  
    5.   int kq[3] = {1,2,3};
    6.   int *ptr;
    7.   ptr = kq;
    8.  
    9.   std::cout << "&kq[0] = " << &kq[0] << '\n';
    10.   std::cout << "kq = " << kq << '\n';
    11.   std::cout << "*(kq+2) = " << *(kq+2) << '\n';
    12.   std::cout << "*ptr = " << *ptr ;
    13.   return 0;
    14. }
    Kết quả đây :
    &kq[0] = 0x246ff30
    kq = 0x246ff30
    *(kq+2) = 3
    *ptr = 1
    Tên của nó là con trỏ hằng, như nếu in ra thì thấy thực ra nó là địa chỉ của thằng số kq[0], vậy hàm này trả về con trỏ tức là :
    dòng : return (ketqua + i + 1) == *(ketqua + i + 1)
    Mà toán tử * là khử tham chiếu, vậy tức là chính là con trỏ trỏ tới 1 giá trị nào đó trong mãng ketqua[] đó.

  3. #3
    Ngày gia nhập
    12 2007
    Bài viết
    224

    Cám ơn rook . Cái static và cái return (ketqua+i+1) em đã hiểu . Ngoại trừ dòng sau:
    Code:
    giatri = giatri * n + (strchr(chuso, number[i]) - &chuso);
    Em thấy có dấu & vẫn chạy ngon . Em thắc mắc nhất chỗ đó . Vì em hiểu chuso là hằng điạ chỉ của chuso[0] . Đã là địa chỉ còn thêm dấu & để làm gì nhỉ . Thông thường phép & để dùng lấy điạ chỉ của 1 biến bình thường mà .

    Bài toán này là bài toán đổi cơ số từ cơ số n thành cơ số m thôi . Em biết chắc cái giatri ấy là để chuyển thành cơ số 10 trước thui .
    Đã được chỉnh sửa lần cuối bởi sieuphuong : 05-01-2008 lúc 02:47 PM.

  4. #4
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Ờ, do mình nhác đọc ý tưởng quá hì hì, còn chỗ đó thì ko hiểu sao complier mình đã thử cả TC và DevCpp nó đều complain hết á. Do mình bắt đầu học từ C++ nên cũng không rành C lắm, không biết nó có khác chỗ nào nữa. Mình cout ra thử thì nó cho kết quả thế này :
    C++ Code:
    1. #include <iostream>
    2.  
    3. int main(){
    4.  
    5.   char chuso[17] = "0123456789ABCDEF";
    6.  
    7.   std::cout << "&chuso = " << &chuso << '\n';
    8.   std::cout << "chuso = " << chuso << '\n';
    9.  
    10.   return 0;
    11. }

    Output Code:
    1. &chuso = 0x246ff1c
    2. chuso = 0123456789ABCDEF

    Theo mình nghĩ thì phải là "chuso" mới đúng vì thằng kia trả về con trỏ thì thằng này cũng phải là con trỏ, nhưng cái này lập luận chủ quan của mình thôi, nên có gì để mai mình xem lại coi sao. Bạn cũng tập cout << ra như mình á, cái nào không hiểu thì cout << nó ra, rồi để ý 1 chút là hiểu liền à ^^!

  5. #5
    Ngày gia nhập
    12 2007
    Bài viết
    224

    À , bác rox ơi . em phát hiện ra cái này cũng vui lắm :

    Code:
    void main()
    {
     int a[]={1,2,3};
     cout<<&a<<endl;
     cout<<a;
    }
    kết quả cả 2 cùng in ra địa chỉ của a . Chứng tỏ thêm dấu & trước 1 hằng địa chỉ là 1 điều vô nghĩa . Có cũng như ko thôi . Bác nhận xét giúp .

  6. #6
    Ngày gia nhập
    11 2006
    Bài viết
    633

    Mặc định Đổi cơ số trong lập trình C

    Hơi nhầm 1 chút ^^
    a trong &a được hiểu là 1 mảng và dấu & sẽ đi lấy địa chỉ của mảng a tức là lấy địa chỉ của vị trí đầu tiên trong mảng.
    a trong a được hiểu là pointer chỉ đến vị trí đầu tiên trong mảng.
    2 cái có 2 ý nghĩa khác nhau đó nha.
    Chuyện lấy địa chỉ của 1 địa chỉ thì còn xem lại xem có pointer chỉ tới hay ko.
    Nhân tiện nhận xét rox chút:
    Cậu dùng using namespace std; cho nó gọn, khỏi phải mỗi câu lệnh cout, cin thêm cái std:: ở đầu.
    Hoan nghênh cậu lên làm mod box C++.

  7. #7
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Mình đọc tới đọc lui cả mấy tiếng đồng hồ mà chưa hiểu phải giải thích sao cho hợp lý, thôi mình post lên cho bạn coi những điểm khác biệt, biết đâu bạn có thể rút ra kết luận cho bạn cũng được:
    Trong C++, thực chất thằng char và các kiểu còn lại như int, float, double.. là hoàn toàn khác nhau, bây h bạn coi ví dụ sau :
    C++ Code:
    1. #include <iostream>
    2. int main(){
    3.  
    4.   int x = 0;
    5.   int *ptr = &x;
    6.   std::cout << "The address of x is " << ptr << '\n'
    7.             << "the value of x " << *ptr << '\n';
    8.   return 0;
    9. }

    Output

    The address of x is 0x246ff40
    the value of x 0
    Nhưng đó là kiểu int, nếu bây đổi thành char là nó in ra garbage ngay :
    C++ Code:
    1. #include <iostream>
    2.  
    3. int main(){
    4.  
    5.   char x('A');
    6.   char *ptr = &x;
    7.   std::cout << "The address of x is : " << ptr << '\n'
    8.             << " and the value of x : " << *ptr << '\n';
    9.   return 0;
    10. }
    Output
    The address of x is : Aê F☻☻D
    and the value of x : A
    Đó, bạn thấy đó, rõ ràng là do thằng nó ra rác, chỗ này là do thằng cout << của C++, nó được overloaded để in ra dữ liệu của thằng char * như là 1 chuỗi kí tự có NULL ở cuối, cho nên bây h muốn đúng thì ta đổi thành như sau :
    SOLUTION
    C++ Code:
    1. #include <iostream>
    2.  
    3. int main(){
    4.  
    5.   char x('A');
    6.   char *ptr = &x;
    7.   std::cout << "The address of x is : " << static_cast<void*>(ptr) << '\n'
    8.             << " and the value of x : " << *ptr << '\n';
    9.   return 0;
    10. }

    Bây h quay lại thằng int :
    C++ Code:
    1. int main(){
    2.  
    3.   int array[3] = {1,2,3};
    4.  
    5.   for(int x = 0; x < 3; x++)
    6.     std::cout << &array[x] << '\n';
    7.  
    8.   return 0;
    Output
    0x246ff34
    0x246ff38
    0x246ff3c
    Rõ ràng nó cout ra địa chỉ của từng phần tử. Như bạn đã nêu ra cái mà bạn nói thú vị đó và cũng như huynguyen đã nói : tên của mãng thực chất là con trỏ hằng trỏ tới vị trí đầu tiên của mãng, vậy nếu có khai báo :
    Code:
     ptr = array
    thì tương đương với :
    Code:
     ptr = &array[0]
    Vì vậy bạn cout ra nó có kết quả như nhau.
    Nhưng đó là đối với mãng int, còn đối với mãng char trong C++ thì nó khác. Ví dụ :
    C++ Code:
    1. int main(){
    2.  
    3.   char array[] = "abc";
    4.  
    5.   for(int x = 0; x < 3; x++){
    6.     cout << &array[x] << '\n';
    7.   }
    8.   return 0;
    Output
    abc
    bc
    c
    Vì các kí tự là những cấu trúc cơ bản 1 chương trình C++. Mỗi chương trình sẽ được là tác phẩm của 1 loạt các kí tự, mà khi các kí tự này được gom lại 1 cách có ý nghĩa thì nó được thông dịch bởi complier nhưng là 1 chuỗi các hướng dẫn dùng để tiến hành 1 nhiệm vụ nào đó. Và một chương trình thì có thể chưa những kí tự hằng (character constant). Mà 1 kí tự hằng thì là 1 giá trị kiểu integer được biễu diễn bởi 2 cái quote ví dụ 'A', 'B'...
    Trong khi thằng string lại là 1 chuỗi của các kí tự mà nó được xem như là 1 thể độc lập. Mà chuỗi trong C++ thì được viết với syntax là :
    "Iam C++", "This is my cat"...
    Đồng thời chuỗi trong C++ là 1 mãng của các kí tự mà kết thúc bởi 1 kí tự null (null character) ('\0'), cái này là cái mà để xác định chuỗi kết thúc trong bộ nhớ máy tính. Mà 1 chuỗi thì được truy xuất thông qua 1 con trỏ tới kí tự đầu của chuỗi đó. Cho nên khai báo :
    Code:
     char color[] = "blue";
    Và khai báo :
    Code:
     char color[] = {'b','l','u','e','\0'};
    Là hoàn toàn giống nhau. Và khai báo như thế nghĩa là các kí tự tạo thành 1 chuỗi tự do, liên tục nhau, và nó được bộ nhớ máy tính lưu tại 1 địa chỉ nào đó trong vùng nhớ.
    Cái này tuy hơi lạc đề, nhưng mình nghĩ muốn hiểu cái gì đến tận cùng đầu tiên phải nắm bản chất của nó là gì, vì trong lập trình sai 1 ly thì đi 1 dặm.

    Bây giờ vấn đề chính là tại sao nếu khai báo char :
    Code:
    cout << &chuso

    Code:
    cout << chuso
    lại khác nhau
    trong khi khai báo int
    Code:
    cout << chuso
    Code:
    cout << &chuso
    lại giống nhau
    Cho đến h mình chỉ có 2 giải thiết :
    - Thứ nhất là thực chất vì chuỗi là tự do, nằm liên tục cho nên nó chỉ có 1 địa chỉ duy nhất, do đó ta không truy xuất được các địa chỉ tiếp theo của nó, mà tau chỉ có thể truy xuất tới thông qua con trỏ của nó thôi.
    - Thứ hai là do nó là string, nên có thể thằng cout << được quá tải để xử lý đối với trường hợp là chuỗi, do đó nó sẽ tự hiểu và in ra giá trị thay vì địa chỉ của nó. Mình thì có lẽ thấy cái trường hợp này đúng hơn, vì bản chất thằng stream cout << nó không có quá tải cho thằng pointer kiểu int, hay float...nên nó output ra thẳng địa chỉ, trong khi đối với những string thì nó lại cho ra giá trị vì nó có quá tải của string trong đó.
    Mình chỉ hiểu được tới đó, thôi đành để những tiền bối như anh TQN giải đáp vậy :(. Nhưng cũng cám ơn bạn vì những câu hỏi khó chịu như vậy, haha, tìm hiểu nó mà oải luôn nhưng bù lại biết được cái mình chưa biết- mà cái này giá trị hơn ^^!

  8. #8
    Ngày gia nhập
    08 2006
    Bài viết
    59

    Thân gửi bạn rox_rook,

    thằng char và các kiểu còn lại như int, float, double.. là hoàn toàn khác nhau
    ......
    Nhưng đó là đối với mãng int, còn đối với mãng char trong C++ thì nó khác
    => tui thì nghĩ là: char và int, float, double là giống nhau (tui tạm gọi là kiểu đơn): nếu x là kiểu đơn (char, int, float, double) thì nói chung: x khác với &x

    Nhưng mảng và kiểu đơn thì khác nhau: nếu m là mảng thì m và &m là giống nhau
    (và mảng char thì cũng giống như mảng int)

    Tuy nhiên, với cout: như nhận định cuối cùng của bạn về quá tải cho cout => làm cho bạn có cảm giác là ch và &ch là giống nhau khi bạn xài cout. Nếu mình thay cout bằng printf thì sẽ thấy ch và &ch là khác nhau (printf 1 con trỏ thì phải xài "%p" và ép kiểu về (void*))

    (còn trường hợp mảng char và mảng int của bạn:
    "&array[x]" => thực chất là do cout xử lý &char và &int khác nhau như nói ở trên; bạn thử thay cout bằng printf coi sao (printf 1 con trỏ thì phải xài "%p" và ép kiểu về (void*))

    (hiểu biết nông cạn; có gì sai sót mong được góp ý; xin cám ơn)

    - thân
    Đã được chỉnh sửa lần cuối bởi bete : 06-01-2008 lúc 09:45 AM.

  9. #9
    Ngày gia nhập
    12 2006
    Nơi ở
    US
    Bài viết
    1,917

    Mình không hiểu về printf cho lắm, Bete có thể cho mình biết cú pháp xài printf thế nào để in ra địa chỉ của chuỗi tự do được không ? Bete dùng printf có thể in ra địa chỉ của phần tử thứ 2 của mãng khai báo thế này không ?
    PHP Code:
     char A[] = "abc"

  10. #10
    Ngày gia nhập
    09 2006
    Bài viết
    711

    printf("0x%08X\n", &A[2]);

Quyền hạn của bạn

  • Bạn không thể gửi đề tài mới
  • Bạn không thể gửi bài trả lời
  • Bạn không thể gửi các đính kèm
  • Bạn không thể chỉnh sửa bài viết của bạn