คุณจะแปลงint
(จำนวนเต็ม) เป็นสตริงได้อย่างไร ฉันพยายามสร้างฟังก์ชั่นที่แปลงข้อมูลของ a struct
เป็นสตริงเพื่อบันทึกลงในไฟล์
int
เป็นตัวแทนของค่าของ ใช่ฉันรู้. มันเป็นทางลัดที่พบบ่อยมาก แต่ก็ยังบั๊กฉันอยู่
คุณจะแปลงint
(จำนวนเต็ม) เป็นสตริงได้อย่างไร ฉันพยายามสร้างฟังก์ชั่นที่แปลงข้อมูลของ a struct
เป็นสตริงเพื่อบันทึกลงในไฟล์
int
เป็นตัวแทนของค่าของ ใช่ฉันรู้. มันเป็นทางลัดที่พบบ่อยมาก แต่ก็ยังบั๊กฉันอยู่
คำตอบ:
แก้ไข: ตามที่ระบุไว้ในความคิดเห็นitoa()
ไม่ใช่มาตรฐานดังนั้นควรใช้ sprintf () วิธีที่แนะนำในคำตอบที่แข่งขันกัน!
คุณสามารถใช้itoa()
ฟังก์ชันเพื่อแปลงค่าจำนวนเต็มเป็นสตริง
นี่คือตัวอย่าง:
int num = 321;
char snum[5];
// convert 123 to string [buf]
itoa(num, snum, 10);
// print our string
printf("%s\n", snum);
หากคุณต้องการส่งออกโครงสร้างของคุณไปยังไฟล์ไม่จำเป็นต้องแปลงค่าใด ๆ ไว้ล่วงหน้า คุณสามารถใช้ข้อกำหนดรูปแบบการพิมพ์เพื่อระบุวิธีการส่งออกค่าของคุณและใช้ตัวดำเนินการใด ๆ จากตระกูล printfเพื่อส่งออกข้อมูลของคุณ
itoa
ไม่ได้มาตรฐาน - ดูเช่นstackoverflow.com/questions/190229/…
itoa()
ปัญหาบัฟเฟอร์ล้นเช่นgets()
เดียวกัน
คุณสามารถใช้sprintf
เพื่อทำมันหรือบางทีsnprintf
ถ้าคุณมี:
char str[ENOUGH];
sprintf(str, "%d", 42);
โดยที่จำนวนอักขระ (บวกอักขระยกเลิก) ในstr
สามารถคำนวณได้โดยใช้:
(int)((ceil(log10(num))+1)*sizeof(char))
ENOUGH
นั้นเพียงพอแล้วที่เราสามารถทำได้โดยmalloc(sizeof(char)*(int)log10(num))
(int)log10(42)
1
#define ENOUGH ((CHAR_BIT * sizeof(int) - 1) / 3 + 2)
int length = snprintf(NULL, 0,"%d",42);
เพื่อรับความยาวแล้วจัดสรรlength+1
อักขระสำหรับสตริง
คำตอบสั้น ๆ คือ:
snprintf( str, size, "%d", x );
อีกต่อไปคือ: ก่อนอื่นคุณต้องหาขนาดที่เพียงพอ snprintf
บอกความยาวของคุณถ้าคุณเรียกมันNULL, 0
ว่าเป็นพารามิเตอร์ตัวแรก:
snprintf( NULL, 0, "%d", x );
จัดสรรหนึ่งอักขระขึ้นไปสำหรับ null-terminator
#include <stdio.h>
#include <stdlib.h>
int x = -42;
int length = snprintf( NULL, 0, "%d", x );
char* str = malloc( length + 1 );
snprintf( str, length + 1, "%d", x );
...
free(str);
หากใช้ได้กับสตริงรูปแบบทุกรูปแบบดังนั้นคุณสามารถแปลง float หรือ double เป็น string โดยใช้"%g"
คุณสามารถแปลง int เป็น hex ได้โดยใช้"%x"
และต่อไป
หลังจากดูรุ่นต่างๆของ itoa สำหรับ gcc รุ่นที่ยืดหยุ่นที่สุดที่ฉันพบว่าสามารถจัดการการแปลงเป็นเลขฐานสองทศนิยมและเลขฐานสิบหกทั้งบวกและลบเป็นรุ่นที่สี่ที่พบที่http://www.strudel.org .uk / itoa / ในขณะที่sprintf
/ snprintf
มีข้อได้เปรียบพวกเขาจะไม่จัดการกับจำนวนลบสำหรับสิ่งอื่นใดนอกจากการแปลงทศนิยม เนื่องจากลิงค์ด้านบนเป็นแบบออฟไลน์หรือไม่ทำงานอีกต่อไปเราจึงรวมรุ่นที่ 4 ไว้ด้านล่าง:
/**
* C++ version 0.4 char* style "itoa":
* Written by Lukás Chmela
* Released under GPLv3.
*/
char* itoa(int value, char* result, int base) {
// check that the base if valid
if (base < 2 || base > 36) { *result = '\0'; return result; }
char* ptr = result, *ptr1 = result, tmp_char;
int tmp_value;
do {
tmp_value = value;
value /= base;
*ptr++ = "zyxwvutsrqponmlkjihgfedcba9876543210123456789abcdefghijklmnopqrstuvwxyz" [35 + (tmp_value - value * base)];
} while ( value );
// Apply negative sign
if (tmp_value < 0) *ptr++ = '-';
*ptr-- = '\0';
while(ptr1 < ptr) {
tmp_char = *ptr;
*ptr--= *ptr1;
*ptr1++ = tmp_char;
}
return result;
}
sprintf()
และ "สิ่งนี้เร็วกว่า sprintf มาก" อาจเป็นจริงในคอมไพเลอร์ของคุณ แต่ไม่ได้ถือไว้เสมอ คอมไพเลอร์อาจพิจารณาsprintf(str, "%d", 42);
และปรับให้เหมาะitoa()
กับฟังก์ชั่นที่ได้รับการปรับให้ดีที่สุด- เร็วกว่าผู้ใช้รายนี้อย่างแน่นอน รหัส.
sprintf(str, "%d", 42);
เมื่อผนวกสอง const const แต่นั่นคือทฤษฎี ในทางปฏิบัติผู้คนจะไม่วิ่งตามกันและ itoa ด้านบนนั้นเกือบจะได้รับการปรับให้เหมาะสมที่สุดเท่าที่จะทำได้ อย่างน้อยคุณก็มั่นใจได้ 100% ว่าคุณจะไม่ได้รับคำสั่งให้ลดขนาดของ sprintf ทั่วไป มันจะเป็นการดีถ้าได้เห็นตัวอย่างที่คุณมีอยู่ในใจด้วยเวอร์ชันคอมไพเลอร์และการตั้งค่า
นี่เก่า แต่นี่เป็นอีกวิธีหนึ่ง
#include <stdio.h>
#define atoa(x) #x
int main(int argc, char *argv[])
{
char *string = atoa(1234567890);
printf("%s\n", string);
return 0;
}
หากคุณใช้ GCC คุณสามารถใช้ฟังก์ชั่นส่วนขยาย GNU asprintf
char* str;
asprintf (&str, "%i", 12313);
free(str);
การแปลงทุกอย่างเป็นสตริงควร 1) จัดสรรสตริงผลลัพธ์หรือ 2) ส่งผ่านchar *
ปลายทางและขนาด โค้ดตัวอย่างด้านล่าง:
ทั้งการทำงานทั้งหมดรวมทั้งint
INT_MIN
พวกเขาให้ผลลัพธ์ที่สอดคล้องsnprintf()
ซึ่งไม่เหมือนที่ขึ้นอยู่กับสถานที่
วิธีที่ 1: ส่งคืนNULL
เมื่อหน่วยความจำไม่เพียงพอ
#define INT_DECIMAL_STRING_SIZE(int_type) ((CHAR_BIT*sizeof(int_type)-1)*10/33+3)
char *int_to_string_alloc(int x) {
int i = x;
char buf[INT_DECIMAL_STRING_SIZE(int)];
char *p = &buf[sizeof buf - 1];
*p = '\0';
if (i >= 0) {
i = -i;
}
do {
p--;
*p = (char) ('0' - i % 10);
i /= 10;
} while (i);
if (x < 0) {
p--;
*p = '-';
}
size_t len = (size_t) (&buf[sizeof buf] - p);
char *s = malloc(len);
if (s) {
memcpy(s, p, len);
}
return s;
}
วิธีที่ 2: ส่งคืนNULL
ถ้าบัฟเฟอร์มีขนาดเล็กเกินไป
static char *int_to_string_helper(char *dest, size_t n, int x) {
if (n == 0) {
return NULL;
}
if (x <= -10) {
dest = int_to_string_helper(dest, n - 1, x / 10);
if (dest == NULL) return NULL;
}
*dest = (char) ('0' - x % 10);
return dest + 1;
}
char *int_to_string(char *dest, size_t n, int x) {
char *p = dest;
if (n == 0) {
return NULL;
}
n--;
if (x < 0) {
if (n == 0) return NULL;
n--;
*p++ = '-';
} else {
x = -x;
}
p = int_to_string_helper(p, n, x);
if (p == NULL) return NULL;
*p = 0;
return dest;
}
[แก้ไข] ตามคำขอโดย @Alter Mann
(CHAR_BIT*sizeof(int_type)-1)*10/33+3
อย่างน้อยจำนวนสูงสุดที่char
จำเป็นในการเข้ารหัสชนิดจำนวนเต็มที่ลงนามแล้วบางส่วนเป็นสตริงที่ประกอบด้วยเครื่องหมายลบตัวเลือกตัวเลขและอักขระ null
CHAR_BIT*sizeof(int_type)-1
จำนวนบิตที่ไม่เข้าสู่ระบบจำนวนเต็มลงนามคือไม่เกิน การแสดงพื้นฐาน -10 ของn
เลขฐานสอง -bit นั้นใช้n*log10(2) + 1
ตัวเลขได้สูงสุด เป็นมากกว่าเล็กน้อย10/33
log10(2)
+1 สำหรับเครื่องหมายchar
และ +1 สำหรับอักขระ null เศษส่วนอื่น ๆ สามารถใช้ได้เช่น 28/93
วิธีที่ 3: ถ้าใครต้องการที่จะมีชีวิตอยู่บนขอบและ Buffer overflow ไม่กังวลเป็น C99 ง่ายหรือวิธีการแก้ปัญหาในภายหลังต่อไปนี้ซึ่งจับทั้งหมด int
#include <limits.h>
#include <stdio.h>
static char *itoa_simple_helper(char *dest, int i) {
if (i <= -10) {
dest = itoa_simple_helper(dest, i/10);
}
*dest++ = '0' - i%10;
return dest;
}
char *itoa_simple(char *dest, int i) {
char *s = dest;
if (i < 0) {
*s++ = '-';
} else {
i = -i;
}
*itoa_simple_helper(s, i) = '\0';
return dest;
}
int main() {
char s[100];
puts(itoa_simple(s, 0));
puts(itoa_simple(s, 1));
puts(itoa_simple(s, -1));
puts(itoa_simple(s, 12345));
puts(itoa_simple(s, INT_MAX-1));
puts(itoa_simple(s, INT_MAX));
puts(itoa_simple(s, INT_MIN+1));
puts(itoa_simple(s, INT_MIN));
}
ตัวอย่างผลลัพธ์
0
1
-1
12345
2147483646
2147483647
-2147483647
-2147483648
/*Function return size of string and convert signed *
*integer to ascii value and store them in array of *
*character with NULL at the end of the array */
int itoa(int value,char *ptr)
{
int count=0,temp;
if(ptr==NULL)
return 0;
if(value==0)
{
*ptr='0';
return 1;
}
if(value<0)
{
value*=(-1);
*ptr++='-';
count++;
}
for(temp=value;temp>0;temp/=10,ptr++);
*ptr='\0';
for(temp=value;temp>0;temp/=10)
{
*--ptr=temp%10+'0';
count++;
}
return count;
}
หากคุณต้องการส่งออกโครงสร้างของคุณไปยังไฟล์ไม่จำเป็นต้องแปลงค่าใด ๆ ไว้ล่วงหน้า คุณสามารถใช้ข้อกำหนดรูปแบบการพิมพ์เพื่อระบุวิธีการส่งออกค่าของคุณและใช้ตัวดำเนินการใด ๆ จากตระกูล printf เพื่อส่งออกข้อมูลของคุณ
ใช้ฟังก์ชันitoa()
เพื่อแปลงจำนวนเต็มเป็นสตริง
ตัวอย่างเช่น:
char msg[30];
int num = 10;
itoa(num,msg,10);
printf
หรือหนึ่งในลูกพี่ลูกน้องของมันควรทำเคล็ดลับ