我對 C 很陌生,并試圖從檔案中讀取輸入資料流,將其附加到動態大小的陣列中,這在這一點上效果很好。之后,我想按字母順序對陣列進行排序。我閱讀了 strcmp 的聯機幫助頁,并認為這是最好的方法。但是,每當我嘗試執行它時,我都會遇到“分段錯誤”。分配記憶體時我到底做錯了什么?這是我的參考代碼:
int main (int argc, char* argv[]) {
int c = getLineCount();
FILE * wordlist = fopen("test", "r");
// If file doesn't exist, handle error
if ( wordlist == NULL ) {
fputs("Unable to open input file", stderr);
exit(1);
}
int length = 101;
char line[length];
int i = 0;
char **words = malloc(c * sizeof(line));
if ( words == NULL ) {
fputs("Unable to allocate Memory", stderr);
exit(1);
}
while (1) {
char *l = fgets(line, length, wordlist);
if ( (l == NULL) ) {
// Check if EOF is reached
if (feof(wordlist)) {
// fputs("--- EOF ---\n", stdout);
break;
// Check if error occured while reading
} else {
fputs("Error reading file", stderr);
exit(1);
}
} else if (strchr(line, '\n') == NULL) {
// Check if line is too long
// Iterate until newline is found or until EOF
int c;
while((c = fgetc(wordlist)) != '\n' && c != 0);
fputs("--- LINE TOO LONG ---\n", stderr);
continue;
} else if ( line[0] == '\n' ) {
// Check if line is only "\n", if yes, ignore the line
continue;
} else {
words[i] = malloc(sizeof(line) * sizeof(char));
if ( words[i] == NULL ) {
fputs("Unable to allocate Memory", stderr);
exit(1);
}
strcpy(words[i], line);
i ;
}
}
// Close file
fclose(wordlist);
char temp[101];
for (int i = 0; i < (length-1); i ) {
int lowest = i;
for (int j = i 1; j < length; j ) {
if (strcmp(words[j], words[lowest]) < 0) {
lowest = j;
}
}
if (lowest != i) {
strcpy(temp, words[i]);
words[i] = words[lowest];
free(words[lowest]);
words[lowest] = malloc(sizeof(temp) * sizeof(char));
if ( words[lowest] == NULL ) {
fputs("Unable to allocate Memory", stderr);
exit(1);
}
strcpy(words[lowest], temp);
}
}
// Print out array
fputs("--- ARRAY ---\n\n", stdout);
for (int i = 0; i < c; i ) {
fputs(words[i], stdout);
}
exit(0);
}
uj5u.com熱心網友回復:
排序演算法的上限是length,這是不正確的,輸入行緩沖區length的大小也是如此。
for (int i = 0; i < (length-1); i ) {
上限應該i來自這里的外部范圍,因為它會在向陣列中添加新行時遞增:
strcpy(words[i], line);
i ;
這個上限
for (int i = 0; i < c; i ) {
也應該更改,因為有效行數可能與預期行數不匹配。
完成后不要忘記釋放記憶體。
這兩行很快造成記憶體泄漏(原始指標值words[i]丟失),然后設定了釋放后使用錯誤,因為新值與被釋放words[i]的指標值相同words[lowest]。
words[i] = words[lowest];
free(words[lowest]);
這里不需要額外的緩沖區、(取消)分配和字串復制。例如,如果您對整數陣列進行排序,只需交換指標值即可。
char *tmp = words[i];
words[i] = words[lowest];
words[lowest] = tmp;
這是一個常見的粗略示例,沒有錯誤處理,使用strdup. 它應該說明交換指標值,并確定陣列的長度。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAX_LINES 256
int main(void) {
char line[4096];
char **lines = malloc(sizeof *lines * MAX_LINES);
size_t len = 0;
while (len < MAX_LINES && fgets(line, sizeof line, stdin))
lines[len ] = strdup(line);
for (size_t i = 0; i < len - 1; i ) {
size_t lowest = i;
for (size_t j = i 1; j < len; j )
if (strcmp(lines[j], lines[lowest]) < 0)
lowest = j;
if (lowest != i) {
char *tmp = lines[i];
lines[i] = lines[lowest];
lines[lowest] = tmp;
}
}
for (size_t i = 0; i < len; i ) {
printf("%s", lines[i]);
free(lines[i]);
}
free(lines);
}
stdin:
one
two
hello
foo
world
^D
stdout:
foo
hello
one
two
world
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/470621.html
