Chuyển một chữ số ký tự thành số nguyên tương ứng trong C


103

Có cách nào để chuyển đổi một ký tự thành một số nguyên trong C không?

Ví dụ, từ '5'đến 5?

Câu trả lời:


147

Theo các câu trả lời khác, điều này ổn:

char c = '5';
int x = c - '0';

Ngoài ra, để kiểm tra lỗi, trước tiên bạn có thể kiểm tra isdigit (c) là đúng. Lưu ý rằng bạn không thể hoàn toàn di động làm tương tự cho các chữ cái, ví dụ:

char c = 'b';
int x = c - 'a'; // x is now not necessarily 1

Tiêu chuẩn đảm bảo rằng các giá trị char cho các chữ số từ '0' đến '9' là liền nhau, nhưng không đảm bảo cho các ký tự khác như các chữ cái trong bảng chữ cái.


3
@Paul Tomblin: Có đối với các chữ số không phải chữ cái, bởi vì, như tôi đã nói trong câu trả lời, tiêu chuẩn đảm bảo '0' đến '9' là liền nhau nhưng không đảm bảo như vậy cho các ký tự khác như 'a' thành 'z'.
Chris Young

char c = 'b'; int x = c - 'a'; thì x sẽ là 1 duy nhất trong ASCII?
Pan

@Pan Trong bất kỳ mã hóa nào, kể cả ASCII, có 'b' 1 nhiều hơn 'a'. Điều này vẫn đúng trong EBCDIC, tuy nhiên nó làm cho ('j' - 'i') == 8.
Chris Young

@ChrisYoung Tại sao? Nguyên nhân trong EBCDIC, 'j' không nhiều hơn 'i' 1?
Pan

2
Tôi còn thiếu gì ở đây khi atoi không được sử dụng?
Daniel

41

Trừ '0' như thế này:

int i = c - '0';

Tiêu chuẩn C đảm bảo mỗi chữ số trong phạm vi '0'..'9'lớn hơn một chữ số trước đó (trong phần 5.2.1/3của dự thảo C99 ). Số lượng tương tự đối với C ++.


1
Câu trả lời này sẽ tốt hơn nếu bạn đề cập rằng một ký tự là / đã / thực sự là một số nguyên, ký hiệu được xác định bằng ký hiệu được triển khai (nghĩa là có thể có dấu hoặc không dấu) và dài CHAR_BITS.
Arafangion

tôi không chắc biết điều đó có thực sự giúp ích cho anh ấy. nhưng Chris đã có một điểm tốt với a..z không nhất thiết phải liền kề. thay vào đó tôi nên đề cập đến điều đó. bây giờ anh ấy đã thắng cuộc đua :)
Johannes Schaub - litb

1
Tuy nhiên, của bạn thì tốt hơn vì bạn đã đủ điều kiện trả lời - Chris rất có thể đã hoàn thành nội dung của mình. :)
Arafangion

Cảm ơn vì sự đánh giá cao. tôi thừa nhận rằng tôi không chắc chắn về trạng thái của C. vì vậy tôi đã tìm kiếm và 'vì tôi đã ở đó nên tôi đã dán tham chiếu vào câu trả lời :)
Johannes Schaub - litb

Và đó, thưa ông, đó là lý do tại sao ông hơn tôi vài điểm. :)
Arafangion

29

Nếu do một sự trùng hợp ngẫu nhiên nào đó, bạn muốn chuyển đổi một chuỗi ký tự thành một số nguyên, bạn cũng có thể làm điều đó!

char *num = "1024";
int val = atoi(num); // atoi = ASCII TO Int

valbây giờ là 1024. Rõ ràng atoi()là ổn, và những gì tôi đã nói về nó trước đó chỉ áp dụng cho tôi (trên OS X (có thể (chèn trò đùa Lisp vào đây))). Tôi đã nghe nói rằng đó là một macro ánh xạ gần đúng đến ví dụ tiếp theo, sử dụng strtol(), một chức năng có mục đích chung hơn, để thực hiện chuyển đổi thay thế:

char *num = "1024";
int val = (int)strtol(num, (char **)NULL, 10); // strtol = STRing TO Long

strtol() hoạt động như thế này:

long strtol(const char *str, char **endptr, int base);

Nó chuyển đổi *strthành a long, coi nó như thể nó là một basesố cơ sở . Nếu **endptrkhông phải là null, nó chứa ký tự không phải chữ số đầu tiên strtol()được tìm thấy (nhưng ai quan tâm đến điều đó).


Không có vấn đề về luồng nào với atoi (nó không có dữ liệu tĩnh) và nó không bị phản đối. Trong thực tế, nó có chức năng tương đương với: #define atoi (x) (int) (strtol ((x), NULL, 10)
Evan Teran

5
Vấn đề với atoi là nó sử dụng 0 làm giá trị "không thể tìm thấy số ở đây", vì vậy atoi ("0") và atoi ("một") đều trả về 0. Nếu điều đó không hiệu quả với những gì bạn ' đang sử dụng nó cho, hãy tìm strtol () hoặc sscanf ().
David Thornley

Tất nhiên, lợi thế khác của strtol là bạn cũng có thể cần đọc những thứ khác từ cùng một chuỗi đứng sau số.
dfeuer

@EvanTeran Thật không may nếu bạn chạy Visual Studio, bạn sẽ nhận được cảnh báo khấu hao (và sẽ không biên dịch mà không bị vô hiệu hóa). VS bây giờ khuyến nghị itoa_s().
Simon

7

Trừ char '0' hoặc int 48 như thế này:

char c = '5';
int i = c - '0';

Giải thích: Bên trong nó hoạt động với giá trị ASCII . Từ bảng ASCII, giá trị thập phân của ký tự 5 là 530 là 48 . Vậy 53 - 48 = 5

