将未知长度字符串转换为小写问题

时间:2012-01-27 07:00:39

标签: c visual-studio-2010 file-io

所以我对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();
}

4 个答案:

答案 0 :(得分:3)

我现在看到更多问题,所以我将评论扩展到答案:

您分配了一个包含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"进行比较,input[i] != '\0'是字符串,而不是字符。实际上这几乎是正确的:你应该使用void makeLower(char *input) { while (*input != '\0') /* "while (*input)" would also work */ { *input = tolower(*input); input++; } }

最后,我将如何实现它:

strlen

关于功能的一些解释:

  • 所有char数组都可以转换为char指针,但不是相反。传递char指针是实际传递字符串的最常用方法,正如您可以从所有接受字符串的标准函数(例如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); 是一个局部变量,因此指针上的操作不会影响调用函数中的任何内容。

现在可以像这样调用此函数:

{{1}}

答案 1 :(得分:1)

您是否尝试了(* input [i]!=“\ 0”)而不是您拥有的?由于某种原因,你似乎传递给你的函数一个指向char(* input [])和&amp; lineStr的指针,所以当你检查字符串终结符字符“\ 0”....时,取消引用两次是有意义的。 / p>

只是一个想法,希望它有所帮助

答案 2 :(得分:0)

我认为问题在于你不知道字符串在你想要的时候会等于'\ 0'。所以你可能会超出界限,很可能你不知道字符串的长度。

答案 3 :(得分:0)

据我所知,将'\ 0'传递给tolower()是很好的。这是一个有效的unsigned char值,如果输入字符无法进行任何转换,tolower()只返回输入字符。

因此,循环可以简洁地表示为:

while(input[i] = tolower(input[i]))
  ++i;

这再次呼叫tolower(),但它更短,(imo)非常清楚。只是想提一下它。