Chuyển đổi char thành int trong C và C ++


401

Làm cách nào để chuyển đổi a charthành intC trong C và C ++?


1
@Matt: nó sẽ là một ý tưởng tốt để cụ thể hơn. hỏi về một khái quát hóa chỉ mời những câu trả lời khái quát không thể áp dụng hoặc thậm chí đúng cho nhiệm vụ của bạn. Hãy nhớ rằng, khi bạn phải hỏi, có lẽ bạn không biết đủ để khái quát chính xác.
Chúc mừng và hth. - Alf

@Alf P. Steinbach: Câu hỏi ban đầu rất mơ hồ về ngôn ngữ nào. Với các từ khóa cc++, tôi nghĩ rằng câu trả lời đối đầu với cả hai ngôn ngữ là hợp lý.
Matt Joiner

8
Từ kinh nghiệm sâu rộng của tôi trên các diễn đàn kỹ thuật khác, trực giác của tôi là OP thực sự có nghĩa là "làm thế nào để tôi biểu diễn văn bản của một số (trong cơ sở 10) và chuyển đổi nó thành số tương ứng?" Nói chung, Ceophyte C và C ++ thường có những ý tưởng vô cùng mờ nhạt về cách văn bản hoạt động trong các ngôn ngữ đó và ý charnghĩa thực sự của nó.
Karl Knechtel

3
@KarlKnechtel: Nếu đó là sự thật (Tôi cho nó khoảng 50/50 vì nhiều hướng dẫn ban đầu cũng khuyến khích lấy các giá trị ASCII ra khỏi ký tự, mặc dù ASCII không bao gồm toàn bộ phạm vi), OP cần phải rõ ràng - nhưng đó là một bản sao của stackoverflow.com/questions/439573/ cường .
Fred Nurk

3
OP đã có ba giờ để làm rõ câu hỏi này và không làm như vậy. Vì nó là như vậy, không có cách nào để biết những gì thực sự được hỏi. Bình chọn để đóng.
sbi

Câu trả lời:


551

Phụ thuộc vào những gì bạn muốn làm:

để đọc giá trị dưới dạng mã ascii, bạn có thể viết

char a = 'a';
int ia = (int)a; 
/* note that the int cast is not necessary -- int ia = a would suffice */

để chuyển đổi nhân vật '0' -> 0, '1' -> 1, vv, bạn có thể viết

char a = '4';
int ia = a - '0';
/* check here if ia is bounded by 0 and 9 */

Giải thích :
a - '0'tương đương với ((int)a) - ((int)'0'), có nghĩa là các giá trị ascii của các ký tự được trừ vào nhau. Vì 0xuất hiện trực tiếp trước đó 1trong bảng ascii (và cứ thế cho đến khi 9), sự khác biệt giữa hai cái cho số mà nhân vật ađại diện.


14
ia = (a - '0')% 48;
Kshitij Banerjee

@KshitijBanerjee Đó không phải là ý tưởng hay vì hai lý do: nó cung cấp cho bạn số âm cho các ký tự ascii trước '0' (như &-> -10) và nó cung cấp cho bạn các số lớn hơn 10 (như x-> 26)
SheetJS

2
int ia = a - '0' - đó là những gì bạn cần
funk

5
@ kevin001 Nếu bạn muốn chuyển đổi char thành int và một ký tự '1'cung cấp số ascii thì không 1, bạn cần xóa phần bù '0'để căn chỉnh lại để đếm từ 0-9. Các số liên tiếp 1-9 nằm liền kề trong số nguyên ascii.
krisdestrraction

Không yêu cầu diễn viên / mong muốn
Craig Estey

97

Chà, trong mã ASCII, các số (chữ số) bắt đầu từ 48 . Tất cả bạn cần làm là:

int x = (int)character - 48;

19
@chad: Không chỉ dễ đọc hơn, nó còn dễ mang theo hơn. C và C ++ không đảm bảo đại diện ASCII, nhưng họ đảm bảo rằng bất kỳ đại diện nào đang được sử dụng, các đại diện của 10 chữ số thập phân đều liền kề nhau và theo thứ tự số.
Ben Voigt

Điều duy nhất tôi đã thay đổi là bước sang tuổi 48, có vẻ hơi "ma thuật" thành'0'
ArielGro

59

C và C ++ luôn thúc đẩy các loại ít nhất int. Hơn nữa, các ký tự chữ có loại inttrong C và chartrong C ++.

Bạn có thể chuyển đổi một charloại chỉ đơn giản bằng cách gán cho một int.

