打印C字符串时不需要的字符

时间:2017-10-04 05:42:34

标签: c c-strings

在大多数情况下,我的代码可以满足我的需求。唯一的问题是它在字符串前面打印了额外不需要的非ASCII字符。

我尝试在longestConsec()函数中打印字符串,发现它已包含不需要的字符,所以我知道问题出在函数中。

此外,我尝试循环遍历res(使用我用malloc()分配给它的长度)将字符设置为空格;这工作但我不想要前导和尾随空格,如果没有必要,我不想写一个算法来删除它。

如果我做了一些事情导致这些不需要的字符出现,那么我宁愿通过将所有内容设置为空白然后修剪它来解决这个问题。

任何帮助都将不胜感激。

输出:

Expected Output:threefourthreefour
Output: ÉmthreefourÉmthreefour
Output with white space replacement:          threefour         threefour

代码:

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

char* longestConsec(char* strarr[], int n, int k)
{
    int i = 0;
    int longest = 0;
    int longestIndex = 0;
    for(; i < n; i++) {
        if(longest < strlen(strarr[i])) {
            longestIndex = i;
            longest = strlen(strarr[i]);
        }
    }
    //printf("%d", longestIndex);
    int length = 0;
    i = longestIndex;
    int j = 0;
    for(; i < n && j < k; i++, j++) {
        length += strlen(strarr[i]);
    }
    char* res = malloc(length * sizeof(char));
    int m = 0;
    for(; m < length; m++) {
        res[m] = ' ';
    }

    i = longestIndex;
    j = 0;

    //printf("%s", res);
    for(; i < n && j < k; i++, j++) {
        strcat(res, strarr[i]);
    }
    printf("%s", res);
    return res;
}



int main()
{
    char* strs[10] = {"One", "Two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
    printf("%s", longestConsec(strs, 10, 2));
    return 0;
}

2 个答案:

答案 0 :(得分:0)

前导'意外'字符的问题是因为对strcat()的调用开始在遇到NUL字节的位置放置字符。

这可以在内存中的任何地方(I.E.未定义的行为,但不在代码中设置NUL字节。)

不是循环设置分配的内存中的所有字节,也不是调用calloc(),而是更好的方法是将分配的内存的FIRST字节设置为NUL I.E。

res[0] = '\0';

然后,strcat()的以下呼叫将正常工作。

答案 1 :(得分:0)

Valgrind非常直截了当地说明了这一点:

==19471== Invalid read of size 1
==19471==    at 0x4C2EAA4: strcat (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19471==    by 0x108863: longestConsec (46557761.c:34)
==19471==    by 0x10892A: main (46557761.c:45)
==19471==  Address 0x51d5049 is 0 bytes after a block of size 9 alloc'd
==19471==    at 0x4C2BBEF: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==19471==    by 0x108805: longestConsec (46557761.c:23)
==19471==    by 0x10892A: main (46557761.c:45)

您已在已分配的大小为length的块中创建了一个至少包含length个字符的未终止字符串。只需在查找现有字符串的末尾时,追加就必然会超出缓冲区。

您应该编写一个NUL字符,而不是编写length个空格,以形成空字符串。

顺便说一下,你应该修复你的编译警告(确保你至少有-Wall -Wextra或同等的。)

固定代码

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

char *longestConsec(const char *strarr[], unsigned int n, unsigned int k)
{
    unsigned int longest = 0;
    unsigned int longestIndex = 0;

    for (unsigned int i = 0;  i < n;  ++i) {
        unsigned int len = strlen(strarr[i]);
        if (longest < len) {
            longestIndex = i;
            longest = len;
        }
    }

    unsigned int lastIndex = longestIndex + k;
    if (lastIndex > n) {
        lastIndex = n;
    }

    unsigned int length = 0;
    for (unsigned int i = longestIndex;  i < lastIndex;  ++i) {
        length += strlen(strarr[i]);
    }
    char *res = malloc(length + 1);
    res[0] = '\0';

    for (unsigned int i = longestIndex;  i < lastIndex;  ++i) {
        strcat(res, strarr[i]);
    }
    return res;
}


#include <stdio.h>
int main()
{
    char const *strs[10] = {"One", "Two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"};
    char *longest = longestConsec(strs, 10, 2);
    printf("%s\n", longest);
    free(longest);
    return 0;
}