閱讀,並與線導向功能寫作很容易,獲取用戶輸入scanf函數經常被使用。
困難的部分是做了足夠的錯誤檢查,其中大部分遺漏,直到爲時已晚。
這是一個很好的但並不完美的例子,使用最佳實踐。總是有更好和更有效的方式,但與此開始做這項工作,讓您和C.好
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define BUFFER_SIZE 512
static void searchAndReplace(char* original_file,char* destination_file,char *searchString,char *replacementString){
FILE* original = NULL;
FILE* modified = NULL;
char origLine[BUFFER_SIZE]; //buffer, assuming the longest line will be BUFFER_SIZE -1 characters, being the null terminator the last one
size_t searchStringLength = strlen(searchString);//length without terminating NULL.
memset(origLine,0,BUFFER_SIZE);// filling with nulls just in case
original = fopen(original_file,"r");
if(!original){
printf("Error opening file for reading : %s \n",original_file);
perror("Cause of Error");
exit(2);
}
modified = fopen(destination_file,"w+");
if(!modified){
printf("Error opening file for writing: %s \n",destination_file);
perror("Cause of Error");
exit(2);
}
while(NULL != (fgets(origLine,BUFFER_SIZE,original))){
char* searchStringPos=NULL;
/*it begins to concatenate at the beginning of the string, next position is strlen(searchString) from the last
searchString pointer position*/
char* lastConcatPos = origLine;
if(feof(original) != 0){
break;
}
while ((searchStringPos = strstr(lastConcatPos,searchString)) != NULL){
/* offset between position where searchStringPos was found and the last position being concantenated */
char tempBuffer[BUFFER_SIZE];
size_t sizeToConcatenate = (size_t)(searchStringPos - lastConcatPos);
/* if searchString was located at the beginning of the line or right after the last occurrence do nothing */
if(sizeToConcatenate >0){
strncpy(tempBuffer,lastConcatPos,sizeToConcatenate);
tempBuffer[sizeToConcatenate]='\0';
fputs(tempBuffer,modified);
}
fputs(replacementString, modified);
lastConcatPos = searchStringPos + searchStringLength;/* continue search after current occurrence*/
}
fputs(lastConcatPos,modified);
}
fclose(original);
fclose(modified);
}
static void askUserForInput(char* data_storage,char* text_message){
int result = 0;
do{
//printf("%s, | %s\n | result = %i",text_message,data_storage,result);
printf("%s\n",text_message);
fflush(stdout);
result = scanf("%s",data_storage);
}while(result ==0);
}
int main(int argc,char* argv[]){
/* Use: program <original_filename> <modified_filename> <string_to_search> <replacement_string> or
* program for asking the user for input */
if(argc == 5){
searchAndReplace(argv[1],argv[2],argv[3],argv[4]);
}else if(argc == 1){
char origin_file[128];
char destination_file[128];
char search_string[128];
char replacement_string[128];
askUserForInput(origin_file,"Enter origin file please");
askUserForInput(destination_file,"Enter destination file please");
askUserForInput(search_string,"Enter search string please");
askUserForInput(replacement_string,"Enter replacement string please");
searchAndReplace(origin_file,destination_file,search_string,replacement_string);
}else{
printf("Usage:\n %s <original_filename> <modified_filename> <string_to_search> <replacement_string>\n or"
"%s without parameter for asking for input",argv[0],argv[0]);
exit(1);
}
return 0;
}
編輯的見解:還有很大的提升空間,比如檢查每個空指針功能,改變searchAndReplace
根據錯誤的類型返回int
= 0成功和別人並讓呼叫者管理程序行爲的其他部分一樣再次嘗試,而不是退出程序等
而且printf
上錯誤處理部分應替換爲fprintf(stderr,"message",..)
這是您可以用來改進和學習的一些想法和概念 多很多。希望你有很多樂趣
替換是困難的,除非你用一個完全相同大小的字符串替換原件。否則,下一個最好的事情就是記憶地圖並使用'memmove'。 –
如果我有條目存儲在一個數組中,我可以檢查替換的條目在替換之前是否會超出數組的大小。對? – Questioneer
較大的*和*較小都有問題,因爲您需要移動所有後續文件內容。唯一容易的是平面覆蓋。 –