我在C中打印字符串时遇到问题(好吧,*ptr
指向的字符串。)
我有以下代码:
char *removeColon(char *word) {
size_t wordLength;
char word1[MAXLENGTH];
wordLength = strlen(word);
wordLength--;
memcpy(word1, word, wordLength);
printf("word1: %s\n", word1);
return *word1;
}
我用word = "MAIN:"
运行它(word的值来自strtok
从文件读取的字符串)。
它工作正常,直到printf
,结果是:
字1:MAIN╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠╠ ╠╠╠╠╠╠╠╠
然后有一个例外,一切都会中断。
有什么想法吗?
答案 0 :(得分:1)
您必须确保(1)每个字符串都是以空字符结尾的,并且(2)您没有尝试修改字符串文字。你有很多方法可以采取。使用strlen
删除最后一个字符(任何字符)的简单方法:
char *rmlast (char *s)
{
if (!*s) return s; /* return if empty-string */
s[strlen (s) - 1] = 0; /* overwrite last w/nul */
return s;
}
(您还可以使用string.h
函数strchr
(搜索0
),strrchr
(搜索目标字符,如果通过),{{1} (搜索几个字符中的一个)等,以便找到最后一个字符)
或者你可以用指针做同样的事情:
strpbrk
如果要将删除限制为任何特定字符,并且在使用 nul-terminatedating 字符覆盖它之前在函数中进行简单比较,也可以传递最后一个感兴趣的字符。
查看两者并告诉我您是否有任何疑问。
答案 1 :(得分:1)
您的函数removeColon
应该
只将字符复制到本地数组,而不是空终止符,也不在缓冲区中设置一个,将此数组传递给printf("%s", ...)
调用未定义的行为:printf
继续打印缓冲区内容直到它找到一个'\0'
字节,它甚至超出了数组的末尾,调用未定义的行为,打印垃圾并最终在崩溃中死亡。
您无法返回指向自动数组的指针,因为该函数一返回就会变为不可用。稍后取消引用指针将调用未定义的行为。
这是一个适用的功能:
char *removeColon(char *word) {
if (*word) word[strlen(word) - 1] = '\0';
return word;
}
这是复制到目标缓冲区的一个,假设足够长:
char *removeColon(char *dest, const char *word) {
size_t len = strlen(word);
memcpy(dest, word, len - 1);
dest[len - 1] = '\0';
return dest;
}
这是一个分配内存的方法:
char *removeColon(const char *word) {
size_t len = strlen(word);
char *dest = malloc(len);
memcpy(dest, word, len - 1);
dest[len - 1] = '\0';
return dest;
}
答案 2 :(得分:0)
wordLength = strlen(word);
您必须在长度中包含空终止符,因为每个字符串都有一个终止字符,其ASCII值为0,在C中拼写为\0
。另外,使用str...
系列函数代替mem...
,因为前者用于空终止字符串,后者用于数组。此外,您无法返回本地堆栈分配的数组。根据函数的代码,听起来你正在删除最后一个字符。如果是这种情况,最好做
void remlast(char *str)
{
str[strlen(str) - 1] = '\0';
}
请注意,这不适用于空字符串。
答案 3 :(得分:0)
您复制wordLength
个字节,但无法添加空终止字节。由于word1
在此副本之前未初始化,因此其余字节未定义。
因此,当printf
尝试打印字符串时,它找不到空终止符并继续读取,直到它在数组边界之外的某处找到空字节。这是未定义的行为。
复制字节后,需要手动添加空终止符:
memcpy(word1, word, wordLength);
word1[wordLength] = '\0';
此外,您将返回指向局部变量的指针。当函数返回时,该变量超出范围,并且取消引用该指针也是未定义的行为。
不是让word1
成为本地数组,而是可以为它动态分配内存:
char *word1 = malloc(strlen(word));
如果你这样做,你需要在调用函数的某个地方free
这个内存。另一个选择是让调用者传入适当大小的缓冲区:
void removeColon(char *word, char *word1) {