char c = 'a'; // narrowing on C
int a = c;

3
Bạn cũng có thể sử dụng unary được đánh giá thấp operator+()cho mục đích này.
Cubbi

24
-1 Câu trả lời không chính xác cho cách giải thích có ý nghĩa duy nhất của câu hỏi. (Mã int a = c;) này sẽ giữ bất kỳ giá trị âm nào, mà các hàm thư viện chuẩn C không thể xử lý. Các hàm thư viện chuẩn C đặt tiêu chuẩn cho ý nghĩa của việc xử lý charcác giá trị là int.
Chúc mừng và hth. - Alf

6
@Matt: Tôi đang giữ downvote. Tôi sẽ tăng cường nếu có thể! Việc giải thích câu hỏi mà bạn và những người khác đã cho là không có ý nghĩa, bởi vì nó quá tầm thường và bởi vì sự kết hợp các loại đặc biệt của OP có một vấn đề thực tế rất quan trọng không quan trọng. Những lời khuyên bạn đưa ra là nguy hiểm trực tiếp cho người mới. Nó rất có thể sẽ dẫn đến Hành vi không xác định cho các chương trình của họ sử dụng các hàm phân loại ký tự thư viện chuẩn C. Giới thiệu lại. với câu trả lời của @ Sayam, anh ta đã xóa câu trả lời đó.
Chúc mừng và hth. - Alf

3
-1 vì không chính xác: isupper () sẽ có kết quả không xác định nếu vượt qua ký tự 1252 highbit.
Chris Becke

1
Bạn có ý nghĩa gì bởi "luôn luôn thúc đẩy"? Các giá trị được phát huy trong quá trình chuyển đổi ngầm định, một số loại tham số nhất định truyền (ví dụ: sang hàm varargs) và khi toán tử phải làm cho các toán hạng của nó tương thích với các loại. Nhưng chắc chắn có những lúc giá trị không được phát huy (như nếu tôi chuyển char cho hàm mong đợi char), nếu không chúng ta sẽ không có loại nào nhỏ hơn int.
Adrian McCarthy

31

char chỉ là số nguyên 1 byte. Không có gì kỳ diệu với loại char! Giống như bạn có thể gán một đoạn ngắn cho một int hoặc một int cho một long, bạn có thể gán một char cho một int.

Đúng, tên của kiểu dữ liệu nguyên thủy là "char", trong đó ẩn ý rằng nó chỉ nên chứa các ký tự. Nhưng trong thực tế, "char" chỉ là một cái tên nghèo nàn để gây nhầm lẫn cho tất cả những người cố gắng học ngôn ngữ. Một tên tốt hơn cho nó là int8_t và thay vào đó bạn có thể sử dụng tên đó, nếu trình biên dịch của bạn tuân theo tiêu chuẩn C mới nhất.

Mặc dù tất nhiên bạn nên sử dụng kiểu char khi thực hiện xử lý chuỗi, bởi vì chỉ mục của bảng ASCII cổ điển phù hợp với 1 byte. Tuy nhiên, bạn cũng có thể xử lý chuỗi với ints thông thường, mặc dù không có lý do thực tế nào trong thế giới thực tại sao bạn lại muốn làm điều đó. Ví dụ: đoạn mã sau sẽ hoạt động hoàn hảo:

  int str[] = {'h', 'e', 'l', 'l', 'o', '\0' };

  for(i=0; i<6; i++)
  {
    printf("%c", str[i]);
  }

Bạn phải nhận ra rằng các ký tự và chuỗi chỉ là số, giống như mọi thứ khác trong máy tính. Khi bạn viết 'a' trong mã nguồn, nó được xử lý trước thành số 97, là hằng số nguyên.

Vì vậy, nếu bạn viết một biểu thức như

char ch = '5';
ch = ch - '0';

điều này thực sự tương đương với

char ch = (int)53;
ch = ch - (int)48;

sau đó sẽ trải qua các chương trình khuyến mãi số nguyên ngôn ngữ C

ch = (int)ch - (int)48;

và sau đó cắt ngắn thành một char để phù hợp với loại kết quả

ch = (char)( (int)ch - (int)48 );

Có rất nhiều điều tinh tế như thế này xảy ra giữa các dòng, trong đó char được coi là một int.


Vì câu hỏi không được gắn thẻ ascii, bạn không nên sử dụng bất kỳ mã hóa cụ thể nào. Đặt charbằng int8_tlà sai vì nó có thể giống nhau uint8_thoặc uint24_t.
Roland Illig

