b3n*_*m1n 1 c string replace char segmentation-fault
我对C非常陌生,并且创建了一个函数,该函数从字符串中删除特殊字符并返回一个新字符串(不包含特殊字符)。
乍一看,这似乎运行良好,现在我需要在一个(巨大的)文本文件(一百万个句子)的行上运行此功能。经过几千行/句(大约4,000个)之后,我遇到了段错误。
我对C中的内存分配和字符串没有太多的经验,但我尝试找出代码的问题,很不幸,这没有任何运气。这是代码:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char *preproccessString(char *str) {
// Create a new string of the size of the input string, so this might be bigger than needed but should never be too small
char *result = malloc(sizeof(str));
// Array of allowed chars with a 0 on the end to know when the end of the array is reached, I don't know if there is a more elegant way to do this
// Changed from array to string for sake of simplicity
char *allowedCharsArray = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
// Initalize two integers
// i will be increased for every char in the string
int i = 0;
// j will be increased every time a new char is added to the result
int j = 0;
// Loop over the input string
while (str[i] != '\0') {
// l will be increased for every char in the allowed chars array
int l = 0;
// Loop over the chars in the allowed chars array
while (allowedCharsArray[l] != '\0') {
// If the char (From the input string) currently under consideration (index i) is present in the allowed chars array
if (allowedCharsArray[l] == toupper(str[i])) {
// Set char at index j of result string to uppercase version of char currently under consideration
result[j] = toupper(str[i]);
j++;
}
l++;
}
i++;
}
return result;
}
Run Code Online (Sandbox Code Playgroud)
这是程序的其余部分,我认为问题可能出在这里。
int main(int argc, char *argv[]) {
char const * const fileName = argv[1];
FILE *file = fopen(fileName, "r");
char line[256];
while (fgets(line, sizeof(line), file)) {
printf("%s\n", preproccessString(line));
}
fclose(file);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
你有几个问题。
sizeof(str)
是指针的大小,而不是字符串的长度。您需要使用char *result = malloc(strlen(str) + 1);
Run Code Online (Sandbox Code Playgroud)
+ 1
用于终止空字节。
result[j] = '\0';
Run Code Online (Sandbox Code Playgroud)
之前 return result;
一旦发现字符与允许的字符匹配,就无需继续遍历其余允许的字符。break
在之后添加j++
。
您的main()
函数永远不会释放的结果preprocessString()
,因此可能内存不足。
while (fgets(line, sizeof(line), file)) {
char *processed = preproccessString(line);
printf("%s\n", processed);
free(processed);
}
Run Code Online (Sandbox Code Playgroud)
如果在结果字符串中有调用方传递,而不是在函数中分配,则可以解决其中的大多数问题。只需char[256]
在main()
函数中使用两个数组即可。
int main(int argc, char *argv[])
{
char const* const fileName = argv[1];
FILE* file = fopen(fileName, "r");
char line[256], processed[256];
while (fgets(line, sizeof(line), file)) {
processString(line, processed);
printf("%s\n", processed);
}
fclose(file);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
然后只需更改函数,以使参数为:
void preprocessString(const char *str, char *result)
Run Code Online (Sandbox Code Playgroud)