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