不同操作系统换行符类型及统一替换为\0的技术咨询
Hey there! Let's tackle your two questions one by one, with practical fixes for your code.
For modern development, the three newline formats you listed cover nearly all real-world scenarios:
\n(Line Feed): Used by Linux, modern macOS, and most Unix-like systems\r\n(Carriage Return + Line Feed): Used by Windows and legacy DOS systems\r(Carriage Return): Used by classic macOS (pre-OS X) and older iOS versions
There are extremely rare cases of legacy systems (like IBM mainframes using EBCDIC-based line endings) with obscure newline sequences, but these are almost never encountered today. Focusing on the three above will cover 99.9% of your use cases.
Looking at your code, there are a few key issues causing the leftover \r\n in your URL:
First: Critical typo in fgets
You passed buf as the third argument to fgets instead of the file pointer! That's breaking your read logic entirely. It should be:
fgets(buf, sizeof buf, file);
Second: Stripping newline characters reliably
fgets preserves newline characters from the file (text mode behavior varies by OS, so you can't rely on automatic conversion). To remove all \r and \n characters from your input, add this cleanup step right after reading the line:
// Remove any trailing \r or \n from the buffer char *newline = strpbrk(buf, "\r\n"); if (newline != NULL) { *newline = '\0'; }
This works perfectly for URLs, which shouldn't contain internal newlines. If you ever need to remove all newlines (even mid-line), use this loop instead:
char *pos = buf; while (*pos != '\0') { if (*pos == '\r' || *pos == '\n') { memmove(pos, pos + 1, strlen(pos)); } else { pos++; } }
Third: Fixing memory leaks and unsafe strncpy
- Your current code leaks memory: it allocates a new
urlpointer each loop without freeing the old one. Always clean up existing memory first:if ((*properties)->url != NULL) { free((*properties)->url); (*properties)->url = NULL; } size_t buf_len = strlen(buf); (*properties)->url = (char *)malloc(buf_len + 1); if ((*properties)->url != NULL) { strcpy((*properties)->url, buf); } strncpyis risky because it doesn't guarantee a null terminator if the source string matches the target buffer length. Instead, either usestrcpy(if you know the target is large enough) or explicitly add a null terminator:// Example with a fixed-size target buffer #define MAX_URL_LENGTH 256 strncpy(url, properties->url, MAX_URL_LENGTH - 1); url[MAX_URL_LENGTH - 1] = '\0'; // Ensure safe termination
Final revised code
Here's your code with all fixes applied:
FILE *file = fopen(filename, "rt"); if (file == NULL) { // Handle file open failure (e.g., log error, return early) return; } while (fgets(buf, sizeof buf, file) != NULL) { // Strip trailing newline characters char *newline = strpbrk(buf, "\r\n"); if (newline != NULL) { *newline = '\0'; } // Clean up previous URL memory to avoid leaks if ((*properties)->url != NULL) { free((*properties)->url); } // Allocate and copy the cleaned URL size_t url_len = strlen(buf); (*properties)->url = (char *)malloc(url_len + 1); if ((*properties)->url != NULL) { strcpy((*properties)->url, buf); } // ... Rest of your logic here } fclose(file); // Don't forget to close the file! // Line x: Safe URL copy to target buffer #define MAX_URL_BUFFER 256 strncpy(url, properties->url, MAX_URL_BUFFER - 1); url[MAX_URL_BUFFER - 1] = '\0';
内容的提问来源于stack exchange,提问作者Sateesh

