C语言文本自动换行程序输出不符问题求助
C语言文本自动换行程序问题修复
我是C语言新手,正在编写一个文本自动换行程序,要求处理后每行长度不超过指定的linewidth值。其中readfile函数负责从文件读取内容到字符串数组(数组每个元素对应文件一行),需要实现逻辑将内容转换为符合长度限制的newtext字符串数组。
目前程序输出和预期不符,尝试过调整结束索引、编写单独的空格跳过循环都没解决问题:
- 预期效果:每行长度不超过设定值,优先在单词末尾换行,不截断单词;若单个单词长度超过限制,才强制截断
- 当前输出:存在单词被截断、换行位置错误的情况
原程序代码
#include <stdio.h> #include <string.h> #include <stdlib.h> int readfile(char* filename, char*** bufp) { FILE* fp = fopen(filename, "r"); char** buf = NULL; int numlines = 0; char tmp[1000]; while (fgets(tmp, sizeof(tmp), fp)) { if (numlines % 16 == 0) { buf = (char**)realloc(buf, (numlines+16) * sizeof(char*)); } int len = strlen(tmp); tmp[len-1] = 0; buf[numlines] = malloc(len + 1); strcpy(buf[numlines], tmp); numlines++; } *bufp = buf; return numlines; } void print_text(char** lines, int numlines) { for (int i=0; i<numlines; i++) { printf("%s\n", lines[i]); } } int main(int argc, char** argv) { char** text; int numlines = readfile(argv[1], &text); int linewidth = atoi(argv[2]); char** newtext = NULL; int newnumlines = 0; for (int i = 0; i < numlines; i++) { char * line = text[i]; int length = strlen(line); int x = 0; int start = 0; while (start < length) { // Calculate the end index of the current line segment int end = start + linewidth; // Adjust the end index if it falls within a word while (end > start && end < length && line[end] != ' ') { end--; } char *newline = malloc(end - x + 1 + 1); strncpy(newline, line + start, end - start); newline[end - start] = '\0'; newtext = realloc(newtext, (newnumlines + 1) * sizeof(char*)); newtext[newnumlines++] = newline; start = end; while(start < length && line[start] == ' ') { start++; } } } for(int i = 0; i < newnumlines; i++) { // Skip printing empty lines if (strlen(newtext[i]) > 0) { printf("%s\n", newtext[i]); } } //freeing memory for(int i = 0; i < numlines; i++){ free(text[i]); } free(text); for(int i = 0; i < newnumlines; i++){ free(newtext[i]); } free(newtext); return 0; }
问题分析与修复
原代码存在4个关键错误导致输出异常,修复后的代码如下:
#include <stdio.h> #include <string.h> #include <stdlib.h> int readfile(char* filename, char*** bufp) { FILE* fp = fopen(filename, "r"); if (!fp) { perror("Failed to open file"); return 0; } char** buf = NULL; int numlines = 0; char tmp[1000]; while (fgets(tmp, sizeof(tmp), fp)) { if (numlines % 16 == 0) { buf = (char**)realloc(buf, (numlines+16) * sizeof(char*)); if (!buf) { perror("Realloc failed"); exit(EXIT_FAILURE); } } int len = strlen(tmp); // 处理文件最后一行没有换行符的情况 if (tmp[len-1] == '\n') { tmp[len-1] = 0; len--; } buf[numlines] = malloc(len + 1); if (!buf[numlines]) { perror("Malloc failed"); exit(EXIT_FAILURE); } strcpy(buf[numlines], tmp); numlines++; } fclose(fp); *bufp = buf; return numlines; } int main(int argc, char** argv) { if (argc != 3) { printf("Usage: %s <filename> <linewidth>\n", argv[0]); return 1; } char** text; int numlines = readfile(argv[1], &text); if (numlines == 0) { return 1; } int linewidth = atoi(argv[2]); if (linewidth <= 0) { printf("Invalid linewidth\n"); return 1; } char** newtext = NULL; int newnumlines = 0; for (int i = 0; i < numlines; i++) { char *line = text[i]; int length = strlen(line); int start = 0; while (start < length) { int end = start + linewidth; // 确保end不超过字符串长度 if (end > length) { end = length; } // 回退到最近的空格,避免截断单词 while (end > start && end < length && line[end] != ' ') { end--; } // 处理超长单词:如果回退到start,直接截断到linewidth if (end == start) { end = start + linewidth; if (end > length) { end = length; } } // 分配正确的内存:end-start是字符数,加1存终止符 char *newline = malloc(end - start + 1); if (!newline) { perror("Malloc failed"); exit(EXIT_FAILURE); } strncpy(newline, line + start, end - start); newline[end - start] = '\0'; newtext = realloc(newtext, (newnumlines + 1) * sizeof(char*)); if (!newtext) { perror("Realloc failed"); exit(EXIT_FAILURE); } newtext[newnumlines++] = newline; // 更新start,跳过后续空格(只有当end没到末尾时才处理) start = end; if (start < length && line[start] == ' ') { while(start < length && line[start] == ' ') { start++; } } } } for(int i = 0; i < newnumlines; i++) { printf("%s\n", newtext[i]); } // 释放内存 for(int i = 0; i < numlines; i++){ free(text[i]); } free(text); for(int i = 0; i < newnumlines; i++){ free(newtext[i]); } free(newtext); return 0; }
关键修改点
- 边界处理:添加
end不超过字符串长度的判断,避免数组越界访问 - 超长单词兼容:当回退
end到start时,直接截断到linewidth,避免无限循环 - 内存分配修正:去掉无用变量
x,按end-start+1分配内存,确保能存下终止符 - 空格跳过逻辑优化:只有当
end未到字符串末尾时,才跳过后续空格,避免越界 - 增加错误检查:添加文件打开、内存分配的错误处理,提升程序稳定性
内容的提问来源于stack exchange,提问作者dev jonston
相关产品推荐
相关产品推荐