1
@RolandIllig Không, a charluôn là 1 byte và nếu các loại int8_t/ uint8_ttồn tại trên hệ thống đã cho (rất có thể), chúng sẽ có thể phù hợp với kết quả của a char, vì khi đó nó sẽ là 8 bit. Trên các hệ thống rất kỳ lạ như DSP lỗi thời khác nhau, charsẽ là 16 bit và uint8_tsẽ không tồn tại. Viết mã để tương thích với DSP lỗi thời là vô nghĩa, cũng như viết cho khả năng tương thích với các hệ thống bổ sung hoặc ký hiệu & cường độ của một người. Lãng phí thời gian rất lớn, vì các hệ thống như vậy hầu như không tồn tại trong thế giới thực.
Lundin

18

(Câu trả lời này đề cập đến khía cạnh C ++, nhưng vấn đề mở rộng dấu hiệu cũng tồn tại trong C.)

Xử lý cả ba charloại ( signed, unsignedchar) tinh tế hơn lần đầu tiên xuất hiện. Các giá trị trong phạm vi từ 0 đến SCHAR_MAX(là 127 cho 8 bit char) rất dễ dàng:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
int n = c;

Nhưng, khi somevaluenằm ngoài phạm vi đó, chỉ đi qua unsigned charsẽ mang lại cho bạn kết quả nhất quán cho các chargiá trị "giống nhau" trong cả ba loại:

char c = somevalue;
signed char sc = c;
unsigned char uc = c;
// Might not be true: int(c) == int(sc) and int(c) == int(uc).
int nc = (unsigned char)c;
int nsc = (unsigned char)sc;
int nuc = (unsigned char)uc;
// Always true: nc == nsc and nc == nuc.

Điều này rất quan trọng khi sử dụng các hàm từ ctype.h , chẳng hạn như isupperhoặc toupper, vì phần mở rộng dấu hiệu:

char c = negative_char;  // Assuming CHAR_MIN < 0.
int n = c;
bool b = isupper(n);  // Undefined behavior.

Lưu ý chuyển đổi thông qua int là ẩn; cái này có cùng một UB:

char c = negative_char;
bool b = isupper(c);

Để sửa lỗi này, đi qua unsigned char, mà có thể dễ dàng thực hiện bằng cách gói ctype.h chức năng thông qua safe_ctype :

template<int (&F)(int)>
int safe_ctype(unsigned char c) { return F(c); }

//...
char c = CHAR_MIN;
bool b = safe_ctype<isupper>(c);  // No UB.

std::string s = "value that may contain negative chars; e.g. user input";
std::transform(s.begin(), s.end(), s.begin(), &safe_ctype<toupper>);
// Must wrap toupper to eliminate UB in this case, you can't cast
// to unsigned char because the function is called inside transform.

Điều này hoạt động bởi vì bất kỳ chức năng nào lấy bất kỳ loại nào trong ba loại char cũng có thể lấy hai loại char khác. Nó dẫn đến hai chức năng có thể xử lý bất kỳ loại nào:

int ord(char c) { return (unsigned char)c; }
char chr(int n) {
  assert(0 <= n);  // Or other error-/sanity-checking.
  assert(n <= UCHAR_MAX);
  return (unsigned char)n;
}

// Ord and chr are named to match similar functions in other languages
// and libraries.

ord(c)luôn cung cấp cho bạn một giá trị không âm - ngay cả khi được truyền âm charhoặc âm signed char- và chrlấy bất kỳ giá trị nào ordtạo ra và trả lại chính xác như nhau char.

Trong thực tế, tôi có thể chỉ unsigned charsử dụng thay vì sử dụng chúng, nhưng chúng thực sự bao bọc các diễn viên, cung cấp một nơi thuận tiện để thêm kiểm tra lỗi cho int-to- char, và sẽ ngắn hơn và rõ ràng hơn khi bạn cần sử dụng chúng nhiều lần trong một khoảng cách rất gần.



7

Nó phụ thuộc vào những gì bạn có nghĩa là "chuyển đổi".

Nếu bạn có một loạt các ký tự đại diện cho một số nguyên, như "123456", thì có hai cách điển hình để thực hiện điều đó trong C: Sử dụng chuyển đổi mục đích đặc biệt như atoi () hoặc strtol () hoặc sscanf cho mục đích chung () . C ++ (thực sự là một ngôn ngữ khác giả dạng như một bản nâng cấp) thêm một chuỗi thứ ba.

