如何解决字符串操作导致段错误 C
我正在尝试“深度复制”一个字符串,以便我可以对一个副本执行操作,同时保留原始副本。这是我得到的基本示例,出于某种原因,strncpy 调用会导致段错误。请帮忙
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main() {
char* stringA = "someVeryinTeresTingString";
char* stringB = malloc(sizeof(char) * strlen(stringA));
printf("A: %s,B: %s\n",stringA,stringB);
for (int i = 0; i < strlen(stringA); i++) {
stringB[i] = tolower(stringA[i]);
}
printf("A: %s,stringB);
strncpy(stringA,stringB,strlen(stringA) - 1);
printf("A: %s,stringB);
}
解决方法
最简单的解决方法是制作该字符串文字的本地副本:
char stringA[] = "someVeryinTeresTingString";
其他一切都一样。
请注意,在原始代码中,您有一个指向不可变内存的指针,而在此版本中,您有一个本地(堆栈)数组,该数组使用该字符串的副本进行初始化。
另一件需要注意的事情是,如果您要复制和操作 C 字符串,请执行以下操作:
char* stringB = strdup(stringA);
for (int i = 0; i < strlen(stringB); ++i) {
stringB[i] = tolower(stringB[i]);
}
或者通过避免所有这些昂贵的 strlen()
调用来提高效率:
char* stringB = strdup(stringA);
for (char* p = stringB; *p; ++p) {
*p = tolower(*p);
}
,
这一行:
char* stringB = malloc(sizeof(char) * strlen(stringA));
应该是这样的:
char* stringB = malloc(sizeof(char) * (strlen(stringA) + 1));
然后你就可以复制stringA末尾的\0
此外,您想复制到文字字符串 - 即分段错误
char *strncpy(char *dest,const char *src,size_t n)
,
我会尝试在您自己的代码中评论并更正我所看到的错误:
(我不会纠正可以消除或以其他方式做得更好,但正确或无害的事情,因此您只会看到由于编程错误而必须纠正的事情,并且不是关于风格或编程用途的问题)
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
int main() {
char* stringA = "someVeryinTeresTingString";
/* you need to consider the space for the final null character in the malloc() call */
char* stringB = malloc(sizeof(char) * (strlen(stringA) + 1));
/* you don't need to use sizeof(char) as it is always equal to one.
* Multiplying by one is not necessary,but you'll probably know.
* char is warranteed by C standard that its sizeof is one. */
/* you need to copy the string *before* printing,or you will print an
* uninitialized string. Or at least initialize stringB to zeros,so you can
* use it with printf like functions (I do initialize the first char position to
* zero to make it appear as a length zero "" string)
* You will incurr in undefined behaviour if you don't do this. */
stringB[0] = '\0';
printf("A: %s,B: %s\n",stringA,stringB);
/* you need to copy the strings,so you can do it better if you test when
* stringA[i] == '\0',so you don't calculate the length of a string that is
* not going to change at every loop iteration. I will not change your
* code,because this is not an error. But strlen() searches from the
* beginning of the string for the '\0' char,character by character,* and this test is done at every loop iteration. With the expression
* stringA[i] == 0 you do only a test per loop iteration to see if
* the char at position i in stringA is the null character. */
int i;
for (i = 0; i < strlen(stringA); i++) {
stringB[i] = tolower(stringA[i]);
}
/* you have not copied the final '\0',so I do it now. I need to move the
* declaration of i outside of the loop to be able to use it's value. */
stringB[i] = 0; /* you can use 0 or '\0' interchangeably */
printf("A: %s,stringB);
/* nope. you need to copy the strings with a normal strcpy() as you know that
* both are the same length (better,you know that the space in stringB
* is the same as the length of stringA plus one). If you do this,you will not copy the last '\0' char,so wee need to append it.
* well,I don't know if that is what you want,so I don't actually touch anything here. */
strncpy(stringA,stringB,strlen(stringA) - 1);
/* stringB should be one char shorter than stringA */
printf("A: %s,stringB);
}
顺便说一下,我们建议您使用 strdup(3)
。这是一个好主意,在这种情况下您不需要考虑最终的空值,因为 strdup()
会处理它。请记住,strdup(3)
并未包含在许多 C 标准修订版中,因此如果您
把你的程序移到没有它的地方(反正那应该很奇怪)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。