c语言修改字符串c2133,通过create_string_buffer、create_unicode_buffer让C语言具备修改字符串的能力...
字符串的修改
我們知道C中不存在字符串這個概念,python中的字符串在C中也是通過字符數組來實現的。我們說在C中創建一個字符數組有兩種方式:
char *s1 = "hello world";
char s2[] = "hello world";
這兩種方式雖然打印的結果是一樣的,并且s1、s2都指向了對應字符數組的首地址,但是內部的結構確是不同的。
1.char *s1 = "hello world";此時這個字符數組是存放在靜態存儲區里面的,程序編譯的時候這塊區域就已經確定好了,靜態存儲區在程序的整個運行期間都是存在的,主要用來存放一些靜態變量、全局變量、常量。因此s1只能夠訪問這個字符數組,卻不能夠改變它,因為它是一個常量。而char s2[] = "hello world";,這種方式創建的字符數組是存放在棧當中的,可以通過s2這個指針去修改它。
2.char *s1 = "hello world";是在編譯的時候就已經確定了,因為是一個常量。而char s2[] = "hello world";則是在運行時才確定。
3.char *s1 = "hello world";創建的字符數組存于靜態存儲區,char s2[] = "hello world";創建的字符數組存儲于棧區,所以s1訪問的速度沒有s2快。
所以我們說char?*s這種方式創建的字符數組在C中是不能修改的,但是我們通過ctypes卻可以做到對char?*s進行修改:
#include
int test(char *s1, char s2[6])
{
//兩種方式都進行修改
s1[0] = 'a';
s2[0] = 'a';
printf("s1 = %s, s2 = %s\n", s1, s2);
}
我們還是將C文件編譯成mmp.dll
import ctypes
from ctypes import *
lib = ctypes.CDLL("./mmp.dll")
# 我們看到無論是char *s1,還是char s2[...],我們都可以使用c_char_p這種方式傳遞
lib.test(c_char_p(b"hello"), c_char_p(b"hello")) # s1 = aello, s2 = aello
我們看到兩種方式都成功修改了,但是即便能修改,我們不建議這么做。不是說不讓修改,而是應該換一種方式。如果是需要修改的話,那么不要使用c_char_p的方式來傳遞,而是建議通過create_string_buffer來給C語言傳遞可以修改字符的空間。
create_string_buffer
create_string_buffer是ctypes提供的一個函數,表示創建具有一定大小的字符緩存,就理解為字符數組即可。
from ctypes import *
# 傳入一個int,表示創建一個具有固定大小的字符緩存,這里是10個
s = create_string_buffer(10)
# 直接打印就是一個對象
print(s) #
# 也可以調用value方法打印它的值,可以看到什么都沒有
print(s.value) # b''
# 并且它還有一個raw方法,表示C語言中的字符數組,由于長度為10,并且沒有內容,所以全部是\x00,就是C語言中的\0
print(s.raw) # b'\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
# 還可以查看長度
print(len(s)) # 10
當然create_string_buffer如果只傳一個int,那么表示創建對應長度的字符緩存。除此之外,還可以指定字節串,此時的字符緩存大小和指定的字節串大小是一致的:
from ctypes import *
# 此時我們直接創建了一個字符緩存
s = create_string_buffer(b"hello")
print(s) #
print(s.value) # b'hello'
# 我們知道在C中,字符數組是以\0作為結束標記的,所以結尾會有一個\0,因為raw表示C中的字符數組
print(s.raw) # b'hello\x00'
# 長度為6,b"hello"五個字符再加上\0一共6個
print(len(s))
當然create_string_buffer還可以指定字節串的同時,指定空間大小。
from ctypes import *
# 此時我們直接創建了一個字符緩存,如果不指定容量,那么默認和對應的字符數組大小一致
# 但是我們還可以同時指定容量,記得容量要比前面的字節串的長度要大。
s = create_string_buffer(b"hello", 10)
print(s) #
print(s.value) # b'hello'
# 長度為10,剩余的5個顯然是\0
print(s.raw) # b'hello\x00\x00\x00\x00\x00'
print(len(s)) # 10
下面我們來看看如何使用create_string_buffer來傳遞:
#include
int test(char *s)
{
//變量的形式依舊是char *s
//下面的操作就是相當于把字符數組的索引為5到11的部分換成" satori"
s[5] = ' ';
s[6] = 's';
s[7] = 'a';
s[8] = 't';
s[9] = 'o';
s[10] = 'r';
s[11] = 'i';
printf("s = %s\n", s);
}
from ctypes import *
lib = CDLL("./mmp.dll")
s = create_string_buffer(b"hello", 20)
lib.test(s) # s = hello satori
此時就成功地修改了,我們這里的b"hello"占五個字節,下一個正好是索引為5的地方,然后把索引為5到11的部分換成對應的字符。但是需要注意的是,一定要小心\0,我們知道C語言中一旦遇到了\0就表示這個字符數組結束了。
from ctypes import *
lib = CDLL("./mmp.dll")
# 這里把"hello"換成"hell",看看會發生什么
s = create_string_buffer(b"hell", 20)
lib.test(s) # s = hell
# 我們看到這里只打印了"hell",這是為什么?
# 我們看一下這個s
print(s.raw) # b'hell\x00 satori\x00\x00\x00\x00\x00\x00\x00\x00'
# 我們看到這個create_string_buffer返回的對象是可變的,在將s傳進去之后被修改了
# 如果沒有傳遞的話,我們知道它是長這樣的。
"""
b'hell\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
hell的后面全部是C語言中的\0
修改之后變成了這樣
b'hell\x00 satori\x00\x00\x00\x00\x00\x00\x00\x00'
我們看到確實是把索引為5到11(包含11)的部分變成了"satori"
但是我們知道C語言中掃描字符數組的時候一旦遇到了\0,就表示結束了,而hell后面就是\0,
因為即便后面還有內容也不會輸出了,所以直接就只打印了hell
"""
另外除了create_string_buffer之外,還有一個create_unicode_buffer,針對于wchar_t,用法和create_string_buffer一樣。
C語言中查看字符數組的長度
C語言中如何查看字符數組的長度呢?有兩種方法,一種是通過sizeof,一種是通過strlen。話說我說這個干什么?算了,不管了。
#include
#include
int main() {
char s[] = "hello world";
//C語言中查看字符串的長度可以使用strlen,這個需要導入string.h頭文件。strlen計算的就是字符的個數,不包括\0
//使用sizeof計算的結果是包含\0的,所以會比strlen計算的結果多1
printf("%d %d\n", strlen(s), sizeof(s) / sizeof(s[0])); // 11 12
return 0;
}
但是我們發現字符數組的創建方式是通過char s[]這種形式,如果是char?*s呢?
#include
#include
int main() {
char *s = "hello world";
printf("%d %d\n", strlen(s), sizeof(s) / sizeof(s[0])); // 11 8
return 0;
}
我們看到使用strlen計算的結果是一樣的,但是使用sizeof得到的結果卻是不一樣的。因為char?*s,這個s我們雖然可以使用它來打印字符數組,但它本質上是一個指針,一個指針在64位機器上占8個字節,所以結果是8。而char?s[]中的s雖然也指向字符數組的首地址,但它本質上是一個數組名,我們使用sizeof查看得到的結果還是字符數組中所有元素的總大小。
艾瑪,你扯到C上面干啥。。。。。。你又不會C。。。。。。
來源:https://www.cnblogs.com/traditional/p/12238984.html
總結
以上是生活随笔為你收集整理的c语言修改字符串c2133,通过create_string_buffer、create_unicode_buffer让C语言具备修改字符串的能力...的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: c++ 访问控制与封装
- 下一篇: pdf从结构新建书签_强力推荐一款PDF