C从字符串中删除特殊字符

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)

Bar*_*mar 5

你有几个问题。

  1. 您没有分配足够的空间。sizeof(str)是指针的大小,而不是字符串的长度。您需要使用
char *result = malloc(strlen(str) + 1);
Run Code Online (Sandbox Code Playgroud)

+ 1 用于终止空字节。

  1. 您没有在结果字符串中添加一个终止的空字节。加
result[j] = '\0';
Run Code Online (Sandbox Code Playgroud)

之前 return result;

  1. 一旦发现字符与允许的字符匹配,就无需继续遍历其余允许的字符。break在之后添加j++

  2. 您的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)