[英]Coverting an unknown length string to lower case issues
因此,我對C不太滿意,但是我正在設計一個GLUT應用程序,該應用程序讀取的文件不區分大小寫。 為了更容易,我想將字符串轉換為所有小寫字母。 我做了一個函數makeLower,該函數正在修改通過引用傳遞的變量。
我在makeLower方法中有一個While循環,該循環似乎可以通過while循環的第一次迭代的一部分,然后使EXE崩潰。 任何提示都很好,謝謝!
輸出:
C:\Users\Mark\Documents\Visual Studio 2010\Projects\Project 1\Debug>"Project 1.e
xe" ez.txt
Line is #draw a diamond ring
Character is #
然后錯誤“項目1.exe已停止工作”
碼:
void makeLower(char *input[]){
int i = 0;
printf("Line is %s\n", *input);
while(input[i] != "\0"){
printf("Character is %c\n", *input[i]);
if(*input[i] >= 'A' && *input[i] <= 'Z'){
*input[i] = tolower(*input[i]);
}
i++;
}
}
int main(int argc, char *argv[]) {
FILE *file = fopen(argv[1], "r");
char linebyline [50], *lineStr = linebyline;
char test;
glutInit(&argc, argv);
while(!feof(file) && file != NULL){
fgets(lineStr , 100, file);
makeLower(&lineStr);
printf("%s",lineStr);
//directFile();
}
fclose(file);
glutMainLoop();
}
我現在看到了更多問題,因此我將評論擴展到一個答案:
您分配了一個由50個字符組成的數組,但告訴fgets
最多獲取100個字符,這可能是致命的,因為fgets
會覆蓋不在字符串中的內存。
將C字符串傳遞給函數時,不必將指針的地址傳遞給字符串( &lineStr
),實際的指針或數組都可以。 這意味着您可以將makeLower
函數更改為void makeLower(char *input)
或void makeLower(char input[])
。 現在, makeLower
的參數聲明為數組或char指針,而不是char數組的指針。
在上面我提出的新makeLower
,您可以將單個字符作為數組( input[i]
)或作為指針加上偏移量( *(input + i)
,就像我在評論中說的那樣,最后一個版本是如果您使用第一個,則編譯器可能會創建,但是第一個更易讀,所以我建議這樣做。
同樣在makeLower
您與"\\0"
進行比較, "\\0"
是字符串而不是字符。 實際上這幾乎是正確的:您應該使用input[i] != '\\0'
。
最后,這就是我的實現方式:
void makeLower(char *input)
{
while (*input != '\0') /* "while (*input)" would also work */
{
*input = tolower(*input);
input++;
}
}
有關該功能的一些解釋:
strlen
或strcpy
)中所看到的那樣。 *input
取消引用 (即獲取指針指向的值)字符串。 它與*(input + 0)
,因此獲取字符串中第一個字符的值。 '\\0'
(從技術上來說是正常的零),我們將循環播放。 tolower
函數。 無論字符是什么,這都將起作用, tolower
只會將大寫字符變為小寫,所有其他字符將被返回。 tolower
復制的第一個字符。 之所以可行,是因為必須在分配之前執行分配的右側,因此不會有任何錯誤或問題。 input
指向字符串中的下一個字符。 這是可行的,因為input
是局部變量,因此對指針的操作不會影響調用函數中的任何內容。 現在可以這樣調用該函數:
char input[100];
fgets(input, sizeof(input), stdin);
printf("before: \"%s\"\n", input);
makeLower(input);
printf("after : \"%s\"\n", input);
您是否嘗試了while(* input [i]!=“ \\ 0”)而不是您擁有的東西? 由於某種原因,您似乎將指向char(* input [])和&lineStr的指針傳遞給函數,因此在檢查字符串終止符“ \\ 0”時,應兩次取消引用。...
只是一個想法,希望對您有所幫助
我認為問題是您不希望該字符串等於'\\ 0'。 因此,您可能會超出范圍,這很可能是您不知道字符串的長度。
據我了解,可以將'\\ 0'傳遞給tolower()
。 這是有效的unsigned char
值,並且tolower()
僅在無法進行任何轉換tolower()
返回輸入字符。
因此,可以將循環簡寫為:
while(input[i] = tolower(input[i]))
++i;
這會再調用一次tolower()
,但它更短,並且(imo)很清楚。 只是想提一下它。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.