缩短字符串的这个功能有什么问题?

时间:2016-08-10 06:17:56

标签: c string

我在C中定义了一个函数,它将长字符串缩短为固定大小并打印缩短的字符串。功能如下:

void fit(char *str,unsigned int size) // shorten long strings to fixed size, "size" and prints the shortened string.
{
    if ( strlen(str) > size)
        str[size] = '\0';  
    printf("%s", str);  // prints the shortened string
}

如果我运行此函数,编译器指出没有警告也没有错误,但执行停止。代码的哪一部分会使执行停止?

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

void fit(char *str, unsigned int size);

int main(void)
{
    fit("Hello People!!", 6);
}

void fit(char *str,unsigned int size)
{
    if ( strlen(str) > size)
        str[size] = '\0';
    printf("%s", str);
}

3 个答案:

答案 0 :(得分:4)

在标准C和C ++中,字符串文字("these")是只读的。

通常这些位于只读存储器中。通过在特定示例中写入str,程序会尝试写入写保护的内存,操作系统(或运行时,如果适用)不允许写入,这会导致程序异常终止。如果您正在编写C ++,编译器可能会抱怨您将const char*传递给接受非const参数的函数。

您有四种选择:

  1. 告诉编译器把“Hello People !!”在构建或初始化程序时,可写数据区域中的字符串而不是写保护数据 - 这需要编译器或平台特定的功能,而不是标准C或C ++的一部分。

  2. 使用特定于操作系统的命令使存储区域可写(玩得开心!)

  3. 在修改字符串之前将其复制到可变缓冲区。

  4. 使用char str[] = "Hello People!!"; - 这与选项3基本相同,但编译器会为您执行此操作。但是,在离开范围时要小心。

  5. 请注意,将空字符插入字符串缓冲区作为缩短字符串的方法可能是个坏主意,因为它会在分配的缓冲区中隐藏额外的空间。通常,您应该将字符串视为不可变的,如果您希望通过以写时复制的方式重用字符串来提高效率,那么请使用指向现存缓冲区的start/end对,而不是依赖于空终止。

答案 1 :(得分:2)

您可以使用静态字符串初始化分配的内存,它应该可以正常工作:

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

void fit(char *string, size_t size);

int main(void)
{
    char string[] = "Hello People!!";

    fit(string, 6);

    printf("%s\n", string);

    return 0;
}

void fit(char *string, size_t size)
{
    if (strlen(string) > size)
        string[size] = '\0';
}

答案 2 :(得分:2)

您正在尝试剪切string literal,即const char *,即写保护。

您可以将代码更改为:

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

void fit(char *str, unsigned int size);

int main(void)
{
    char test[] = "Hello People!!";

    fit(test, 6);
}

void fit(char *str,unsigned int size)
{
    if ( strlen(str) > size)
    {
        str[size] = '\0';
        printf("%s\n", str);
    }
    else
    {
        fprintf(stderr, "Size passed greater than string length!\n");
    }
}

正如您所看到的,您正在使用文字字符串初始化char(C-String)数组。所以通过引用传递该数组(传递给函数时使用数组衰减到指针)你可以修改它,结果就是你所期望的。

第二种解决方案是在fit func:

中创建一个新的临时字符串
#include <stdio.h>
#include <string.h>

void fit(char *str, size_t size);

int main(void)
{
    fit("Hello People!!", 6);
}

void fit(char *str, size_t size)
{
    // One char is added to store null terminator into new string
    char cutString[size+1] = {0};

    if ( strlen(str) > size)
    {
        for (size_t i=0; i<size; i++)
        {
            cutString[i] = str[i];
        }
        cutString[size] = '\0';

        printf("%s\n", cutString);
    }
    else
    {
       fprintf(stderr, "Size passed greater than string length!\n");
    }
}