打印C中反转的字符串

时间:2013-11-22 11:00:52

标签: c string reverse

我正在编写一个程序,它将一些文件作为参数并打印所有反转的行。问题是我得到了意想不到的结果:

如果我将其应用于包含以下行的文件

one
two
three
four 

我得到了预期的结果,但是如果文件包含

september
november
december

返回

rebmetpes
rebmevons
rebmeceds

而且我不明白为什么它会添加一个""最后

这是我的代码

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

void reverse(char *word);

int main(int argc, char *argv[], char*envp[]) {
    /* No arguments */
    if (argc == 1) {
        return (0);
    }

    FILE *fp;

    int i;
    for (i = 1; i < argc; i++) {
        fp = fopen(argv[i],"r"); // read mode

        if( fp == NULL )
        {
            fprintf(stderr, "Error, no file");
        }

        else
        {
            char line [2048];
/*read line and reverse it. the function reverse it prints it*/
            while ( fgets(line, sizeof line, fp) != NULL )
                reverse(line);  
        }
        fclose(fp);
    }

    return (0);
}

void reverse(char *word)
{
    char *aux;
    aux = word;
    /* Store the length of the word passed as parameter */
    int longitud;
    longitud = (int) strlen(aux);

    /* Allocate memory enough ??? */
    char *res = malloc( longitud * sizeof(char) );

    int i;

    /in this loop i copy the string reversed into a new one
    for (i = 0; i < longitud-1; i++)
    {
        res[i] = word[longitud - 2 - i];
    }

    fprintf(stdout, "%s\n", res);
    free(res);
}

(注意:为清楚起见,已删除了一些代码,但应编译)

4 个答案:

答案 0 :(得分:4)

您忘记使用\0字符终止字符串。在反转中,字符串\0成为反向字符串的第一个字符。首先为比你分配的字符多一个字符分配内存

char *res = malloc( longitud * sizeof(char) + 1);  

试试这个

for (i = 0; i < longitud-1; i++)
{
    res[i] = word[longitud - 2 - i];
}
res[i] = '\0'; // Terminating string with '\0'

答案 1 :(得分:1)

我想我知道这个问题,这有点奇怪。

C中的字符串为零终止。这意味着字符串&#34;嗨!&#34;在内存中实际表示为'H','i','!','\0'。然后strlen等方式知道字符串的长度是通过计算字符数,从第一个字符开始,在零终止符之前。同样,在打印字符串时,fprintf将打印所有字符,直到它到达零终结符。

问题是,你的reverse函数永远不会在最后设置零终结符,因为你需要逐个字符地将字符复制到缓冲区中。这意味着它在你分配的res缓冲区的末尾运行,并进入未定义的内存,当你点击它时恰好为零(malloc没有对你分配的缓冲区内容做出承诺,只是它足够大了)。您应该在Windows上获得不同的行为,因为我相信在调试模式下,malloc会将所有缓冲区初始化为0xcccccccc。

所以,你正在发生的事情是将9月复制到res。这就像你看到的那样有效,因为它恰好在最后有一个零。

然后,您再次释放res,然后malloc。再次,偶然(并且由于malloc中的一些聪明)你得到了相同的缓冲区,它已经包含了&#34; rebmetpes&#34;。然后你把&#34; 11月&#34; in,reverse,稍短,因此你的缓冲区现在包含&#34; rebmevons&#34;。

那么,修复?分配另一个字符,这将保留您的零终结符(char *res = malloc( longitud * sizeof(char) + 1);)。反转字符串后,在字符串末尾设置零终止符(res[longitud] = '\0';)。

答案 2 :(得分:1)

有两个错误,第一个是你需要一个更多的char分配(字符串的所有字符+终结符的1个字符)

    char *res = malloc( (longitud+1) * sizeof(char) );

第二个是你必须终止字符串:

   res[longitud]='\0';

您可以在进入循环之前终止字符串,因为您已知道目标字符串的大小。

请注意,使用calloc而不是malloc,您将不需要终止字符串,因为内存已被零初始化

答案 3 :(得分:0)

谢谢,它解决了我的问题。我在字符串中读到了一些关于“\ 0”的内容但是不是很清楚,现在在阅读完所有答案之后(一切都很好)。谢谢大家的帮助。