c語言深度剖析(31)—字符串典型問題分析

1.典型問題一

  • 下面的程序輸出什麼?爲什麼?
#include <stdio.h>

int main()
{
	char buf[10] = { 0 };
	char src[] = "hello %s";

	snprintf(buf, sizeof(buf), src);

	printf("buf = %s\n", buf);

	return 0;
}
  • 運行結果:
  • 輸出不符合我們的預期,我們預期輸出hello  %s。
  • 分析 :
  • snprintf函數本身是可變參數函數,原型:int snprintf(char* buffer, int buf_size, const char* fomart, ...) 
  • 當函數只有3個參數時,如果第三個參數沒有包含格式化信息,函數調用沒有問題;相反,如果第三個參數包含了格式 化信息,但缺少後續對應參數,則程序行爲不確定。格式化信息必須與變參個數相匹配 
  • 上面代碼修改如下:
#include <stdio.h>
#include <string.h>

int main()
{
    char buf[12] = {0};
    char src[] = "hello %s";

    snprintf(buf, sizeof(buf), src, "world");   
    printf("buf = %s\n", buf);

    return 0;
}
  • 運行結果:

2.典型問題二

  • 下面的程序輸出什麼?爲什麼?
#include <stdio.h>
#include <string.h>

int main()
{
#define STR "Hello, \0D.T.Software\0"

	char *src = STR;
	char buf[255] = { 0 };

	snprintf(buf, sizeof(buf), src);

	printf("strlen(STR) = %d\n", strlen(STR));  // 7
	printf("sizeof(STR) = %d\n", sizeof(STR));  // 22,即便是\0結尾也會編譯器也會再加上\0

	printf("strlen(src) = %d\n", strlen(src));  // 7
	printf("sizeof(src) = %d\n", sizeof(src));  // 8

	printf("strlen(buf) = %d\n", strlen(buf));  // 7  
	printf("sizeof(buf) = %d\n", sizeof(buf));  // 255

	printf("src = %s\n", src);
	printf("buf = %s\n", buf);

	return 0;
}
  • 運行結果:
  • 分析:
    • 字符串相關的函數均以第—個出現的 '\0'作爲結束符 
    • 編譯器總是會在字符串字面量的未尾添加'\0' 
    • 字符串字面量的本質爲數組
    • 字符串、字符數組、字符指針本質是不同的,但是它們之間有一定的關係。
    • 字符串是一個特殊的字符數組,字符指針可以指向一個字符數組。因此,可以說字符指針可以指向一個字符串。

3.典型問題三 

  • 下面的程序輸出什麼?爲什麼?    

  • S1==S2本質上是想將兩個字符數組做比較,字符串字面量的本質就是字符數組,S1和S2在值上是相等的兩個字符數組,但它們在地址中可能佔用兩片不同的區域,因此,S1、S2(代表字符數組的首地址)可能不相等。
#include <stdio.h>
#include <string.h>

#define S1 "D.TSoftware"
#define S2 "D.TSoftware"

int main()
{
	if (S1 == S2)
	{
		printf("Equal\n");
	}
	else
	{
		printf("Non Equal\n");
	}

	if (0 == strcmp(S1, S2))
	{
		printf("Equal\n");
	}
	else
	{
		printf("Non Equal\n");
	}

	return 0;
}
  • 運行結果:
  • 第一個輸出與我們的分析有出入,這是爲什麼呢?
  • 這是編譯器的優化,S1和S2代表了同一片內存。編譯器先定義S1代表的字符串,然後開始定義S2,當編譯器發現S2代表的字符串已經定義了,於是直接讓S2代表了S1這片內存。
  • bcc32的編譯輸出結果如下:

        

  • 總結: 
  • 字符串之間的相等比較需要用strcmp完成,不可直接用 == 進行字符串直接比較; 
  • 完全相同的字符串字面量的 == 比較結果往往爲false,一些現代編譯器能夠將相同的字符串字面量映射到同一個無名字符數組,因此 == 比較結果爲 true。 
  • 注意:不編寫依賴特殊編譯器的代碼,因此字符串之間的相等比較用strcmp

4.典型問題四 

  • 字符串循環右移

 

  • 關鍵點在於計算出循環右移後字符的下標變化規律。求出變化公式。
#include <stdio.h>
#include <string.h>

void right_shift_r(const char *src, char *result, unsigned int n)
{
    const unsigned int LEN = strlen(src);
    int i = 0;
        
    for(i=0; i < LEN; i++)
    {
        result[(n + i) % LEN] = src[i];
    }
    
    result[LEN] = '\0';
}

int main()
{
    char result[255] = {0};
    
    right_shift_r("abcde", result, 2);
    
    printf("%s\n", result);
    
    right_shift_r("abcde", result, 5);
    
    printf("%s\n", result);
    
    right_shift_r("abcde", result, 8);
    
    printf("%s\n", result);
    
    return 0;
}
  • 運行結果:
  • 只遍歷了一次字符串,就將結果計算出來了,因此,效率是最高的。複雜度是O(n)。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章