HOẶC LÀ

char c = '5';
int i = c - 48; // Because decimal value of char '0' is 48

Điều đó có nghĩa là nếu bạn trừ 48 từ bất kỳ ký tự số nào, nó sẽ tự động chuyển đổi thành số nguyên.


6
char numeralChar = '4';
int numeral = (int) (numeralChar - '0');

numeralChar - '0'đã là loại int, vì vậy bạn không cần diễn viên. Ngay cả khi nó không phải, diễn viên là không cần thiết.
Alok Singhal

Hả, đúng vậy sẽ ép buộc phải không? Có lẽ Java đã tô màu cho nhận thức của tôi. Hoặc có thể tôi hoàn toàn nhầm lẫn và nó thậm chí sẽ ép buộc trong Java. :)
Kevin Conner

5

Để chuyển đổi chữ số ký tự thành số nguyên tương ứng. Làm như hình bên dưới:

char c = '8';                    
int i = c - '0';

Logic đằng sau phép tính trên là sử dụng các giá trị ASCII. Giá trị ASCII của ký tự 8 là 56, giá trị ASCII của ký tự 0 là 48. Giá trị ASCII của số nguyên 8 là 8.

Nếu chúng ta trừ hai ký tự, phép trừ sẽ xảy ra giữa ASCII của các ký tự.

int i = 56 - 48;   
i = 8;

Tại sao tôi là người duy nhất ủng hộ điều này? Lời giải thích rất đơn giản và đầy đủ thông tin: +1:
Brandon Benefield

0

Nếu đó chỉ là một ký tự đơn 0-9 trong ASCII, thì việc trừ giá trị của ký tự 0 ASCII khỏi giá trị ASCII sẽ hoạt động tốt.

Nếu bạn muốn chuyển đổi các số lớn hơn thì thao tác sau sẽ thực hiện:

char *string = "24";

int value;

int assigned = sscanf(string, "%d", &value);

** đừng quên kiểm tra trạng thái (phải là 1 nếu nó hoạt động trong trường hợp trên).

Paul.


0
char chVal = '5';
char chIndex;

if ((chVal >= '0') && (chVal <= '9')) {

    chIndex = chVal - '0';
}
else 
if ((chVal >= 'a') && (chVal <= 'z')) {

    chIndex = chVal - 'a';
}
else 
if ((chVal >= 'A') && (chVal <= 'Z')) {

    chIndex = chVal - 'A';
}
else {
    chIndex = -1; // Error value !!!
}

0

Khi tôi cần làm điều gì đó như thế này, tôi bắt đầu một mảng với các giá trị tôi muốn.

const static int lookup[256] = { -1, ..., 0,1,2,3,4,5,6,7,8,9, .... };

Sau đó, chuyển đổi dễ dàng

int digit_to_int( unsigned char c ) { return lookup[ static_cast<int>(c) ]; }

Về cơ bản đây là cách tiếp cận được thực hiện bởi nhiều triển khai của thư viện ctype. Bạn cũng có thể điều chỉnh điều này để làm việc với các chữ số hex.


Điều đó dường như cực kỳ không hiệu quả để chuyển đổi một chữ số thập phân (hoặc bát phân). Nếu phần có liên quan của bảng tra cứu của bạn không nằm trong bộ nhớ cache L1, bạn sẽ thực hiện một loạt các chu kỳ để kéo nó vào chỉ để nhận được một giá trị. Thành thật mà nói, tôi có xu hướng nghi ngờ đây thậm chí là một ý tưởng hay nếu bạn đang chuyển đổi toàn bộ một loạt các chữ số, nhưng bạn phải đo lường điều đó. Tất nhiên, nó cạnh tranh hơn nhiều đối với hex.
dfeuer

0

Kiểm tra điều này,

char s='A';

int i = (s<='9')?(s-'0'):(s<='F')?((s-'A')+10):((s-'a')+10);

chỉ 0,1,2, ...., E, F.


0

Chỉ cần sử dụng atol()chức năng:

#include <stdio.h>
#include <stdlib.h>

int main() 
{
    const char *c = "5";
    int d = atol(c);
    printf("%d\n", d);

}

0

Nếu chữ số của bạn là, chẳng hạn, '5'trong ASCII, nó được biểu diễn dưới dạng số nhị phân 0011 0101(53). Mọi chữ số đều có 4 bit cao nhất và 4 bit 0011thấp nhất đại diện cho chữ số trong bcd. Vì vậy, bạn chỉ cần làm

char cdig = '5';
int dig = cdig & 0xf; // dig contains the number 5

để lấy 4 bit thấp nhất, hoặc chữ số tương tự. Trong asm, nó sử dụng andphép toán thay vì sub(như trong các câu trả lời khác).


'5'là 53 ( 00110101)
eyllanesc

@eyllanesc Lúc đầu, nó là một 4. Cảm ơn. Đã chỉnh sửa nó.
Garmekain

0

Dưới đây là các hàm trợ giúp cho phép chuyển đổi chữ số trong char thành int và ngược lại:

int toInt(char c) {
    return c - '0';
}

char toChar(int i) {
    return i + '0';
}

-2

sử dụng hàm: atoi cho mảng thành số nguyên, atof cho mảng thành kiểu float; hoặc là

char c = '5';
int b = c - 48;
printf("%d", b);

Một số câu trả lời đã bao gồm điều này. Điều này không thêm gì mà họ đã không đề cập đến.
ShadowRanger

-3

Bạn sẽ truyền nó thành một int (hoặc float hoặc double hoặc những gì bạn muốn làm với nó) và lưu trữ nó trong biến anoter.

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.