Nếu bạn có nghĩa là bạn muốn mẫu bit chính xác trong một trong các intbiến của bạn được coi là một char, thì điều đó dễ dàng hơn. Trong C, các loại số nguyên khác nhau thực sự mang nhiều ý nghĩa hơn là các "loại" riêng biệt thực sự. Chỉ cần bắt đầu sử dụng nó ở những nơi charđược yêu cầu, và bạn sẽ ổn thôi. Bạn có thể cần một chuyển đổi rõ ràng để làm cho trình biên dịch thoát khỏi rên rỉ, nhưng tất cả những gì nên làm là bỏ bất kỳ bit thừa nào qua 256.


6

Tôi hoàn toàn có nullkỹ năng về C, nhưng để phân tích cú pháp đơn giản:

char* something = "123456";

int number = parseInt(something);

... điều này làm việc cho tôi:

int parseInt(char* chars)
{
    int sum = 0;
    int len = strlen(chars);
    for (int x = 0; x < len; x++)
    {
        int n = chars[len - (x + 1)] - '0';
        sum = sum + powInt(n, x);
    }
    return sum;
}

int powInt(int x, int y)
{
    for (int i = 0; i < y; i++)
    {
        x *= 10;
    }
    return x;
}

Mã này nhanh chóng gọi hành vi không xác định và do đó không phù hợp để sao chép và dán. (int tràn)
Roland Illig

4

Có lẽ bạn muốn chuyển đổi này để sử dụng các chức năng từ thư viện chuẩn C.

Trong trường hợp đó, do (cú pháp C ++)

typedef unsigned char UChar;

char myCppFunc( char c )
{
    return char( someCFunc( UChar( c ) ) );
}

Biểu thức UChar( c )chuyển đổi thành unsigned charđể loại bỏ các giá trị âm, ngoại trừ EOF, không được các hàm C hỗ trợ.

Sau đó, kết quả của biểu thức đó được sử dụng làm đối số thực tế cho một intđối số chính thức. Nơi bạn nhận được khuyến mãi tự động đến int. Bạn có thể thay thế viết bước cuối cùng một cách rõ ràng, như int( UChar( c ) ), nhưng cá nhân tôi thấy điều đó quá dài dòng.

Chúc mừng & hth.,


0

Tôi đã gặp vấn đề khi chuyển đổi một mảng char như "7c7c7d7d7d7d7c7c7c7d7d7d7d7c7c7c7c7c7c7d7d7c7c7c7c7d7c7d7d7d7c7c2e2e2e"thành giá trị nguyên thực của nó có thể được biểu thị bằng `7C 'dưới dạng một giá trị thập lục phân. Vì vậy, sau khi bay để được giúp đỡ, tôi đã tạo ra cái này và nghĩ rằng nó sẽ rất tuyệt để chia sẻ.

Điều này phân tách chuỗi char thành các số nguyên bên phải của nó và có thể hữu ích cho nhiều người hơn là chỉ tôi;)

unsigned int* char2int(char *a, int len)
{
    int i,u;
    unsigned int *val = malloc(len*sizeof(unsigned long));

    for(i=0,u=0;i<len;i++){
        if(i%2==0){
            if(a[i] <= 57)
                val[u] = (a[i]-50)<<4;
            else
                val[u] = (a[i]-55)<<4;
        }
        else{
            if(a[i] <= 57)
                val[u] += (a[i]-50);
            else
                val[u] += (a[i]-55);
            u++;
        }
    }
    return val;
}

Hy vọng nó giúp!


Bạn đã bao giờ thử mã này chưa? Số 50 phải là số 48, số 55 chỉ hoạt động đối với các chữ cái ASCII viết hoa trong khi ví dụ của bạn chứa các chữ cái viết thường.
Roland Illig

0

Đối với char hoặc short to int, bạn chỉ cần gán giá trị.

char ch = 16;
int in = ch;

Tương tự như int64.

long long lo = ch;

Tất cả các giá trị sẽ là 16.


-1
int charToint(char a){
char *p = &a;
int k = atoi(p);
return k;
}

Bạn có thể sử dụng phương pháp atoi này để chuyển đổi char thành int. Để biết thêm thông tin, bạn có thể tham khảo http://www.cplusplus.com/reference/cstdlib/atoi/ , http://www.cplusplus.com/reference/opes/stoi/ .


1
Đây là hành vi không xác định. Lấy địa chỉ của một biến char sẽ cung cấp cho bạn một char * nhưng không phải là chuỗi C, đó là những gì atoi mong đợi.
luizfls
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.