简体   繁体   English

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

[英]Unwanted characters when printing a C string

For the most part my code below does what I want.在大多数情况下,我下面的代码可以满足我的要求。 The only issue is it is printing extra unwanted non-ASCII characters in front of the string.唯一的问题是它在字符串前面打印了多余的不需要的非 ASCII 字符。

I tried printing the string inside the longestConsec() function and found that it already contains the unwanted characters so I know that the problem is in the function.我尝试在longestConsec()函数中打印字符串,发现它已经包含不需要的字符,所以我知道问题出在函数中。

Additionally, I tried looping through res (using the length that I assigned to it with malloc() ) to set the characters to whitespace;此外,我尝试遍历res (使用我通过malloc()分配给它的长度)将字符设置为空格; this worked but I don't want leading and trailing whitespace and I don't want to write an algorithm to remove it if it's not necessary.这行得通,但我不想要前导和尾随空格,如果不需要,我不想编写算法来删除它。

If I did something to cause these unwanted characters to appear then I would prefer to fix that than to work around by setting everything to whitespace and then trimming it.如果我做了什么导致这些不需要的字符出现,那么我宁愿解决这个问题,也不愿通过将所有内容设置为空白然后修剪它来解决。

Any help would be appreciated.任何帮助,将不胜感激。

Output:输出:

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

Code:代码:

#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;
}

the problem with the leading 'unexpected' characters is because the call to strcat() begins placing characters WHERE it encounters a NUL byte.前导“意外”字符的问题是因为对strcat()的调用开始在遇到 NUL 字节的地方放置字符。

That could be anywhere,in memory (IE undefined behavior with out setting the NUL byte in the code.)这可能是内存中的任何地方(即未在代码中设置 NUL 字节的未定义行为。)

Rather than the loop that sets all the bytes in the allocated memory nor calling calloc() , a MUCH BETTER method would be to set the FIRST byte of the allocated memory to NUL IE不是在分配的内存中设置所有字节或调用calloc()的循环,更好的方法是将分配的内存的第一个字节设置为 NUL IE

res[0] = '\0';

Then the following call(s) to strcat() will work correctly.然后对strcat()的以下调用将正常工作。

Valgrind shows this quite straightforwardly: 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)

You have created an unterminated string with at least length characters in a block of size length you allocated.您已在分配的大小length的块中创建了一个至少包含length字符的未终止字符串。 Appending will necessarily overrun the buffer, simply while looking for the end of the existing string.追加必然会溢出缓冲区,只是在寻找现有字符串的结尾时。

Instead of writing length spaces, you should write a single NUL character, to form an empty string.你应该写一个 NUL 字符,而不是写length空格,以形成一个空字符串。

BTW, you should fix your compilation warnings (ensure you have at least -Wall -Wextra or equivalent).顺便说一句,你应该修复你的编译警告(确保你至少有-Wall -Wextra或等效的)。


Fixed code固定码

#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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM