讀古今文學網 > C語言解惑 > 8.3 對庫函數的作用理解不對 >

8.3 對庫函數的作用理解不對

【例8.4】下面程序中將姓和名分別輸出在兩行,改正這個錯誤。


#include <stdio.h>
#include <string.h>
int main
( 
)
{
      char first_name[100]
;
      char last_name[100]
;
      char full_name[100]
;
      printf
(\"First name
: \"
);
      fgets
(first_name
,sizeof
(first_name
),stdin
);
      printf
(\"Last name
: \"
);
      fgets
(last_name
,sizeof
(last_name
),stdin
);
      strcpy
(full_name
, \" \"
);
      strcpy
(full_name
,first_name
);
      strcat
(full_name
,last_name
);
      printf
(\"Full name
: %s\"
,full_name
);
      return 0
;
}
  

【解答】下面是程序的運行示範:


First name
: Wang
Last name
: Guoying
Full_name
: Wang
Guoying
  

庫函數fgets在讀取字符時,會自動在尾部加入「n」。用strcat函數連接兩個字符串時,中間就多了一個換行符。解決的辦法就是將「n」換成空格。用strlen函數求出「n」的位置,這個位置的數組下標就是字符串長度-1。下面的程序將這個換行符換成空格。


#include <stdio.h>
#include <string.h>
int main
( 
)
{
       char first_name[100]
;
       char last_name[100]
;
       char full_name[100]
;
       int i=0
;
       printf
(\"First name
: \"
);
       fgets
(first_name
,sizeof
(first_name
),stdin
);
       printf
(\"Last name
: \"
);
       fgets
(last_name
,sizeof
(last_name
),stdin
);
       strcpy
(full_name
, \" \"
);
       strcpy
(full_name
,first_name
);
       i=strlen
(first_name
)-1
;
       strcat
(full_name
,last_name
);
       full_name[i]=\' \'
;
       printf
(\"Full name
: %s\"
,full_name
);
       return 0
;
}
  

運行示範如下:


First name
: Wang
Last name
: Guoying
Full_name
: Wang Guoying
  

當然,也可以先處理換行符,即把換行符改為空格,然後再連接。


//
先處理換行符再連接字符串的程序
#include <stdio.h>
#include <string.h>
int main
( 
)
{
       char first_name[100]
;
       char last_name[100]
;
       char full_name[100]
;
       int i=0
;
       printf
(\"First name
: \"
);
       fgets
(first_name
,sizeof
(first_name
),stdin
);
       printf
(\"Last name
: \"
);
       fgets
(last_name
,sizeof
(last_name
),stdin
);
       strcpy
(full_name
, \" \"
);
       strcpy
(full_name
,first_name
);
       i=strlen
(first_name
)-1
;
       full_name[i]=\' \'
;                       //
先處理換行符再連接字符串
       strcat
(full_name
,last_name
);
       printf
(\"Full name
: %s\"
,full_name
);
       return 0
;
}
  

【例8.5】分析下面程序中存在的錯誤。


#include <stdio.h>
#include <string.h>
int main
( void 
)
{
     char string[80]
;
     strcpy
( string
, \"Hello world\0\" 
);
     return 0
;
}
  

【解答】庫函數strcpy的原型為


char *strcpy
( char *strDestination
, const char *strSource 
);
  

它將strSource指向的字符串(包含結束標誌)拷貝到strDestination指向的字符數組中。所以程序中多了結束符號「\0」。當然結果是一樣的,但說明程序編寫者對該函數的理解不夠。於此類似的還有strcat函數。它的函數原型為


char *strcat
( char *strDestination
, const char *strSource 
);
  

它將strSource指向的字符串連接到strDestination指向的字符數組的後面,連接規則為:假定原來的數組有足夠的空間存儲連接後的字符串,被連接字符串覆蓋原字符串最後的空白終止符,用自己的結束符作為新字符串的結束符,例8.6說明了它的用法。

【例8.6】下面程序很簡單,雖然編譯給出錯誤信息,也能產生執行文件,但運行時出現錯誤。找出原因並修改運行程序。


#include <stdio.h>
#include <string.h>
const char PATH=\"d
:/user/my\"
;
char *full_name
( char 
);
int main
( 
)
{
         printf
(\"Full name is
: %sn\"
,full_name
(\"data\"
));
         return 0
;
 }
 char *full_name
(const char name
)
 {
        char file_name[100]
;
        strcpy
(file_name
,PATH
);
        strcat
(file_name
,\'/\'
);
        strcat
(file_name
,name
);
        return 
(file_name
);
 }
  

【解答】這個程序不長,問題也不少。const定義的是字符,但確賦給字符串。正確的是定義為


const char PATH=\"d
:/user/my\"
;
  

雖然也可以使用如下的


#define PATH \"d
:/user/my\"
  

宏定義方式,但推薦使用const。

函數聲明與定義不符合,定義使用const,聲明也必須相同。即


char *full_name
(const char 
);
  

對庫函數strcat的使用不對,\'/\'是字符,strcat要求的是字符串。應改為


strcat
(file_name
,\"/\"
);
  

full_name函數里定義的普通字符數組file_name在結束運行時就失去作用,必須將它定義為靜態數組。下面是修改後的程序。


#include <stdio.h>
#include <string.h>
const char PATH=\"d
:/user/my\"
;
char *full_name
(const char 
);
int main
( 
)
{
        printf
(\"Full name is
: %sn\"
,full_name
(\"data\"
));
        return 0
;
}
char *full_name
(const char name
)
{
        static  char file_name[100]
;
        strcpy
(file_name
,PATH
);
        strcat
(file_name
,\"/\"
);
        strcat
(file_name
,name
);
        return 
(file_name
);
}
  

程序運行結果為


Full name is
: d
:/user/my/data
  

【例8.7】分析下面程序中存在的錯誤。


#include <stdio.h>
#include <string.h>
void main
( void 
)
{
   char string[80]
;
   char str2=\"strcat
!\" 
;
   strcpy
( string
, \"Hello world from \" 
);
   strcat
( string
, \"strcpy \" 
);
   strcat
( string
, \"and \" 
);
   strcat
( string
, str2 
);
   printf
(\"
字符串%s
的長度為%d
。n\"
,string
,strlen
(string
)+1
);
   strcpy
( string
, str2 
);
   printf
(\"
字符串%s
的長度為%d
。n\"
,string
,strlen
(string
)+1
);
   return 
;
}
  

【解答】strlen的函數原型為


size_t strlen
( const char *string 
);
  

size_t是unsigned integer,即strlen函數返回字串的長度(字符串的個數),這個長度不包含字符串的結束標誌\'\0\',也就是不是存儲字符串的長度。將兩個輸出語句中的「+1」去掉即可。例如:


printf
(\"
字符串%s
的長度為%d
。n\"
,string
,strlen
(string
));
  

修改後的運行結果如下。


字符串Hello world from strcpy and strcat
!的長度為35
。
字符串strcat
!的長度為7
。
  

結論:必須正確理解庫函數的原型。